본문으로 건너뛰기
Advertisement

HTTP 프록시 연동 — proxy_pass 완전 정복

Nginx에서 proxy_pass로 Tomcat을 연동하는 것은 가장 표준적인 방법입니다. 헤더 전달, 실제 IP 전달, 업스트림 정의까지 실무에서 반드시 알아야 할 설정을 다룹니다.


기본 proxy_pass 설정

server {
listen 80;
server_name example.com;

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

이것만으로도 Nginx가 Tomcat에 요청을 전달합니다. 하지만 실무에서는 헤더 전달, 타임아웃, 버퍼 등 추가 설정이 필요합니다.


upstream 블록으로 백엔드 정의

upstream 블록으로 Tomcat을 명시적으로 정의하면 가독성이 높아지고 여러 인스턴스로 확장하기 쉽습니다.

# /etc/nginx/conf.d/upstream.conf
upstream tomcat_backend {
server 127.0.0.1:8080;
keepalive 32; # 업스트림 keep-alive 연결 유지 수
}
# /etc/nginx/sites-available/myapp.conf
server {
listen 443 ssl;
server_name example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

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

필수 프록시 헤더 설정

# /etc/nginx/snippets/proxy-headers.conf
# 이 파일을 include로 재사용

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_set_header X-Forwarded-Port $server_port;

# HTTP 버전 업그레이드 (keepalive 사용 시 필수)
proxy_http_version 1.1;
proxy_set_header Connection "";
헤더Tomcat에서의 역할
Host$host가상 호스트 매칭
X-Real-IP$remote_addr실제 클라이언트 IP
X-Forwarded-For$proxy_add_x_forwarded_for프록시 체인 IP 목록
X-Forwarded-Proto$scheme원래 프로토콜(http/https)

실제 IP 전달 (RemoteIpValve)

Tomcat이 request.getRemoteAddr()에서 Nginx IP(127.0.0.1) 대신 실제 클라이언트 IP를 반환하도록 설정합니다.

Nginx 설정

# X-Forwarded-For 헤더 정리 (신뢰할 수 없는 IP 제거)
set_real_ip_from 127.0.0.1; # Nginx 자신
set_real_ip_from 10.0.0.0/8; # 내부 네트워크
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

Tomcat server.xml 설정

<!-- Host 태그 안에 추가 -->
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="x-forwarded-for"
protocolHeader="x-forwarded-proto"
internalProxies="127\.0\.0\.1|10\.\d+\.\d+\.\d+|192\.168\.\d+\.\d+"/>

이렇게 하면:

  • request.getRemoteAddr() → 실제 클라이언트 IP 반환
  • request.isSecure() → Nginx가 HTTPS로 받았다면 true 반환
  • 로그에 실제 클라이언트 IP 기록

완전한 프록시 설정 예시

upstream tomcat_backend {
server 127.0.0.1:8080;
keepalive 32;
}

server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl http2;
server_name example.com;

# SSL 설정
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

# 실제 IP 복원
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

# 클라이언트 요청 설정
client_max_body_size 50m; # 파일 업로드 크기 제한
client_body_buffer_size 128k;

# Tomcat으로 프록시
location / {
proxy_pass http://tomcat_backend;

# 필수 헤더
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_set_header X-Forwarded-Port $server_port;

# HTTP/1.1 + keepalive
proxy_http_version 1.1;
proxy_set_header Connection "";

# 타임아웃
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;

# 버퍼
proxy_buffering on;
proxy_buffer_size 16k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
}

# 에러 페이지
error_page 502 503 504 /error/5xx.html;
location = /error/5xx.html {
root /var/www/myapp;
internal;
}

# 접근 로그
access_log /var/log/nginx/myapp_access.log combined;
error_log /var/log/nginx/myapp_error.log warn;
}

proxy_pass URI 처리 주의사항

proxy_pass에 URI를 포함하느냐 여부에 따라 동작이 달라집니다.

# URI 없이 — location 경로 그대로 전달
location /app/ {
proxy_pass http://127.0.0.1:8080;
# /app/foo → http://127.0.0.1:8080/app/foo
}

# URI 포함 — location 경로를 대체
location /app/ {
proxy_pass http://127.0.0.1:8080/;
# /app/foo → http://127.0.0.1:8080/foo (경로 변환)
}

# API 경로 변환 예시
location /api/ {
proxy_pass http://127.0.0.1:8080/api/v1/;
# /api/users → http://127.0.0.1:8080/api/v1/users
}

특수 경로 처리

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; # WebSocket 연결 유지
proxy_send_timeout 3600s;
}

SSE(Server-Sent Events) 프록시

location /events/ {
proxy_pass http://tomcat_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off; # SSE는 버퍼링 비활성화 필수
proxy_cache off;
proxy_read_timeout 3600s;
}

파일 업로드 경로

location /upload/ {
proxy_pass http://tomcat_backend;
client_max_body_size 500m; # 대용량 파일 업로드
proxy_request_buffering off; # 청크 전송 지원
proxy_read_timeout 600s; # 업로드 시간 여유
}

프록시 설정 검증

# Nginx 설정 검증
sudo nginx -t
# nginx: configuration file /etc/nginx/nginx.conf test is successful

# 리로드 (무중단)
sudo nginx -s reload

# 프록시 연결 테스트
curl -v https://example.com/api/test
# X-Forwarded-For, X-Forwarded-Proto 헤더 확인

# Tomcat에서 실제 IP 확인
curl -s https://example.com/debug/ip # 앱에서 request.getRemoteAddr() 반환

Summary

설정내용
업스트림upstream 블록 + keepalive 32
필수 헤더Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto
HTTP 버전proxy_http_version 1.1 + Connection "" (keepalive 필수)
실제 IPNginx: real_ip_header + Tomcat: RemoteIpValve
WebSocketUpgrade: $http_upgrade + Connection: upgrade
SSEproxy_buffering off + proxy_cache off
Advertisement