문제 정의
502 Bad Gateway는 reverse proxy가 upstream에서 정상 응답을 받지 못했다는 신호입니다. 하지만 사용자가 보는 증상은 하나여도 원인은 다양합니다. 백엔드가 죽었을 수도 있고, 포트가 틀렸을 수도 있으며, 컨테이너는 healthy인데 프록시 네트워크가 다를 수도 있습니다.
502 대응은 추측이 아니라 계층별 확인 순서가 있어야 빨라집니다.
상황과 배경
Docker Compose와 Nginx를 함께 쓰는 서비스에서는 로컬 컨테이너 상태와 공개 도메인 상태가 다를 수 있습니다. 백엔드 health는 정상인데 Nginx upstream이 다른 포트를 보고 있거나, API base URL이 잘못되어 브라우저에서만 실패하는 경우도 흔합니다.
컨테이너 준비 상태를 나누는 기준은 Docker Compose healthcheck 기준에서 먼저 정리할 수 있습니다.
502를 좁히는 순서
- 프록시 로그: Nginx access/error log에서 upstream 오류를 확인합니다.
- 컨테이너 상태: backend 컨테이너가 running/healthy인지 봅니다.
- upstream 주소: Nginx가 바라보는 host와 port가 실제 compose port와 맞는지 확인합니다.
- readiness: backend가 DB 연결까지 준비됐는지 확인합니다.
- 브라우저 요청: API URL, CORS, HTTPS mixed content를 확인합니다.
실제 적용 방법
먼저 서버 내부에서 backend readiness URL을 직접 호출합니다. 그 다음 Nginx 컨테이너 또는 호스트에서 upstream 주소로 요청해 봅니다. 여기까지 정상이라면 공개 도메인, SSL, location block 순서로 봅니다. 프론트엔드가 API를 직접 호출하는 구조라면 브라우저 개발자 도구에서 실제 요청 URL도 확인해야 합니다.
배포 후 공개 경로 확인은 배포 후 smoke test에 포함해 반복 가능한 절차로 만들어야 합니다.
운영 체크리스트
- Nginx error log의 upstream host와 port를 기록합니다.
- backend
/health/ready가 DB 연결까지 확인하는지 봅니다.
- compose service name과 host port를 혼동하지 않습니다.
- 프론트 빌드 시점 API URL과 런타임 API URL 차이를 확인합니다.
- 수정 후에는 홈, 글 상세, API health를 모두 다시 확인합니다.
결론
502는 한 번에 고치는 문제가 아니라 계층을 좁히는 문제입니다. API 에러 처리 기준까지 함께 갖추면 사용자에게도 운영자에게도 실패 상태가 더 명확해집니다.