웹 서버
클라이언트(브라우저)의 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
| 항목 | Nginx | Apache |
| 아키텍처 | 이벤트 기반 (비동기, 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) — 보안, 성능, 안정성