웹 서버

클라이언트(브라우저)의 HTTP 요청을 받아 정적 콘텐츠(HTML, CSS, JS, 이미지)를 제공하고, 동적 요청은 WAS로 전달하는 역할을 하는 서버 소프트웨어입니다.

핵심 개념

항목내용
역할정적 콘텐츠 제공, 리버스 프록시, 로드 밸런싱, SSL 처리
프로토콜HTTP / HTTPS
대표 소프트웨어Nginx, Apache HTTP Server
처리 대상HTML, CSS, JS, 이미지, 동영상 등 이미 만들어진 파일

웹 서버의 역할

역할설명
정적 콘텐츠 제공HTML, CSS, JS, 이미지 등 파일을 그대로 반환
리버스 프록시클라이언트 요청을 WAS로 중계
로드 밸런싱여러 WAS에 요청을 분배
SSL 종료HTTPS 암호화/복호화를 웹 서버에서 처리
캐싱자주 요청되는 리소스를 캐시하여 응답 속도 향상
압축gzip/brotli 압축으로 전송 크기 감소
보안접근 제어, DDoS 방어, 요청 필터링
로깅접근 로그, 에러 로그 기록

웹 서버의 동작 방식

클라이언트 (브라우저)
    │
    │  GET /index.html
    │  GET /api/users
    ▼
┌──────────────────────────────────────┐
│          Web Server (Nginx)           │
│                                      │
│  ① 요청 수신 (80/443 포트)            │
│  ② 요청 경로 확인                     │
│     │                                │
│     ├── /index.html → 정적 파일?      │
│     │   → Yes → 파일 시스템에서 읽어   │
│     │           클라이언트에 직접 반환   │
│     │                                │
│     └── /api/users → 동적 요청?       │
│         → Yes → WAS(Tomcat)로 전달    │
│                    │                  │
└────────────────────┼──────────────────┘
                     ▼
┌──────────────────────────────────────┐
│           WAS (Tomcat)                │
│  비즈니스 로직 실행 → DB 조회 → 응답 생성 │
└──────────────────────────────────────┘

Nginx vs Apache

항목NginxApache
아키텍처이벤트 기반 (비동기, Non-Blocking)프로세스/스레드 기반
동시 접속수만 동시 연결 처리 가능연결당 프로세스/스레드 → 제한적
메모리 사용적음 (고정적)많음 (연결 수에 비례 증가)
정적 파일 성능매우 빠름빠름
설정 방식설정 파일 기반.htaccess 지원 (디렉토리별 설정)
모듈컴파일 시 포함런타임 동적 로딩 가능
점유율현재 1위레거시에서 많이 사용
[Apache — 프로세스/스레드 기반]
요청 1 → 스레드 1 (전담)
요청 2 → 스레드 2 (전담)
요청 3 → 스레드 3 (전담)
  ...
요청 1000 → 스레드 1000 (메모리 부족 가능)

[Nginx — 이벤트 기반]
             ┌── 요청 1
워커 프로세스 ─┼── 요청 2
 (1~수 개)   ├── 요청 3     ← 하나의 워커가
             ├── ...          수천 연결을 비동기로 처리
             └── 요청 10000
동시 접속 수 증가에 따른 메모리 사용:

메모리
  ↑
  │         Apache
  │        ╱
  │      ╱
  │    ╱
  │  ╱──────────── Nginx (거의 일정)
  │╱
  └────────────────────→ 동시 접속 수

리버스 프록시

웹 서버가 클라이언트와 WAS 사이에서 중개자(Proxy) 역할을 합니다.

[리버스 프록시 없이 — WAS 직접 노출]
클라이언트 ──→ WAS (Tomcat:8080)
  → 보안 취약, 정적 파일 처리 비효율, 로드 밸런싱 불가

[리버스 프록시 있을 때]
클라이언트 ──→ Nginx (80/443) ──→ WAS (Tomcat:8080)
  → WAS가 외부에 노출되지 않음
  → Nginx가 정적 파일, SSL, 로드 밸런싱 처리
장점설명
보안WAS의 IP/포트를 외부에 숨김
SSL 종료Nginx에서 HTTPS 처리 → WAS는 HTTP로 통신
로드 밸런싱여러 WAS에 요청 분배
캐싱응답을 캐시하여 WAS 부하 감소
장애 대응WAS 장애 시 에러 페이지 반환

로드 밸런싱

                      ┌─── WAS 1 (Tomcat:8081)
클라이언트 → Nginx ────┼─── WAS 2 (Tomcat:8082)
                      └─── WAS 3 (Tomcat:8083)
알고리즘설명
Round Robin순서대로 돌아가며 분배 (기본값)
Least Connections현재 연결이 가장 적은 서버에 분배
IP Hash클라이언트 IP 기준으로 항상 같은 서버에 분배
Weighted서버 성능에 따라 가중치 부여

Nginx 설정 예시

# nginx.conf

# 로드 밸런싱 설정
upstream backend {
    server localhost:8081;
    server localhost:8082;
    server localhost:8083;
}

server {
    listen 80;
    server_name example.com;

    # HTTPS 리다이렉트
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;

    # SSL 설정
    ssl_certificate     /etc/ssl/cert.pem;
    ssl_certificate_key /etc/ssl/key.pem;

    # 정적 파일 → Nginx가 직접 처리
    location /static/ {
        root /var/www/html;
        expires 30d;                    # 브라우저 캐시 30일
        add_header Cache-Control "public";
    }

    # 동적 요청 → WAS로 전달 (리버스 프록시)
    location /api/ {
        proxy_pass http://backend;      # upstream으로 로드 밸런싱
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # gzip 압축
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;
}

SSL 종료 (SSL Termination)

[SSL 종료 — 웹 서버에서 처리]

클라이언트 ──HTTPS(암호화)──→ Nginx ──HTTP(평문)──→ WAS
                             ↑
                        여기서 복호화
                        (SSL 종료)

장점:
  - WAS는 암호화/복호화 부담 없음
  - 인증서 관리를 Nginx에서 일괄 처리
  - WAS가 여러 대여도 인증서는 Nginx 하나에만 설치

Web Server가 없으면?

[Web Server 없이 WAS만 운영]

클라이언트 ──→ Tomcat (8080)
  │
  ├── 정적 파일도 Tomcat이 처리 → 비효율적
  ├── SSL도 Tomcat이 처리 → CPU 부담
  ├── 로드 밸런싱 불가 → 단일 서버
  ├── WAS 장애 시 → 아무 응답 없음
  └── WAS가 외부에 직접 노출 → 보안 취약

[Web Server + WAS 분리 구성]

클라이언트 ──→ Nginx (80/443) ──→ Tomcat (8080)
  │
  ├── 정적 파일 → Nginx가 빠르게 처리
  ├── SSL → Nginx에서 종료
  ├── 로드 밸런싱 → 여러 WAS에 분배
  ├── WAS 장애 시 → Nginx가 에러 페이지 반환
  └── WAS가 외부에 노출되지 않음 → 보안 강화

Spring Boot에서의 웹 서버

// Spring Boot는 WAS(Tomcat)가 내장되어 있어
// 개발 시에는 웹 서버 없이 단독 실행 가능

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        // 내장 Tomcat이 8080에서 시작
        // 개발 환경: Tomcat 단독으로 충분
        // 운영 환경: 앞에 Nginx를 두는 것이 일반적
    }
}
개발 환경:
  클라이언트 → Tomcat (8080) — 간편하게 개발

운영 환경:
  클라이언트 → Nginx (80/443) → Tomcat (8080) — 보안, 성능, 안정성

CSLOG에서 보기