Nginx 502 Bad Gateway 오류 진단 및 해결 방법
Nginx는 강력하고 인기 있는 웹 서버이자 리버스 프록시이며, 종종 정적 콘텐츠를 제공하고, 트래픽을 로드 밸런싱하며, PHP-FPM, Node.js, Python Gunicorn 또는 Apache Tomcat과 같은 다양한 업스트림 애플리케이션 서버로 요청을 전달하는 데 사용됩니다. Nginx가 이러한 업스트림 서버 중 하나와 통신하는 데 문제가 발생하면 일반적으로 "502 Bad Gateway" 오류가 발생합니다.
이 문서에서는 Nginx 502 Bad Gateway 오류를 이해하고 진단하며 해결하기 위한 포괄적인 단계별 가이드를 제공합니다. 일반적인 원인을 살펴보고, 명령줄 도구를 사용하여 실용적인 문제 해결 기술을 익히며, 웹 서비스를 빠르게 복구하기 위한 실행 가능한 솔루션을 제공할 것입니다. 시스템 관리자, 개발자 또는 자체 서버를 관리하는 분이라면 이 가이드를 통해 가장 흔한 Nginx 오류 중 하나를 효과적으로 해결하는 데 도움이 될 것입니다.
Nginx 502 Bad Gateway 오류 이해하기
502 Bad Gateway 오류는 리버스 프록시 역할을 하는 Nginx가 업스트림 서버로부터 유효하지 않은 응답을 받았음을 나타냅니다. 이는 Nginx가 업스트림 서버에 성공적으로 연결했지만, 응답을 받지 못했거나, 불완전한 응답을 받았거나, 이해할 수 없는 응답을 받았다는 의미입니다. 중요한 점은 문제는 Nginx 자체에 있는 것이 아니라 Nginx가 통신하려고 하는 서비스에 있다는 것입니다.
일반적인 업스트림 서버는 다음과 같습니다.
- PHP-FPM: PHP 애플리케이션 (예: WordPress, Laravel)용.
- Gunicorn/uWSGI: Python 애플리케이션 (예: Django, Flask)용.
- Node.js: JavaScript 애플리케이션용.
- Apache Tomcat: Java 애플리케이션용.
- 기타 웹 서버: 특정 콘텐츠를 제공하는 Apache HTTP Server 등.
502 오류는 애플리케이션의 백엔드가 올바르게 작동하지 않거나 Nginx에 액세스할 수 없다는 중요한 지표입니다.
단계별 진단
502 오류를 해결하는 핵심은 체계적인 진단입니다. 가장 가능성이 높은 원인부터 시작하여 점진적으로 더 깊이 조사하십시오.
1. Nginx 오류 로그 먼저 확인
Nginx 오류 로그는 정보의 주요 소스입니다. Nginx가 업스트림 서버와 통신할 수 없었던 이유에 대한 특정 세부 정보를 종종 포함합니다.
- 위치: 일반적으로
/var/log/nginx/error.log에서 찾을 수 있습니다. - 명령: 오류를 재현하는 동안
tail -f를 사용하여 실시간으로 로그를 모니터링하십시오.
tail -f /var/log/nginx/error.log
찾아야 할 것:
* connect() failed (111: Connection refused): 업스트림 서버가 지정된 주소/포트에서 수신 대기하고 있지 않거나 방화벽이 연결을 차단하고 있음을 나타냅니다.
* upstream timed out: 업스트림 서버가 응답하는 데 너무 오래 걸렸습니다.
* upstream prematurely closed connection: 업스트림 서버가 완전한 응답을 보내기 전에 연결을 닫았습니다.
* no live upstreams while connecting to upstream: Nginx가 구성된 사용 가능한 업스트림 서버를 찾을 수 없었습니다.
2. 업스트림 서버 상태 확인
Nginx 오류 로그에서 단서를 얻었다면, 업스트림 애플리케이션 서버의 상태를 확인하십시오.
-
PHP-FPM의 경우:
bash systemctl status phpX.X-fpm # X.X를 PHP 버전으로 대체하십시오 (예: php7.4-fpm) sudo service phpX.X-fpm status -
Node.js/Python/기타 사용자 지정 앱의 경우:
프로세스가 실행 중인지 확인하십시오.bash ps aux | grep node ps aux | grep gunicorn
PM2 (Node.js) 또는 Supervisor (일반)와 같은 프로세스 관리자를 사용하는 경우, 해당 상태를 확인하십시오.bash pm2 status sudo supervisorctl status
서비스가 실행 중이 아니라면, 서비스를 시작하고 자체 로그에서 오류를 확인하십시오.
systemctl start phpX.X-fpm
# 또는
sudo service phpX.X-fpm start
3. 업스트림으로의 네트워크 연결 확인
Nginx가 구성된 포트 또는 소켓 경로를 통해 업스트림 서버에 연결할 수 있는지 확인하십시오.
-
TCP/IP 연결의 경우 (예:
127.0.0.1:8000):
Nginx 서버에서telnet또는nc(netcat)를 사용하여 포트 연결을 테스트하십시오.bash telnet 127.0.0.1 8000 nc -vz 127.0.0.1 8000
성공적인 연결은Connected to 127.0.0.1.또는succeeded!를 보여야 합니다. 연결이 지연되거나Connection refused가 표시되면 업스트림 서비스가 수신 대기하고 있지 않거나 방화벽이 차단하고 있는 것입니다. -
Unix 소켓의 경우 (예:
unix:/run/php/phpX.X-fpm.sock):
소켓 파일이 존재하고 올바른 권한을 가지고 있는지 확인하십시오.bash ls -l /run/php/phpX.X-fpm.sock
Nginx는 이 소켓 파일에 대한 읽기/쓰기 권한을 가지고 있어야 합니다. Nginx 사용자 (예:www-data)는 소켓을 소유하는 그룹 (예:www-data또는php-fpm)의 일부여야 합니다.
일반적인 원인 및 해결책
진단 단계에 따라 502 오류의 가장 빈번한 원인과 해결 방법은 다음과 같습니다.
1. 업스트림 서버가 실행 중이 아니거나 충돌
원인: Nginx가 프록시하려는 애플리케이션 (예: PHP-FPM, Gunicorn, Node.js 앱)이 실행 중이 아니거나 충돌했습니다.
해결책: 업스트림 서비스를 시작하거나 다시 시작하십시오.
# PHP-FPM 예시
systemctl start phpX.X-fpm
# 이미 실행 중이고 충돌이 의심되는 경우, 다시 시작하십시오:
systemctl restart phpX.X-fpm
# 사용자 지정 애플리케이션의 경우, 해당 시작/다시 시작 명령을 사용하십시오
팁: 업스트림 서비스가 시스템 부팅 시 자동으로 시작되도록 구성되었는지 확인하십시오. systemd 서비스의 경우, systemctl enable phpX.X-fpm을 사용하십시오.
2. 업스트림 서버 과부하 / 리소스 고갈
원인: 업스트림 서버가 과부하 상태이거나, 메모리, CPU가 부족하거나, 프로세스 제한에 도달하여 응답을 중지하거나 새 연결을 거부합니다.
증상: Nginx 오류 로그에 특히 부하가 걸릴 때 connection refused 또는 upstream timed out이 간헐적으로 나타날 수 있습니다. 시스템 모니터링 도구 (top, htop, free -h)는 높은 리소스 사용량을 보여줍니다.
해결책:
-
PHP-FPM의 경우: PHP-FPM 구성 파일 (예:
/etc/php/X.X/fpm/pool.d/www.conf)에서 PHP-FPM 풀 설정을 조정하십시오.pm.max_children: 동시에 활성화될 수 있는 최대 자식 프로세스 수.pm.start_servers: 시작 시 생성되는 자식 프로세스 수.pm.min_spare_servers,pm.max_spare_servers: 유지되는 유휴 자식 프로세스의 수를 제어합니다.
ini ; 동적 프로세스 관리 예시 pm = dynamic pm.max_children = 50 pm.start_servers = 10 pm.min_spare_servers = 5 pm.max_spare_servers = 20
* 스크립트가 메모리를 고갈시키는 경우,php.ini에서memory_limit을 늘리십시오.
* 다른 애플리케이션의 경우: 작업자 프로세스, 스레드 수를 늘리거나, 가능하다면 더 많은 메모리를 할당하십시오. 애플리케이션의 특정 지표를 모니터링하십시오.
* Nginx 타임아웃: Nginx 구성에서 Nginx의proxy_connect_timeout,proxy_send_timeout,proxy_read_timeout지시어를 늘리십시오. 하지만 이는 백엔드가 실제로 어려움을 겪고 있다면 오류를 지연시킬 뿐이라는 점을 이해하십시오.nginx http { ... proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; ... }
3. Nginx의 잘못된 업스트림 구성
원인: Nginx가 업스트림 서버에 대해 잘못된 IP 주소, 포트 또는 Unix 소켓 경로로 연결하도록 구성되었습니다.
증상: 요청 직후 Nginx 오류 로그에 connect() failed (111: Connection refused)가 표시됩니다.
해결책: Nginx 서버 블록 구성 (/etc/nginx/sites-available/your_site.conf)을 주의 깊게 검토하십시오.
-
HTTP/HTTPS 업스트림의 경우:
nginx location /app { proxy_pass http://127.0.0.1:8000; # IP와 포트가 올바른지 확인 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } -
Unix 소켓을 통한 PHP-FPM의 경우:
nginx location ~ \.php$ { fastcgi_pass unix:/run/php/phpX.X-fpm.sock; # 이 경로가 PHP-FPM 구성과 정확히 일치하는지 확인 fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } -
TCP/IP를 통한 PHP-FPM의 경우:
nginx location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; # IP와 포트 확인 fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }
변경 사항을 적용한 후에는 항상 Nginx 구성을 테스트하고 Nginx를 다시 로드/다시 시작하십시오:
nginx -t
systemctl reload nginx # -t에서 다시 시작해야 한다고 표시되면 restart
4. PHP-FPM request_terminate_timeout 초과
원인: PHP 스크립트가 PHP-FPM의 request_terminate_timeout 설정보다 실행하는 데 더 오래 걸립니다. Nginx는 응답을 기다리지만 PHP-FPM이 스크립트를 종료하여 Nginx가 불완전한 응답을 받게 됩니다.
증상: Nginx 오류 로그에 upstream timed out 또는 script timed out이 표시될 수 있습니다. PHP-FPM 로그에는 child XX exited on signal 9 (SIGKILL)이 표시될 수 있습니다.
해결책:
* request_terminate_timeout 늘리기: PHP-FPM 풀 구성 (www.conf)에서 이 지시어를 찾아 조정하십시오. 0으로 설정하면 타임아웃이 비활성화되지만, 장시간 실행되는 스크립트가 리소스를 고정시킬 수 있으므로 일반적으로 권장되지 않습니다.
```ini
request_terminate_timeout = 300 # 5분 (300초)으로 늘리기
```
-
Nginx에서
fastcgi_read_timeout늘리기: 이 Nginx 타임아웃은request_terminate_timeout과 같거나 커야 합니다.nginx location ~ \.php$ { ... fastcgi_read_timeout 300s; # PHP-FPM의 request_terminate_timeout보다 크거나 같아야 함 ... }
경고: 타임아웃을 늘리면 502 오류를 해결할 수 있지만, 근본적인 성능 문제를 가릴 수 있습니다. 가장 좋은 장기적인 해결책은 느린 PHP 스크립트를 최적화하는 것입니다.
5. 방화벽 문제
원인: 방화벽 (Nginx 서버 또는 업스트림 서버가 분리되어 있는 경우)이 업스트림 포트 또는 소켓으로의 연결을 차단하고 있습니다.
해결책:
* 방화벽 상태 확인:
```bash
sudo ufw status # UFW (Ubuntu/Debian)의 경우
sudo firewall-cmd --list-all # firewalld (CentOS/RHEL)의 경우
sudo iptables -L # iptables의 경우
```
-
필요한 포트 열기: Nginx가 업스트림에 연결하는 데 사용하는 포트 (예: TCP/IP를 통한 PHP-FPM의 경우 9000)가 열려 있는지 확인하십시오.
bash sudo ufw allow from 127.0.0.1 to any port 9000 # 로컬호스트가 9000으로 연결하도록 허용 sudo firewall-cmd --permanent --add-port=9000/tcp # firewalld의 경우 sudo firewall-cmd --reload
* 테스트 목적으로 제어된 환경에서만 일시적으로 방화벽을 비활성화한 다음, 다시 활성화하고 올바르게 구성하십시오.
6. SELinux 또는 AppArmor 간섭
원인: SELinux (RHEL/CentOS) 또는 AppArmor (Ubuntu/Debian)와 같은 보안 강화 기능이 파일 권한 및 방화벽이 올바르게 구성되어 있더라도 Nginx가 업스트림 소켓에 액세스하거나 네트워크 연결을 하는 것을 방해할 수 있습니다.
증상: 특히 /var/log/audit/audit.log (SELinux의 경우)에 permission denied 또는 유사한 메시지가 로그에 표시될 수 있습니다.
해결책:
* audit.log 확인:
```bash
sudo grep nginx /var/log/audit/audit.log
```
- SELinux를 일시적으로 허용 모드로 설정:
sudo setenforce 0. 오류가 해결되면 SELinux가 원인입니다. 그런 다음 적절한 SELinux 정책을 생성하고 적용해야 합니다 (예:audit2allow). 다시 강제 모드로 설정하는 것을 잊지 마십시오 (sudo setenforce 1). - AppArmor 상태 확인:
sudo aa-status. AppArmor가 활성화되어 있으면 Nginx 프로필을 조정해야 할 수 있습니다.
7. 대용량 요청/응답 본문 (프록시 버퍼링)
원인: Nginx의 기본 프록시 버퍼링 설정이 매우 큰 요청 또는 응답 본문에 비해 너무 작아 연결이 조기에 종료될 수 있습니다.
증상: Nginx 오류 로그에 upstream prematurely closed connection while reading response header from upstream 또는 upstream prematurely closed connection while reading response body from upstream이 표시될 수 있습니다.
해결책: http, server, 또는 location 블록에서 Nginx 프록시 버퍼링 지시어를 조정하십시오.
http {
...
proxy_buffer_size 128k; # 응답의 첫 부분에 대한 버퍼 크기
proxy_buffers 4 256k; # 응답의 나머지 부분에 대한 버퍼의 수와 크기
proxy_busy_buffers_size 256k; # 사용 중인 버퍼의 최대 크기
proxy_temp_file_write_size 256k; # 버퍼링이 오버플로될 경우 임시 파일에 쓰는 크기
...
}
참고: 이 설정은 더 많은 메모리를 사용합니다. 서버의 리소스와 애플리케이션 응답의 일반적인 크기를 기반으로 신중하게 조정하십시오.
일반적인 문제 해결 팁
- 모든 관련 로그 검토: Nginx 오류 로그 외에도 Nginx 액세스 로그, 업스트림 애플리케이션 로그 (PHP-FPM, Gunicorn, Node.js 앱 로그) 및 시스템 로그 (
/var/log/syslog,dmesg)를 확인하십시오. - Nginx 다시 시작: 구성 변경 후에는 항상 Nginx를 다시 시작하여 변경 사항이 적용되도록 하십시오:
systemctl restart nginx. - Nginx 구성 테스트: 다시 시작하기 전에 Nginx 구성 구문을 검증하십시오:
nginx -t. - 문제 격리: Nginx를 우회하고 업스트림 애플리케이션에 직접 액세스해 보십시오. 예를 들어, Node.js 앱이
localhost:3000에서 실행 중인 경우, 서버의 명령줄에서curl http://localhost:3000을 사용하십시오. 이것도 실패하면 문제는 Nginx가 아니라 애플리케이션에 있는 것입니다. - 디스크 공간 확인: 디스크가 가득 차면 애플리케이션이 임시 파일이나 로그를 작성하는 것을 방해하여 충돌이나 실패를 초래할 수 있습니다.
df -h를 사용하여 디스크 사용량을 확인하십시오.
결론
Nginx 502 Bad Gateway 오류는 흔하지만 거의 항상 Nginx 자체가 아닌 Nginx가 연결하려는 백엔드 애플리케이션의 문제를 나타냅니다. Nginx 오류 로그를 체계적으로 확인하고, 업스트림 서버 상태를 확인하고, 네트워크 연결을 확인한 다음, 일반적인 구성 또는 리소스 문제를 해결함으로써 이러한 문제를 효과적으로 진단하고 해결할 수 있습니다.
가장 기본적인 확인부터 시작하여 점진적으로 더 깊이 파고드는 체계적인 문제 해결 방식을 기억하십시오. 변경 사항을 적용한 후에는 항상 Nginx 구성을 테스트하고, 향후 발생을 방지하기 위해 애플리케이션 및 서버의 상태를 모니터링하십시오. 이러한 전략을 통해 서비스를 원활하게 실행하는 데 필요한 준비를 갖추게 될 것입니다.