본문으로 건너뛰기
Advertisement

업스트림과 리버스 프록시 기초

Nginx의 리버스 프록시 기능은 클라이언트 요청을 백엔드 서버(Tomcat 등)로 전달하는 핵심 역할을 합니다. proxy_pass, 헤더 전달, 버퍼 설정, 타임아웃을 올바르게 구성해야 프록시 구성이 안정적으로 동작합니다.


리버스 프록시 개념

리버스 프록시(Reverse Proxy) 는 클라이언트와 백엔드 서버 사이에서 요청을 중계하는 서버입니다. 클라이언트는 Nginx에만 연결하고, 백엔드 서버(Tomcat 등)의 존재를 모릅니다.

[클라이언트]
│ GET /api/products HTTP/1.1
│ Host: example.com

[Nginx: 리버스 프록시]
│ GET /api/products HTTP/1.1
│ Host: example.com
│ X-Real-IP: 클라이언트 IP

[Tomcat: 백엔드 서버]

└─ 응답 → Nginx → 클라이언트

proxy_pass 기본 설정

server {
listen 80;
server_name example.com;

# /api/ 하위 요청을 Tomcat으로 전달
location /api/ {
proxy_pass http://127.0.0.1:8080;
}
}

proxy_pass에서 URI 처리 차이

proxy_pass 뒤에 URI를 포함하느냐에 따라 전달되는 경로가 달라집니다.

# 케이스 1: URI 없음 — location의 경로가 그대로 전달됨
location /api/ {
proxy_pass http://127.0.0.1:8080;
}
# GET /api/users → 백엔드: GET /api/users

# 케이스 2: URI 있음 (/로만 끝남) — location 경로가 /로 교체됨
location /api/ {
proxy_pass http://127.0.0.1:8080/;
}
# GET /api/users → 백엔드: GET /users (/api/가 /로 교체)

# 케이스 3: URI 있음 (경로 포함) — location 경로가 해당 경로로 교체됨
location /api/ {
proxy_pass http://127.0.0.1:8080/app/;
}
# GET /api/users → 백엔드: GET /app/users (/api/가 /app/로 교체)

헤더 전달 설정

Nginx가 백엔드에 요청을 전달할 때 기본적으로 일부 헤더는 제거됩니다. 클라이언트의 실제 IP, 원본 도메인 등을 백엔드에서 알 수 있도록 헤더를 추가해야 합니다.

location / {
proxy_pass http://127.0.0.1:8080;

# 원본 Host 헤더 전달 (Tomcat이 server_name을 알 수 있도록)
proxy_set_header Host $host;

# 클라이언트 실제 IP 전달
proxy_set_header X-Real-IP $remote_addr;

# 프록시 체인의 모든 IP 목록 (기존 X-Forwarded-For에 추가)
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# 원본 프로토콜 전달 (http 또는 https)
proxy_set_header X-Forwarded-Proto $scheme;

# 프록시 연결임을 나타내는 헤더 (일부 앱에서 사용)
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}

Spring Boot에서 X-Forwarded-For 활용

Spring Boot 앱에서 실제 클라이언트 IP를 얻으려면:

// application.yml
server:
forward-headers-strategy: native

// 또는 Spring Security와 함께
// WebMvcConfigurer에서 RemoteIpFilter 등록

upstream 블록 — 백엔드 서버 그룹 정의

여러 백엔드 서버를 관리하거나, 이름으로 참조하고 싶을 때 upstream 블록을 사용합니다.

http {
# 백엔드 서버 그룹 정의
upstream tomcat_backend {
server 127.0.0.1:8080;
}

server {
location /api/ {
proxy_pass http://tomcat_backend;
}
}
}

upstream 공통 설정 분리

반복되는 proxy 설정은 별도 파일로 분리하는 것이 좋습니다.

# /etc/nginx/conf.d/proxy-params.conf
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_http_version 1.1;
proxy_set_header Connection "";

# 사용 시
location / {
proxy_pass http://tomcat_backend;
include /etc/nginx/conf.d/proxy-params.conf;
}

버퍼 설정

Nginx는 백엔드에서 받은 응답을 버퍼에 담았다가 클라이언트에 전달합니다. 버퍼 설정이 적절하지 않으면 메모리 낭비나 성능 저하가 발생합니다.

location / {
proxy_pass http://tomcat_backend;

# 응답 버퍼링 활성화 (기본: on)
# off면 백엔드 응답을 버퍼 없이 즉시 클라이언트에 전달
proxy_buffering on;

# 응답 헤더 읽기용 버퍼 크기 (기본: 1 4k|8k)
proxy_buffer_size 4k;

# 응답 본문 버퍼 (개수 × 크기)
proxy_buffers 8 16k;

# 클라이언트에 전달 전 버퍼링 최대 크기
proxy_busy_buffers_size 32k;

# 임시 파일로 스필할 최대 크기 (버퍼 초과 시)
proxy_max_temp_file_size 1024m;
}

스트리밍 응답 (SSE, WebSocket)

스트리밍 또는 실시간 응답의 경우 버퍼링을 비활성화해야 즉각 전달됩니다.

# Server-Sent Events (SSE)
location /api/stream {
proxy_pass http://tomcat_backend;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s; # 1시간 (SSE 연결 유지)
add_header X-Accel-Buffering no;
}

# WebSocket
location /ws/ {
proxy_pass http://tomcat_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}

타임아웃 설정

location / {
proxy_pass http://tomcat_backend;

# Nginx가 백엔드에 TCP 연결을 맺는 최대 대기 시간
proxy_connect_timeout 10s;

# Nginx가 백엔드에 요청 전송 완료까지 최대 대기 시간
proxy_send_timeout 60s;

# Nginx가 백엔드 응답 읽기 완료까지 최대 대기 시간
# 이 시간 내 응답이 없으면 504 Gateway Timeout 반환
proxy_read_timeout 60s;
}
타임아웃기본값설명
proxy_connect_timeout60s백엔드 TCP 연결 대기
proxy_send_timeout60s요청 전송 대기
proxy_read_timeout60s응답 수신 대기

HTTP 버전과 Keep-Alive

Nginx와 백엔드 사이에 HTTP/1.1 Keep-Alive를 유지하면 TCP 연결을 재사용하여 성능이 향상됩니다.

upstream tomcat_backend {
server 127.0.0.1:8080;
keepalive 32; # 유휴 Keep-Alive 연결 최대 32개 유지
}

location /api/ {
proxy_pass http://tomcat_backend;
proxy_http_version 1.1; # HTTP/1.1 사용 (Keep-Alive 필요)
proxy_set_header Connection ""; # Connection: close 헤더 제거
}

에러 처리 및 백업 서버

upstream tomcat_backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081 backup; # 메인 서버 다운 시 사용

# 3번 실패하면 30초간 비활성화
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
}

server {
location / {
proxy_pass http://tomcat_backend;
proxy_next_upstream error timeout http_502 http_503;
proxy_intercept_errors on;
error_page 502 503 504 /maintenance.html;
}
}

정리

설정 항목지시어핵심 포인트
요청 전달proxy_passURI 포함 여부에 따라 경로 처리 다름
헤더 전달proxy_set_headerHost, X-Real-IP, X-Forwarded-For 필수
버퍼링proxy_buffering스트리밍은 off, 일반 응답은 on
타임아웃proxy_read_timeout느린 API에 맞게 조정
Keep-Alivekeepalive + HTTP/1.1TCP 재사용으로 성능 향상
Advertisement