Nginx 502 Bad Gateway 에러 해결 완벽 가이드 Reverse Proxy 설정 점검 체크리스트

Nginx 502 Bad Gateway 에러는 리버스 프록시 환경에서 가장 빈번하게 마주치는 장애 중 하나입니다. 백엔드 서비스는 정상이라고 판단했는데 502가 발생한다면, 문제는 Nginx와 백엔드 사이의 통신 레이어에 있습니다. 이 글에서는 실전에서 검증된 원인 분석 체크리스트와 즉시 적용 가능한 해결 방법을 제시합니다.


Nginx 502 에러 10분 안에 해결하기 로그 분석과 타임아웃 설정 최적화




1. 502 에러의 핵심 원인 4가지

502 Bad Gateway는 Nginx가 upstream 서버(백엔드)로부터 유효하지 않은 응답을 받았을 때 발생합니다. 주요 원인은 다음과 같습니다.

  • 백엔드 프로세스 미동작: 가장 흔한 원인. 애플리케이션(Gunicorn, PHP-FPM, Spring Boot 등)이 실제로 실행되지 않았거나, 지정된 포트에서 리스닝하지 않는 경우
  • proxy_pass 설정 오류: 잘못된 IP, 포트, 또는 upstream 블록 이름을 참조하여 Nginx가 백엔드에 도달하지 못하는 경우
  • 소켓 권한 불일치: PHP-FPM이나 Gunicorn을 유닉스 소켓으로 연동할 때, 소켓 파일의 소유자/그룹이 Nginx 실행 유저와 일치하지 않아 Permission Denied 발생
  • 타임아웃 및 버퍼 부족: 백엔드 응답이 느리거나 대용량 응답을 처리할 때, Nginx의 기본 타임아웃/버퍼 설정이 부족하여 연결이 끊기는 경우

2. 빠른 진단 체크리스트

아래 순서대로 점검하면 대부분의 502 에러 원인을 10분 이내에 특정할 수 있습니다.

  1. 백엔드 프로세스 확인
    • sudo lsof -i :포트번호 또는 sudo netstat -nltp | grep 포트번호로 해당 포트가 LISTEN 상태인지 확인
    • systemd 서비스: sudo systemctl status gunicorn (또는 php-fpm, tomcat 등)
    • Docker/Kubernetes: kubectl get pods, docker ps로 컨테이너 상태 확인
  2. Nginx 설정 검증
    • sudo nginx -t로 문법 오류 확인
    • proxy_pass 지시어가 올바른 upstream 주소(http://127.0.0.1:8000, unix:/tmp/gunicorn.sock 등)를 가리키는지 확인
    • location 블록 내부에 proxy 관련 설정이 위치하는지 확인 (location 외부에 있으면 적용 안 됨)
  3. 소켓 권한 확인 (PHP-FPM, Gunicorn 유닉스 소켓 사용 시)
    • ls -l /var/run/php/php7.4-fpm.sock (또는 /tmp/gunicorn.sock) 파일의 소유자 확인
    • Nginx 실행 유저: ps aux | grep nginx로 확인 (보통 www-data 또는 nginx)
    • 불일치 시: /etc/php/7.4/fpm/pool.d/www.conf에서 listen.owner, listen.group을 Nginx 유저로 변경 후 sudo systemctl restart php7.4-fpm
  4. 로그 확인
    • Nginx 에러 로그: sudo tail -f /var/log/nginx/error.log
    • 백엔드 로그: tail -f nohup.out, journalctl -u gunicorn -f
    • "Connection refused", "Permission denied", "upstream timed out" 등의 키워드로 원인 특정

3. 실전 해결 방법

Case 1: PHP-FPM 소켓 권한 문제

EC2에서 chown -R ubuntu:ubuntu로 소유권을 변경한 후 502 발생. PHP-FPM 소켓은 기본적으로 www-data 소유이므로 Nginx(ubuntu 유저)가 접근 불가.

# /etc/php/7.4/fpm/pool.d/www.conf 수정
listen.owner = ubuntu
listen.group = ubuntu
listen.mode = 0660

# 재시작
sudo systemctl restart php7.4-fpm
sudo systemctl restart nginx

Case 2: proxy_pass 및 버퍼 설정 오류

location 블록 외부에 proxy_buffer 설정을 두거나, proxy_pass 경로가 잘못된 경우.

location /api/ {
    proxy_pass http://127.0.0.1:8000;  # 실제 백엔드 포트 확인 필수
    proxy_buffer_size 16k;
    proxy_buffers 8 16k;
    proxy_busy_buffers_size 32k;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;
    proxy_connect_timeout 75s;
}

주의: proxy_buffer 관련 설정은 반드시 location 블록 내부에 위치해야 합니다. http 또는 server 블록에 두면 일부 환경에서 적용되지 않습니다.

Case 3: Gunicorn 유닉스 소켓 연동

Gunicorn을 systemd로 등록했으나 브라우저 접속이 안 되는 경우, 유닉스 소켓 방식으로 실행했기 때문입니다. 소켓은 Nginx를 통해서만 접근 가능합니다.

# /etc/systemd/system/gunicorn.service
[Service]
WorkingDirectory=/home/ubuntu/myproject
ExecStart=/home/ubuntu/venv/bin/gunicorn --bind unix:/tmp/gunicorn.sock config.wsgi:application

# Nginx 설정
location / {
    proxy_pass http://unix:/tmp/gunicorn.sock;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

코드 변경 후에는 sudo systemctl restart gunicorn 필수. Django 정적 파일은 Gunicorn이 서빙하지 않으므로 Nginx에서 location /static/ 블록을 별도로 설정해야 합니다.

Case 4: Kubernetes Ingress 간헐적 502

파드는 정상이나 Ingress에서 간헐적으로 502 발생 시, timeout과 버퍼를 annotations로 조정합니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
    nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"

Case 5: 무중단 배포 환경 포트 충돌

배포 스크립트가 새 jar를 8081 포트로 실행했으나, Nginx는 여전히 8080을 바라보는 경우.

# 실행 중인 포트 확인
sudo lsof -i :8080
sudo lsof -i :8081

# service-url.inc 또는 upstream 블록 수정
upstream backend {
    server 127.0.0.1:8081;  # 실제 실행 포트로 변경
}

sudo nginx -s reload

꿀팁: 무중단 배포 시 헬스체크 엔드포인트(/health)를 upstream에 추가하고, max_fails=3 fail_timeout=30s 옵션으로 장애 전파를 방지하십시오.

4. 로그 기반 트러블슈팅

로그는 추측을 배제하고 정확한 원인을 파악하는 유일한 수단입니다.

  • Nginx 에러 로그 실시간 확인: sudo tail -f /var/log/nginx/error.log
  • 백엔드 로그: tail -f /var/log/myapp/nohup.out 또는 journalctl -u gunicorn -f
  • 주요 에러 메시지 해석:
    • "connect() failed (111: Connection refused)" → 백엔드 프로세스 미실행 또는 포트 불일치
    • "connect() to unix:/tmp/gunicorn.sock failed (13: Permission denied)" → 소켓 권한 문제
    • "upstream timed out (110: Connection timed out)" → proxy_read_timeout 부족 또는 백엔드 응답 지연

로그를 분리 보관하려면 Nginx 설정에서 access_log /var/log/nginx/myapp_access.log;로 커스텀 경로를 지정하고, logrotate로 주기적 압축/삭제를 설정하십시오.

요약 및 Action Item

502 에러는 백엔드 미동작, proxy_pass 오류, 소켓 권한 불일치, 타임아웃/버퍼 부족이 주요 원인입니다. 체크리스트 순서대로 백엔드 프로세스 확인 → Nginx 설정 검증 → 소켓 권한 점검 → 로그 분석을 수행하면 대부분 해결됩니다. 지금 당장 실행할 것: sudo lsof -i :백엔드포트로 프로세스 실행 여부를 확인하고, sudo tail -f /var/log/nginx/error.log로 에러 메시지를 특정하십시오. 설정 변경 후에는 반드시 sudo nginx -s reload 또는 sudo systemctl restart 서비스명을 실행하여 변경사항을 반영해야 합니다.


#함께 읽으면 좋은 글

유료 VPN 추천 TOP 3: NordVPN vs ExpressVPN 속도 및 보안 기능 비교 2025 : 바로보기


댓글