Nginx 리버스 프록시는 Nginx가 80 또는 443 포트에서 요청을 먼저 받고, 내부 애플리케이션으로 대신 전달하는 설정이에요. 보통 proxy_pass, proxy_set_header, proxy_read_timeout만 정확히 잡아도 기본 동작은 돼요. 2025년에는 HTTPS 종료, Docker 서비스 이름 연결, WebSocket 헤더 전달, 그리고 502·504·413 오류 점검까지 같이 설정하는 경우가 많아요.
Nginx 리버스 프록시가 무엇인지
AI로 생성된 이미지입니다
AI로 생성된 이미지입니다리버스 프록시는 클라이언트가 직접 백엔드 서버에 붙지 않고 Nginx가 요청을 대신 받아 내부 웹서버로 전달하는 구조예요. 이 방식은 HTTPS 종료, 로드밸런싱, 캐시, 압축, 경로 기반 라우팅에 자주 쓰여요. 2025년 배포 문맥에서는 메인라인 1.29.x와 stable 1.28.x 같은 버전 구분도 함께 보는데, 운영 환경에서는 기능보다 배포 정책과 패키지 지원 범위를 먼저 확인하는 편이 실무적이에요.
검색하는 사람이 실제로 궁금한 점은 보통 하나예요. example.com으로 들어온 요청을 127.0.0.1:3000이나 Docker 서비스 이름 같은 내부 주소로 안전하게 넘기고, 원래 요청의 Host, IP, HTTPS 여부를 백엔드가 알게 만드는 방법이에요. 이때 많이 쓰는 헤더가 Host, X-Forwarded-For, X-Forwarded-Proto이고, 백엔드도 프록시 뒤에 있다는 점을 인지하도록 맞춰야 해요.
Nginx 리버스 프록시를 설정하는 방법
AI로 생성된 이미지입니다기본 설정은 서버 블록 1개와 핵심 지시어 몇 개로 끝나요. 자주 쓰는 지시어는 proxy_pass, proxy_set_header, proxy_http_version, proxy_read_timeout, client_max_body_size예요. HTTPS를 앞단에서 종료하면 백엔드는 내부 HTTP로 단순하게 운영할 수 있고, 인증서는 2025년에도 Let’s Encrypt 자동 갱신 구성이 일반적이에요.
백엔드 주소를 정해요. 예를 들어 로컬 서버면
127.0.0.1:3000, Docker Compose면 서비스 이름app:3000처럼 적어요.Nginx
server블록에서listen 80;또는listen 443 ssl;을 선언해요.location /안에proxy_pass를 넣고,Host,X-Real-IP,X-Forwarded-For,X-Forwarded-Proto헤더를 전달해요.업로드가 있으면
client_max_body_size 20m;처럼 제한을 명시해요.응답이 오래 걸리는 API면
proxy_read_timeout 60s;또는 그 이상으로 조정해요.WebSocket이 있으면
proxy_http_version 1.1,Upgrade,Connection헤더를 추가해요.설정 저장 뒤
nginx -t로 문법 검사하고,systemctl reload nginx또는 컨테이너 재시작으로 반영해요.
server {
listen 80;
server_name example.com;
client_max_body_size 20m;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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_read_timeout 60s;
}
location /socket/ {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}경로 기반 프록시를 쓸 때는 /api와 /api/의 차이를 꼭 확인해야 해요. location 매칭 우선순위와 proxy_pass 뒤 슬래시 유무에 따라 upstream으로 전달되는 URI가 달라질 수 있기 때문이에요. 예를 들어 /api/users 요청이 백엔드에서는 /users가 되길 원하는지, 그대로 /api/users가 되길 원하는지 먼저 정하고 테스트해야 해요.
어떤 방식으로 설정할지 비교하는 기준
선택 기준은 기능보다 운영 조건이에요. 단일 앱 1개만 붙일지, /api와 /app처럼 경로를 나눌지, WebSocket까지 필요한지에 따라 설정이 달라져요. 최근에는 HTTP/2만 볼 것이 아니라 HTTP/3 지원 필요 여부도 같이 확인하는데, Nginx는 빌드 옵션과 OpenSSL 또는 QUIC 스택 조합에 따라 지원 범위가 달라져요.
| 방식 | 적합한 상황 | 핵심 설정 | 주의점 |
|---|---|---|---|
| 단일 백엔드 프록시 | Node.js 1개, 포트 3000 1개처럼 단순 배포 | location / + proxy_pass | Host, X-Forwarded-* 헤더 누락 시 앱 링크·로그가 어긋날 수 있어요 |
| 경로 기반 프록시 | /api, /admin, /app을 한 도메인으로 묶을 때 | 여러 location + 경로별 proxy_pass | 슬래시 유무와 rewrite 결과를 꼭 확인해야 해요 |
| WebSocket 포함 프록시 | 채팅, 알림, 실시간 대시보드가 있을 때 | proxy_http_version 1.1, Upgrade, Connection | 헤더 누락 시 101 전환이 실패할 수 있어요 |
| Docker/Compose 기반 프록시 | 컨테이너 IP가 자주 바뀌는 배포 | proxy_pass http://app:3000; | 서비스 이름 DNS를 써야 재시작 후에도 안정적이에요 |
설정할 때 자주 나는 오류
가장 흔한 오류는 502, 504, 413 세 가지예요. 이 세 코드는 대부분 Nginx 설정 1~2줄이나 백엔드 프로세스 상태에서 원인이 드러나요. 먼저 nginx -t, systemctl status nginx, 백엔드 포트 확인, 그리고 Nginx 에러 로그를 순서대로 보는 것이 2025년에도 가장 빠른 점검 루틴이에요.
| 오류 코드 | 먼저 볼 것 | 흔한 원인 | 바로 해볼 조치 |
|---|---|---|---|
| 502 Bad Gateway | 백엔드 프로세스와 포트 | 앱이 죽었거나 proxy_pass 주소가 틀림 | curl http://127.0.0.1:3000 또는 curl http://app:3000으로 직접 확인해요 |
| 504 Gateway Timeout | 응답 시간 | 앱 쿼리 지연, 외부 API 대기, 타임아웃 짧음 | proxy_read_timeout 60s 이상으로 늘리고 앱 로그 시간을 비교해요 |
| 413 Request Entity Too Large | 업로드 크기 | 기본 업로드 제한보다 파일이 큼 | client_max_body_size 20m 또는 필요한 크기로 조정해요 |
| WebSocket 연결 실패 | Upgrade 헤더 | proxy_http_version 1.1 또는 헤더 누락 | Upgrade, Connection 설정을 다시 넣어요 |
또 하나 많이 놓치는 부분은 백엔드 프레임워크 설정이에요. 예를 들어 Express, Django, Spring Boot 같은 앱이 프록시 뒤 환경을 모르면 HTTPS 링크를 HTTP로 만들거나 실제 클라이언트 IP 대신 127.0.0.1만 기록할 수 있어요. 이 경우 Nginx에서 X-Forwarded-Proto와 X-Forwarded-For를 넘기는 것만으로 끝나지 않고, 앱 쪽 신뢰 프록시 옵션도 함께 켜야 해요.
안정적으로 운영하기 위한 팁
운영 팁의 핵심은 설정을 짧게 유지하고 테스트를 분리하는 거예요. location /, /api/, /socket/처럼 역할별로 나누고, 각각에 필요한 헤더와 타임아웃만 넣으면 디버깅이 쉬워져요. Docker Compose를 쓰면 고정 IP 대신 서비스 이름 DNS를 upstream으로 쓰는 패턴이 널리 쓰이고, 컨테이너 재시작으로 IP가 바뀌어도 이름 해석으로 대응할 수 있어요.
HTTPS와 최신 프로토콜이 필요하면 요구사항을 먼저 적어두는 것이 좋아요. 단순 웹앱이면 HTTP/2와 SSL 종료만으로 충분한 경우가 많고, HTTP/3는 Nginx 빌드 방식과 QUIC 스택 조합에 따라 바로 켜지지 않을 수 있어요. 그래서 Nginx 버전, 패키지 출처, 인증서 갱신 방식, 백엔드 포트 목록을 배포 문서에 같이 남기면 다음 수정 때 시간을 줄일 수 있어요.
FAQ
Nginx 리버스 프록시에서 proxy_pass 뒤 슬래시는 왜 중요해요?
proxy_pass http://app:3000;와 proxy_pass http://app:3000/;는 전달되는 URI가 달라질 수 있어요. 특히 location /api/와 함께 쓰면 /api/users가 /users로 바뀌는지 유지되는지 차이가 생기므로 직접 요청 테스트를 해봐야 해요.
Docker Compose에서 localhost 대신 서비스 이름을 써야 하나요?
같은 Compose 네트워크 안에서는 app:3000처럼 서비스 이름을 쓰는 방식이 일반적이에요. 컨테이너 IP는 재시작 때 바뀔 수 있지만 서비스 이름 DNS는 계속 해석되기 때문이에요.
WebSocket 프록시는 일반 HTTP 프록시와 무엇이 달라요?
WebSocket은 proxy_http_version 1.1과 Upgrade, Connection 헤더가 필요해요. 이 둘이 빠지면 HTTP 요청은 될 수 있어도 WebSocket 핸드셰이크는 실패할 수 있어요.
502 Bad Gateway가 나올 때 가장 먼저 뭘 확인해야 하나요?
백엔드 프로세스가 실제로 떠 있는지와 proxy_pass 주소가 맞는지부터 확인해요. 예를 들어 127.0.0.1:3000 또는 app:3000에 curl이 되는지 보면 원인 범위를 빠르게 줄일 수 있어요.
리버스 프록시 앞단에서 HTTPS 종료를 하면 백엔드는 HTTP여도 되나요?
내부 네트워크 구조라면 그렇게 운영하는 경우가 많아요. Nginx가 443에서 SSL 종료를 하고, 백엔드는 내부 HTTP로 단순화할 수 있어요. 대신 X-Forwarded-Proto=https 같은 원래 요청 정보는 꼭 전달해야 해요.