Back to posts
2026년 4월 23일

Nginx 502 Bad Gateway 에러 해결을 위한 역방향 프록시(Reverse Proxy) 및 타임아웃 설정 최적화

1. 프론트의 방패, 리버스 프록시 Nginx의 역할

현대 웹 아키텍처에서 유저의 브라우저가 Node.js, Spring Boot, Python Django 같은 백엔드 애플리케이션 서버(WAS)의 구동 포트(예: 8080, 3000)로 직접 다이렉트 통신하는 경우는 거의 없습니다. 그 앞단에는 반드시 아파치(Apache)나 엔진엑스(Nginx) 같은 리버스 프록시(Reverse Proxy) 서버가 거대한 방패이자 문지기처럼 버티고 서 있습니다. Nginx는 무거운 SSL 인증서 복호화 암호 연산, 악성 트래픽 차단, 수십 대의 서버로의 로드 밸런싱, 그리고 정적 파일(이미지, CSS, JS)의 캐싱 서빙 등을 대신 앞장서 처리해주며, 백엔드 서버가 온전히 핵심 비즈니스 로직 연산에만 집중할 수 있게 완벽히 보호해 줍니다.

그런데 무사히 배포를 마치고 도메인에 접속했을 때, 디자인된 예쁜 웹사이트 대신 무자비한 하얀 바탕의 502 Bad Gateway 화면이 뜬다면 시스템 인프라 내부망 어디선가 심각한 소통의 단절이 발생했다는 의미입니다. 이는 당신의 프론트엔드 클라이언트 코드가 잘못된 것이 아니라, 앞단의 Nginx가 뒷단의 백엔드 서버(Upstream)로 요청을 토스하려고 했으나 문전박대를 당했음을 암시하는 인프라 에러코드입니다.

2. 502 Bad Gateway vs 504 Gateway Timeout의 진실

에러 코드를 정확히 구분하여 원인을 파악하는 것이 인프라 디버깅의 첫걸음입니다.

502 Bad Gateway: 백엔드 서버 프로세스가 아예 죽어있거나(예: PM2 크래시, Docker 컨테이너 종료, Out of Memory), Nginx 설정 파일에 포트 번호를 잘못 매핑했거나, 내부망 방화벽(iptables, Security Group)이 가로막아 Nginx가 백엔드와 TCP 연결 소켓조차 맺지 못하는 상황입니다. 즉, "방문을 두드렸는데 안쪽에 사람이 아예 없는" 상태입니다. 서버에 접속해 netstat -tulpn이나 curl localhost:포트 명령어로 백엔드 프로세스가 제대로 돌고 있는지 확인하는 것이 가장 빠릅니다.

504 Gateway Timeout: Nginx가 백엔드에 성공적으로 연결하여 요청 파라미터를 전달했지만, 백엔드 서버가 무거운 연산(예: 수백만 건의 대용량 엑셀 다운로드, 인덱스가 깨진 복잡한 DB 쿼리, 무한 루프)을 하느라 묵묵부답으로 일관하는 상태입니다. Nginx는 무한정 기다리지 않고 기본적으로 설정된 타임아웃 시간(보통 60초)이 지나면 "기다리다 지쳤다, 더 이상 못 참겠다"라며 연결 소켓을 싹둑 잘라버리고 클라이언트 브라우저에게 504를 던집니다.

3. 프록시 튜닝과 버퍼(Buffer) 최적화 방어 전략

  • 1) 타임아웃 연장 세팅: 대용량 파일 업로드나 AI 연산, 블록체인 노드 동기화처럼 필연적으로 시간이 수 분 이상 오래 걸리는 API가 있다면 Nginx 설정(nginx.conf)의 location 블록에 들어가서 proxy_read_timeout 300;proxy_connect_timeout 300; 을 넉넉하게(300초 등) 늘려주어야 작업 중간에 연결이 강제로 끊기는 불상사를 방지할 수 있습니다.
  • 2) 프록시 버퍼 튜닝 (502 에러 방어): 백엔드 서버가 내려주는 응답(헤더 크기가 큰 JSON이나 대형 이미지)이 너무 거대할 경우 Nginx가 기본 할당된 메모리 버퍼에 이를 다 담지 못해 넘쳐버리며(Buffer overflow) 에러를 뱉기도 합니다. 이때는 proxy_buffer_size 128k;proxy_buffers 4 256k; 지시어의 용량을 키워주어 큰 페이로드를 스무스하게 소화하도록 메모리 인프라를 확장해 주어야 합니다.
  • 3) Keep-Alive 커넥션 재사용: Nginx와 백엔드 간의 내부 통신에서도 매번 TCP 연결을 맺고 끊는 3-way handshake를 반복하면 미세한 지연 시간 오버헤드가 발생합니다. upstream 블록 내부에 keepalive 32; 옵션을 부여하여 내부 소켓 연결 풀을 닫지 않고 재사용하게 만들면 대규모 트래픽에서 엄청난 레이턴시 개선 효과를 얻을 수 있습니다.

4. 자주 묻는 질문 (FAQ)

Q. PM2로 Node.js를 돌리고 있는데 자꾸 랜덤하게 하루에 한 번씩 502 에러가 튀어 나옵니다.

Node 애플리케이션 내부에서 로직 상 처리되지 않은 런타임 예외(Uncaught Exception)나 힙 메모리 누수(OOM)가 한계치에 다다라 프로세스가 뻗었을 확률이 99%입니다. PM2 데몬은 프로세스가 죽으면 0.1초 만에 즉시 재시작시켜 주지만, 그 프로세스가 재부팅되는 찰나의 순간에 Nginx로 들어온 유저 트래픽들은 연결할 백엔드 대상이 없어 502 에러를 정통으로 맞게 됩니다. 앱의 ~/.pm2/logs/error.log를 샅샅이 뒤져 크래시 원인을 찾아 고쳐야 근본 해결이 됩니다.

Q. AWS ALB(Application Load Balancer)를 쓸 때는 Nginx가 필요 없나요?

네, ALB가 Nginx의 핵심적인 리버스 프록시 역할(SSL 인증서 복호화 종료, 상태 점검, 헬스 체크, 로드 밸런싱)을 클라우드 레벨에서 완벽히 대체해 줍니다. 그래서 최신 ECS나 EKS 클라우드 아키텍처에서는 ALB 뒷단에 Nginx를 두지 않고, 곧바로 도커 컨테이너의 서비스 포트를 직접 물려버리는 구조가 아키텍처의 단순화 측면에서 널리 사랑받고 있습니다.


OMANGAZI 편집팀

최신 IT 기술, 오픈소스 AI 생태계, 그리고 모던 웹 개발 트렌드를 연구하고 분석합니다. 단순한 정보 전달을 넘어 개발자들의 실무에 도움이 되는 깊이 있는 인사이트를 제공합니다.

관련 글 보기