502 Bad Gateway 오류 원인과 해결 방법

Advertisement
502 Bad Gateway 오류란?
502 Bad Gateway는 응답한 서버가 게이트웨이 또는 프록시 역할을 하고 있으며, 그 뒤에 있는 서버에서 잘못된 응답을 받았다는 뜻의 HTTP 상태 코드입니다. HTTP 표준(RFC 9110, 15.6.3절)도 정확히 그렇게 정의합니다. 서버가 "게이트웨이 또는 프록시 역할을 하는 동안, 요청을 처리하려고 접근한 내부 서버로부터 잘못된 응답을 받은" 경우입니다.
대부분의 최신 웹사이트에는 최소 두 개의 계층이 있습니다. nginx, Apache, Cloudflare, 클라우드 로드 밸런서 같은 프런트 서버가 연결을 받은 뒤, PHP-FPM, Node.js 앱, Python의 Gunicorn, 컨테이너 같은 업스트림(upstream) 애플리케이션으로 요청을 넘깁니다. 업스트림이 다운되었거나 크래시했거나 프록시가 사용할 수 없는 응답을 보내면, 프록시는 돌려줄 것이 없으므로 502를 반환합니다.
중요한 점은 게이트웨이 자체는 정상 작동하고 있다는 것입니다. 요청을 받았고 응답도 했습니다. 문제는 그보다 한 단계 뒤에 있습니다.
502 오류가 표시되는 여러 가지 모습
상태 코드는 어디서나 같지만, 보이는 페이지는 어떤 프록시가 만들었는지에 따라 달라집니다:
| 발생 위치 | 페이지에 표시되는 내용 |
|---|---|
| nginx | 502 Bad Gateway, 아래에 nginx(때로는 버전까지) 표시 |
| Apache (mod_proxy) | Proxy Error. The proxy server received an invalid response from an upstream server. |
| Cloudflare | Error 502 Bad gateway, Browser / Cloudflare / Host 상태 상자 표시 |
| Microsoft IIS (ARR / ASP.NET Core) | HTTP Error 502.3 - Bad Gateway, 또는 HTTP Error 502.5 - Process Failure |
| Google 서비스 | 502. That's an error. The server encountered a temporary error… |
| 브라우저 / 앱 | HTTP Error 502, 502 Proxy Error, Bad Gateway: The proxy server received an invalid response |
어떤 형태로 보이든, 하단에 표시된 프록시 이름은 유용한 단서입니다. 사이트 운영자가 어느 계층을 조사해야 하는지 알려 주기 때문입니다.
Advertisement
502 vs 500 vs 503 vs 504: 차이점은?
5xx 코드는 모두 '서버 문제'를 뜻하지만, 각각 가리키는 계층이 다릅니다:
| 코드 | 이름 | 의미 | 흔한 원인 |
|---|---|---|---|
| 500 | Internal Server Error | 요청을 처리하는 중 애플리케이션 자체가 실패함 | 코드 버그, PHP 치명적 오류, 잘못된 설정 |
| 502 | Bad Gateway | 프록시가 업스트림에서 잘못된 응답을 받았거나, 사용할 수 있는 응답을 받지 못함 | 앱 다운, 크래시, 잘못된 포트나 소켓, 너무 큰 헤더 |
| 503 | Service Unavailable | 서버가 일시적으로 요청을 거부함 | 과부하, 유지보수 모드, 속도 제한 |
| 504 | Gateway Timeout | 프록시가 업스트림을 기다리다 포기함 | 느린 데이터베이스 쿼리, 오래 실행되는 스크립트, 너무 낮은 타임아웃 |
간단한 규칙: 502 = 업스트림이 잘못된 응답을 보냄(또는 연결을 끊음), 504 = 업스트림이 제시간에 응답하지 않음. 관련 오류는 각 가이드에서 자세히 다룹니다: 500 Internal Server Error, 503 Service Unavailable, 504 Gateway Timeout.
502 Bad Gateway의 원인
업스트림 앱이 실행 중이 아닙니다. PHP-FPM, Node, Gunicorn 또는 컨테이너가 크래시했거나, 배포 후 시작에 실패했거나, 재시작 중입니다.
프록시가 잘못된 곳을 가리킵니다.
proxy_pass나fastcgi_pass가 잘못된 포트, 업그레이드 이전의 오래된 PHP 소켓 경로, 또는 Docker 컨테이너 안의localhost를 사용합니다.일부 요청에서 앱이 크래시합니다. 특정 페이지가 메모리 부족 종료나 처리되지 않은 예외를 일으켜, 응답 전에 연결이 닫힙니다.
모든 워커가 사용 중입니다. PHP-FPM이
pm.max_children에 도달해 새 요청을 처리할 곳이 없습니다.응답 헤더가 너무 큽니다. 큰 쿠키나 긴 보안 헤더가 nginx의
proxy_buffer_size를 넘칩니다.로드 밸런서 뒤의 keep-alive 불일치. 앱이 로드 밸런서가 예상하는 것보다 일찍 유휴 연결을 닫아서, 밸런서가 닫히고 있는 연결로 요청을 보냅니다.
프록시와 원본 서버 사이의 방화벽 또는 네트워크 변경. 예를 들어 원본 서버의 IP 주소나 방화벽 규칙이 바뀌어 CDN이 더 이상 원본에 도달하지 못하는 경우입니다.
Advertisement
방문자로서 502 오류 해결하기
남의 서버를 고칠 수는 없지만, 다음 단계로 문제가 정말 사이트 쪽에 있는지 확인하고 드물게 있는 로컬 원인을 정리할 수 있습니다:
30~60초 기다린 뒤 새로고침하세요(Ctrl + R, Mac은 Cmd + R). 상당수 502는 배포나 재시작이 진행되는 동안만 지속됩니다.
모두에게 다운되었는지 확인하세요. DNS Robot의 HTTP 헤더 확인 도구는 저희 서버에서 페이지를 요청해 정확한 상태 코드를 보여 줍니다. 저희 쪽에서도 502가 나온다면 내 문제가 아니라 사이트 문제입니다. Ping 테스트로 서버 머신이 응답하는지도 확인할 수 있습니다.
강력 새로고침하고 캐시를 지우세요. Ctrl + Shift + R(Mac: Cmd + Shift + R)은 캐시된 사본을 건너뛰므로, 오래된 오류 페이지가 표시되는 경우에 효과가 있습니다.
사이트가 최근 호스팅을 옮겼다면 DNS를 플러시하세요. 그래야 새 서버로 접속합니다. 운영체제별 DNS 플러시 방법을 참고하세요.
VPN과 프록시를 끄세요. 특히 회사 네트워크에서는 내가 쓰는 프록시가 실패하는 '게이트웨이'일 수 있습니다.
다른 브라우저나 모바일 데이터로 연결한 휴대폰에서 시도하세요. 거기서 열린다면 해당 사이트의 쿠키를 지우세요.
내 서버의 502 Bad Gateway 해결하기
서버 측에서 502는 비교적 고치기 쉬운 오류입니다. 프록시가 무엇이 잘못되었는지 거의 항상 정확히 기록해 두기 때문입니다. 다음 네 가지를 순서대로 점검하세요.
Advertisement
1. 프록시의 오류 로그 읽기
502를 재현한 뒤, 프록시 서버의 오류 로그 마지막 줄들을 읽으세요:
| 로그 메시지 | 의미 |
|---|---|
| connect() failed (111: Connection refused) while connecting to upstream | 업스트림 포트에서 수신 대기 중인 것이 없음: 앱이 다운되었거나 다른 포트에서 실행 중 |
| connect() to unix:/run/php/php8.x-fpm.sock failed (2: No such file or directory) | PHP-FPM 소켓이 존재하지 않음, 보통 PHP 버전 변경이 원인 |
| connect() to unix:… failed (13: Permission denied) | nginx가 소켓에 접근할 수 없음: listen.owner / listen.group 수정 필요 |
| upstream prematurely closed connection while reading response header | 요청 처리 중 앱이 크래시했거나 연결을 닫음 |
| upstream sent too big header while reading response header from upstream | 응답 헤더가 proxy_buffer_size보다 큼 |
| no live upstreams while connecting to upstream | upstream 블록의 모든 서버가 실패로 표시됨 |
# nginx
sudo tail -n 50 /var/log/nginx/error.log
# Apache
sudo tail -n 50 /var/log/apache2/error.log # Debian/Ubuntu
sudo tail -n 50 /var/log/httpd/error_log # RHEL/Alma/Rocky다음 nginx 메시지들이 502의 대부분을 차지하며, 각 메시지가 해결 방향을 알려 줍니다:
2. 업스트림 앱이 실행 중인지 확인
# PHP-FPM (버전에 맞게 수정)
sudo systemctl status php8.3-fpm
sudo journalctl -u php8.3-fpm -n 50
# PM2로 실행 중인 Node.js
pm2 status
pm2 logs --lines 50
# Docker
docker ps -a # 계속 재시작되는 컨테이너가 있는지 확인
docker logs --tail 50 <container>
# 메모리를 너무 많이 써서 종료되었나요?
dmesg -T | grep -i "killed process"서비스가 중지되어 있다면 시작하고, 왜 멈췄는지 찾으세요. 실패한 배포, 새 릴리스의 문법 오류, 또는 OOM(메모리 부족) 킬러가 흔한 원인입니다. PHP-FPM 로그의 server reached pm.max_children setting은 모든 워커가 사용 중이었다는 뜻입니다. 서버 RAM이 충분할 때만 pm.max_children을 올리고, 그렇지 않다면 워커를 붙잡고 있는 느린 요청을 찾으세요.
3. proxy_pass가 올바른 포트나 소켓을 가리키는지 확인
nginx가 연결하도록 설정된 대상과 실제로 수신 대기 중인 대상을 비교하세요:
# nginx는 어디로 프록시하고 있나요?
grep -rn "proxy_pass\|fastcgi_pass" /etc/nginx/sites-enabled/
# 실제로 수신 대기 중인 것은?
sudo ss -tlnp # TCP 포트와 해당 프로세스
ls -l /run/php/ # PHP-FPM 소켓 파일전형적인 불일치 두 가지가 있습니다. PHP를 업그레이드하면 소켓이 php8.3-fpm.sock으로 바뀌는데 nginx는 여전히 php8.1-fpm.sock을 가리키는 경우, 그리고 Docker 안에서 proxy_pass http://localhost:3000이 앱이 아닌 nginx 컨테이너 자신을 가리키는 경우입니다. Docker에서는 Compose 서비스 이름(http://app:3000)을 사용하세요. 설정을 바꾼 뒤에는 sudo nginx -t와 sudo systemctl reload nginx를 실행하세요.
4. 실제 사례: dnsrobot.net이 502를 반환한 이유
2026년 9월 30일, 저희 사이트에서 실제로 있었던 일입니다. 새 블로그 글을 여러 개 게시한 뒤, 그중 딱 하나만 nginx 1.24를 통해 502 Bad Gateway를 반환했고 다른 페이지는 모두 정상이었습니다. nginx 뒤의 Next.js 앱에 3000 포트로 직접 요청하면 같은 페이지가 200 OK로 응답했습니다. 즉 앱은 멀쩡했고 게이트웨이가 실패하고 있었습니다.
nginx 오류 로그 한 줄에 답이 있었습니다: upstream sent too big header while reading response header from upstream. 그 페이지의 응답 헤더는 4,087바이트였는데, 대부분 긴 Content-Security-Policy 헤더와 preload Link 헤더였습니다. nginx는 모든 헤더를 포함한 응답의 앞부분을 proxy_buffer_size로 정해진 버퍼에 읽어 들이는데, 기본값은 메모리 한 페이지로 저희 서버에서는 4 KB였습니다. 남은 여유가 9바이트뿐이었고, 상태 줄까지 포함한 전체 헤더 블록이 버퍼를 넘쳤습니다.
해결책은 앱으로 프록시하는 location 블록에 세 줄을 추가하는 것이었습니다:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_buffer_size 16k; # 큰 헤더를 위한 공간 (기본값 4k에서 변경)
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
}nginx -t와 다시 불러오기 후 페이지는 200을 반환했습니다. 교훈: 사이트의 나머지는 정상인데 일부 페이지만 502를 반환한다면, 앱을 의심하기 전에 해당 페이지의 큰 헤더나 큰 쿠키 같은 크기 제한부터 찾아보세요.
로드 밸런서 뒤의 Node.js: 간헐적인 502
AWS Application Load Balancer나 비슷한 밸런서 뒤에서 Node.js를 운영하는데, 앱 로그에는 오류가 없는데도 가끔 502가 난다면 keep-alive 타임아웃을 확인하세요. Node의 HTTP 서버는 기본적으로 유휴 keep-alive 연결을 5초 후에 닫는 반면(server.keepAliveTimeout, Node.js 26 이하 기준), AWS ALB는 유휴 연결을 60초 동안 열어 둡니다. 가끔 Node가 연결을 닫는 바로 그 순간 밸런서가 그 연결을 재사용하고, 그 요청이 502로 돌아옵니다.
해결책은 앱의 타임아웃을 밸런서의 타임아웃보다 길게 설정하는 것입니다:
const server = app.listen(3000)
// 로드 밸런서의 유휴 타임아웃보다 길어야 합니다 (ALB 기본값: 60초)
server.keepAliveTimeout = 65_000
server.headersTimeout = 66_000 // keepAliveTimeout보다 약간 크게 유지Cloudflare의 502 Bad Gateway
Cloudflare를 사용 중이라면 먼저 오류 페이지를 누가 만들었는지 확인하세요:
Cloudflare 브랜드 페이지(Browser ✓ / Cloudflare ✓ / Host ✗): Cloudflare는 정상이지만 원본 서버에서 유효한 응답을 받지 못했습니다. 원본 서버가 켜져 있고 443/80 포트에서 수신 대기 중인지, 방화벽이 Cloudflare의 IP 대역을 차단하지 않는지 확인하세요. 포트 확인 도구로 원본 서버를 직접 테스트할 수 있습니다.
브랜드 없는 일반 502 페이지: cloudflare가 언급되지 않는다면(예: nginx나 Apache가 표시됨) 내 원본 서버가 502를 생성한 것입니다. 위의 서버 측 단계를 따르세요. 하단에 'cloudflare'만 적힌 빈 페이지는 Cloudflare 자체에서 나온 것으로, 일시적인 트래픽 경로 변경 중이거나 원본이 손상된 gzip 콘텐츠를 보낼 때 나타납니다.
원본 IP가 바뀌었나요? 호스팅을 옮겼다면 Cloudflare DNS의 A 레코드를 업데이트하세요. DNS 조회로 현재 전 세계에서 보이는 값을 확인할 수 있습니다.
Advertisement
502 오류가 SEO에 영향을 주나요?
짧은 장애라면 영향이 없습니다. Google 문서에 따르면 5xx 서버 오류가 발생하면 크롤러가 일시적으로 크롤링 속도를 늦춥니다. 이미 색인된 페이지는 처음에는 색인에 남아 있지만, 오류가 계속되면 Google은 결국 해당 URL을 색인에서 제외합니다.
따라서 배포 중 몇 분간 나타나는 502는 무해합니다. 하지만 중요한 페이지에서 며칠씩 이어지거나 몇 주 동안 간헐적으로 나타나는 502는 크롤링을 줄이고 순위를 떨어뜨릴 수 있습니다. 핵심 URL을 모니터링하고, 장애 후에는 Search Console의 크롤링 통계 보고서를 확인하세요.
사이트가 모두에게 502를 반환하고 있나요?
DNS Robot의 HTTP 헤더 확인 도구는 저희 서버에서 모든 URL을 요청해 정확한 상태 코드, 서버 소프트웨어, 모든 응답 헤더를 보여 줍니다. 502를 확인하는 가장 빠른 방법입니다.
사용해보기 HTTP 헤더 확인 도구Advertisement
자주 묻는 질문
접속한 서버가 nginx, Cloudflare, 로드 밸런서 같은 게이트웨이나 프록시이고, 그 뒤의 애플리케이션 서버에서 잘못된 응답을 받았다는 뜻입니다. 프록시는 정상이며, 그 뒤의 앱이 다운되었거나 크래시했거나 도달할 수 없거나 프록시가 사용할 수 없는 응답을 보낸 것입니다.