웹 서비스를 운영하다가 갑자기 브라우저에 504 Gateway Timeout 에러 화면이 출력되는 상황을 경험해봤을까? 서비스 이용자가 대용량 엑셀을 다운로드하거나 긴 작업을 처리할 때 주로 발생하는데, 서버 로그를 확인하지 않으면 Nginx 문제인지 백엔드 애플리케이션 문제인지 판단하기 어렵다.
다만 대부분의 개발자들은 504 에러가 뜨면 정확한 원인이나 해결책을 모르는 채 Nginx 설정 파일에서 타임아웃 숫자만 무작정 늘려놓고 방치하는 경우가 많다.
이번에는 Nginx 504 Gateway Timeout 에러가 정확히 뭔지, 왜 발생하는지, 그리고 fastcgi_read_timeout과 proxy_read_timeout을 비롯한 핵심 설정값을 어떻게 수정해 완벽하게 해결하는지 정리해서 소개하겠다.
504 Gateway Timeout 에러는 게이트웨이나 프록시 역할을 하는 서버(Nginx)가 상위 서버(PHP-FPM, Node.js, Gunicorn 등)로부터 일정 시간 동안 응답을 받지 못했을 때 발생한다.
즉, 클라이언트의 요청이 Nginx를 거쳐 백엔드 애플리케이션으로 전달되었으나, 백엔드 애플리케이션의 처리 시간이 Nginx에 설정된 타임아웃 제한 시간을 초과해버린 것이다.
| 연동 방식 | 주요 원인 | 핵심 관련 설정 항목 |
|---|---|---|
| Nginx + PHP-FPM (FastCGI) | PHP 스크립트 실행 시간이 fastcgi_read_timeout 초과 | fastcgi_read_timeout, max_execution_time |
| Nginx + Node.js / Spring (Reverse Proxy) | 백엔드 API 응답 시간이 proxy_read_timeout 초과 | proxy_read_timeout, proxy_connect_timeout |
| DB / 외부 API 지연 | DB 쿼리 병목 또는 외부 API 응답 지연으로 인한 체증 | DB execution_timeout, cURL timeout |
504 에러를 해결하려면 Nginx의 타임아웃 설정뿐만 아니라 뒤단에 위치한 백엔드 프로세스의 실행 시간 제한도 함께 맞춰주어야 한다. 어느 한쪽에만 설정을 적용하면 다른 쪽에서 여전히 타임아웃이 걸린다.
1. fastcgi_read_timeout (FastCGI 환경): Nginx가 FastCGI 서버(PHP-FPM)로부터 데이터를 읽어들이는 대기 시간이다.
2. proxy_read_timeout (리버스 프록시 환경): Nginx가 프록시된 백엔드 서버(Node.js, Tomcat 등)로부터 응답을 기다리는 시간이다.
3. max_execution_time (PHP 환경): PHP 엔진 내부에서 단일 스크립트가 실행될 수 있는 최대 시간(초)이다.
실무에서 가장 흔히 사용하는 PHP-FPM(FastCGI) 연동 환경과 Node.js(Reverse Proxy) 연동 환경 각각의 설정 예제를 살펴보자.
✗ 잘못된 Nginx FastCGI 설정 (타임아웃 미설정으로 기본 60초 적용)
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# fastcgi_read_timeout이 생략되어 기본값 60s가 적용됨
}✓ 올바른 Nginx FastCGI 및 php.ini 설정
# /etc/nginx/sites-available/default
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# FastCGI 응답 대기 시간을 300초로 연장
fastcgi_read_timeout 300s;
fastcgi_send_timeout 300s;
fastcgi_connect_timeout 60s;
}Nginx 설정 변경 후에는 반드시 php.ini와 php-fpm pool 설정도 함께 수정해야 한다.
; /etc/php/8.2/fpm/php.ini
max_execution_time = 300
; /etc/php/8.2/fpm/pool.d/www.conf
request_terminate_timeout = 300s설정 적용 후 Nginx와 PHP-FPM 서비스를 재시작한다.
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl restart php8.2-fpm출력 결과: Nginx 구문 검사 성공(nginx: configuration file /etc/nginx/nginx.conf test is successful) 후 설정이 반영되어 60초가 넘는 작업도 504 에러 없이 최대 300초까지 정상 처리된다.
✗ 잘못된 Nginx Reverse Proxy 설정
location /api/ {
proxy_pass http://127.0.0.1:3000;
# 타임아웃 설정이 없어 대용량 처리 시 60초 후 504 발생
}✓ 올바른 Nginx Reverse Proxy 설정
location /api/ {
proxy_pass http://127.0.0.1:3000;
# 백엔드 서버와의 통신 타임아웃을 300초로 설정
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}결과: Node.js 애플리케이션의 집계 쿼리나 파일 변환 작업이 1~2분 이상 소요되어도 504 Gateway Timeout 에러가 발생하지 않는다.
타임아웃 숫자를 늘리는 것은 단순 임시방편일 수 있다. 무턱대고 시간을 늘렸을 때 발생하는 문제점과 올바른 접근 방식을 확인하자.
✗ 잘못된 대처: 무조건 타임아웃을 3600초(1시간)처럼 극단적으로 늘리기
타임아웃을 너무 길게 잡으면, 병목이나 락(Lock)이 걸린 요청 프로세스가 서버 메모리와 동시 접속 자원(Worker Process)을 계속 점유하게 되어 결국 서버 전체가 다운된다.
✓ 올바른 대처: 장시간 소요되는 작업은 비동기 큐(Queue) 구조로 전환하기
엑셀 대량 생성, 이메일 대량 발송, 이미지/영상 변환 등 30초 이상 걸리는 작업은 HTTP 동기 요청으로 처리하지 않는 것이 원칙이다. 웹 요청 시에는 즉시 작업 ID만 반환하고, 실제 작업은 백그라운드 큐 Worker(Redis Bullmq, RabbitMQ, Celery 등)에서 처리하도록 구조를 개선하자.
Nginx 504 Gateway Timeout은 게이트웨이가 백엔드 응답을 기다리다 지쳐 발생하는 에러다. 무작정 타임아웃 시간만 늘리기보다는 slow log나 APM을 통해 백엔드의 어떤 쿼리나 스크립트가 병목을 유발하는지 파악하는 것이 우선이다. 시스템 전체 자원 낭비를 막는 작은 최적화와 올바른 타임아웃 설정 습관이 모여서 안정적인 웹 서비스를 만든다는 점을 잊지 말자. 이 글의 Nginx 및 백엔드 설정 단계를 참고해 서버 환경을 점검하면, 504 에러 없는 쾌적한 데이터 처리 환경을 구축할 수 있을 것이다.