infra
Platform

모듈 맵

[Infra Ops] Web Server와 WAS 미들웨어 구조의 이해

0 / 52 완료

펼치기
0 / 52 완료0%

Infra-ops · 09 / 52

[Infra Ops] Web Server와 WAS 미들웨어 구조의 이해

Nginx(Web Server)와 Tomcat(WAS)의 근본적인 차이를 이해하고, 역방향 프록시(Reverse Proxy)로 연동하는 실무 웹 서비스 아키텍처를 구축합니다.

🚨INCIDENT ALERT
HIGH

"마케팅 팀에서 이벤트를 진행하자마자 서버가 마비되었습니다. CPU 점유율은 낮은데 동적 API 서버가 응답을 안 해요!"

원인을 분석해보니, 이벤트 페이지에 삽입된 대용량 고화질 이미지 파일들을 사용자들이 다운로드하면서 문제가 생겼습니다. 동적 자바 비즈니스 로직을 수행해야 할 WAS의 스레드 풀 200개가 이미지 파일을 디스크에서 읽어 보내는 '정적 전송 대기 상태'로 모두 잠겨버린 것입니다.

만약 앞단에 가볍고 분주하게 움직이는 Web Server(Nginx)를 두고 이미지 전송을 전담시킨 뒤, 진짜 동적 연산(API)만 WAS(Tomcat)로 흘려보내는 Web-WAS 2-Tier 구조를 구축했다면, 단 한 대의 서버로도 마비 없이 수천 명의 트래픽을 소화했을 것입니다.

이번 챕터에서 배울 것
  • 1웹 서버(Nginx)와 웹 애플리케이션 서버(Tomcat)의 구조적 차이 비교
  • 2이벤트 기반(Event-driven)과 멀티스레드 스레드 풀(Thread Pool) 동작 모델의 이해
  • 3리버스 프록시(Reverse Proxy) 연동 필요성과 설정 방법
  • 4Nginx 가상 호스트 및 Tomcat 연동용 proxy_pass 실습
  • 5실무 필수 헤더: 클라이언트 실제 IP(X-Real-IP) 전송 설정
  • 6502 Bad Gateway와 504 Gateway Timeout 장애 패턴 및 분석
실습 환경 준비
Nginx 웹 서버 설치 (Ubuntu)
sudo apt-get update && sudo apt-get install -y nginx
Nginx 정상 구동 상태 확인
sudo systemctl status nginx
Nginx 구문 유효성 검사
sudo nginx -t

Web-WAS의 핵심 분리 철학

💡개념

안내원 Nginx와 요리사 Tomcat — 왜 역할을 나눠야 하는가

WAS(Tomcat)만 단독으로 운영하면 처음엔 잘 돌아가는 것처럼 보입니다. 그런데 이벤트 트래픽이 몰리거나 대용량 파일 요청이 겹치는 순간, 스레드 풀 200개가 이미지 전송 대기에 모두 묶여 정작 핵심인 API 처리가 멈춰버립니다. 이 문제를 구조적으로 해결하는 방법이 Web-WAS 분리입니다. 정적 파일은 Nginx가 초고속으로 처리하고, Tomcat은 오직 비즈니스 로직에만 집중하게 만드는 것이 핵심입니다.

Web-WAS 분리 구조 — Nginx가 정적 파일을 처리하고 동적 요청만 Tomcat으로 전달하는 흐름

Nginx (Web Server) = 카페 접수원

Nginx는 이벤트 루프(Event Loop)를 사용하는 비동기 구조입니다. CPU 코어당 1개의 Worker 프로세스만으로 수만 건의 정적 요청을 동시에 처리할 수 있습니다. 파일 I/O가 발생해도 스레드를 블로킹하지 않고 이벤트 큐에서 관리하기 때문에 메모리와 CPU 소모가 극단적으로 적습니다.

Tomcat (WAS) = 전문 요리사

Tomcat은 요청 1개당 JVM 스레드 1개를 완전히 점유하는 Thread-per-request 구조입니다. 스레드 풀이 최대 200개로 설정된 상태에서 200개의 느린 요청이 유입되면, 201번째 요청은 스레드가 릴리즈될 때까지 대기하다 타임아웃됩니다.

[인터넷 요청]
   │
   ▼
┌────────────────────────────────┐
│  Nginx Web Server (Port 80)    │  ← HTML, CSS, Image 직접 처리
└────────────────────────────────┘
   │ proxy_pass (동적 요청만)
   ▼
┌────────────────────────────────┐
│  Tomcat WAS (Port 8080)        │  ← 비즈니스 로직, DB 접근 집중
└────────────────────────────────┘

Web Server vs WAS — 정적/동적 분리 이유

Nginx 리버스 프록시 연동 실습

1Nginx 가상 호스트 설정 파일 생성

기존 기본 설정을 비활성화하고, 프록시 헤더를 정확히 전달하는 전용 서버 블록을 작성합니다.

로컬 터미널
# 기본 설정 비활성화
sudo rm -f /etc/nginx/sites-enabled/default

# 새로운 전용 설정 파일 생성
sudo tee /etc/nginx/sites-available/infra-platform.conf > /dev/null <<'EOF'
server {
    listen 80;
    server_name localhost;

    # 정적 리소스는 Nginx가 직접 처리
    location /static/ {
        alias /var/www/infra-platform/static/;
        expires 30d;
        access_log off;
    }

    # 동적 API 요청은 WAS(Tomcat)로 중계
    location / {
        proxy_pass http://127.0.0.1:8080;
        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;
        proxy_connect_timeout 10s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
    }
}
EOF
sudo rm -f /etc/nginx/sites-enabled/default && sudo tee /etc/nginx/sites-available/infra-platform.conf > /dev/null
🔍설정 파일 생성 확인
  • /etc/nginx/sites-available/infra-platform.conf 파일이 생성됐는가
  • 파일 내용에 proxy_pass http://127.0.0.1:8080; 라인이 있는가
  • proxy_set_header X-Real-IP $remote_addr; 헤더 설정이 포함됐는가
2가상 호스트 활성화 및 설정 검증

심볼릭 링크로 설정을 활성화하고 문법 오류가 없는지 검사한 뒤 리로드합니다.

로컬 터미널
# 심볼릭 링크 생성
sudo ln -sf /etc/nginx/sites-available/infra-platform.conf /etc/nginx/sites-enabled/

# 구문 검사
sudo nginx -t
# 성공 출력: nginx: configuration file /etc/nginx/nginx.conf test is successful

# 무중단 설정 리로드
sudo systemctl reload nginx
sudo ln -sf /etc/nginx/sites-available/infra-platform.conf /etc/nginx/sites-enabled/ && sudo nginx -t
🔍프록시 패킷 흐름 및 실주소 검증

리버스 프록시가 정상 동작하는지 두 가지 방법으로 확인합니다.

로컬 또는 서버
# 1. HTTP 응답 헤더 확인 — Server: nginx 가 보이면 정상
curl -I http://localhost

# 2. WAS 로그에 X-Real-IP 헤더가 전달되는지 확인
# Tomcat access log에 %{X-Forwarded-For}i 패턴이 있어야 실제 IP 기록됨
sudo tail -20 /opt/tomcat/logs/localhost_access_log.*.txt
  • Server: nginx 헤더가 응답에 보이면 Nginx가 앞단에서 동작 중
  • WAS 로그에 127.0.0.1 대신 실제 클라이언트 IP가 찍히면 X-Real-IP 전달 성공
  • 502 Bad Gateway가 나오면 8080 포트에 WAS가 기동 중인지 확인 필요
💼
실무 맥락
현업 패턴

실제 업무에서 이 지식이 쓰이는 상황:

주니어 인프라 엔지니어로 입사하면 시니어가 툭 던지는 두 가지 지시가 있습니다.

"Nginx max_connections랑 Worker 프로세스 설정 좀 봐줘"

최대 동시 접속 수는 worker_processes × worker_connections입니다. lscpu로 CPU 코어 수를 확인하고 worker_processes auto로 설정합니다. ulimit -n(파일 디스크립터 한계)보다 worker_connections가 크면 기동 시 에러가 나므로 반드시 확인합니다.

"WAS 실주소 로깅 똑바로 되고 있는지 확인해봐"

Nginx에 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for가 들어있는지 확인합니다. Tomcat의 server.xml AccessLogValve 포맷 패턴에 %{X-Forwarded-For}i가 지정되어 있어야 클라이언트 실제 IP가 로그에 남습니다. 테스트 요청을 직접 쏴서 로그에 실제 IP가 찍히는지 증빙합니다.

다음 모듈에서는 Web/WAS/DB를 실제 네트워크 망으로 분리하는 3-Tier 이중화 구조를 다룹니다.

지식 확인

퀴즈 — 4문제

Q1

정적 자원(HTML, CSS, Image)만 처리할 때 Nginx(Web Server)가 Tomcat(WAS)보다 압도적으로 유리한 기술적 이유는 무엇입니까?

Q2

Nginx 설정에서 'proxy_pass http://127.0.0.1:8080;'을 추가했습니다. 이 설정의 정확한 역할을 가장 잘 설명한 것은?

Q3

Nginx를 거쳐 WAS에 도달했을 때, WAS의 애플리케이션 로그에 실제 클라이언트 IP가 아닌 '127.0.0.1'만 남는 문제가 생겼습니다. 이 현상의 근본 원인과 해결책은 무엇입니까?

Q4

Nginx로 웹 애플리케이션 접근 시 '502 Bad Gateway' 에러 페이지가 노출되었습니다. 이 에러 코드가 지닌 가장 유력한 의미는 무엇입니까?

0 / 4 답변

🧪 실습으로 확인하기

Nginx 설치 및 기동

초급

Linux 서버에 Nginx를 설치하고 systemd 서비스로 등록하여 80포트에서 응답하는 상태까지 만든다.

30📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요

infra-ops중급 · 55
[Infra Ops] HTTP 요청이 서버에 도달하기까지의 전체 흐름
인프라 서비스 운영 트랙 계속
linux입문 · 30
[Linux] 개발자가 왜 리눅스 서버와 커맨드라인을 반드시 배워야 하는가
Linux 트랙 시작점