본문 바로가기
Q&A2026년 4월 14일1분 읽기

Nginx reverse proxy 뒤에서 WebSocket이 정확히 60초마다 끊깁니다

풀
풀스택지훈
조회 787댓글 3

실시간 채팅 서버를 Nginx 뒤에 두고 운영 중인데, 클라이언트에서 접속하면 정확히 60초 뒤에 연결이 끊깁니다. 앱 레벨에서 30초마다 ping/pong 주고받고 있는데도 동일합니다.

현재 Nginx 설정입니다.

location /ws {
    proxy_pass http://127.0.0.1:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
}

앱 서버(Node, ws 모듈)에 직접 붙으면 안 끊기는데, Nginx 경유만 이 증상이 나옵니다. 60초라는 숫자가 어딘가 박혀 있는 느낌인데 Nginx 쪽이 의심됩니다.

댓글 3

김김영삼6개월 전

예상하신 대로 Nginx입니다. proxy_read_timeout 기본값이 60초이고, WebSocket처럼 idle 유지되는 장기 연결은 이 타이머가 터지면 바로 끊깁니다. 애플리케이션 레벨 ping/pong은 Nginx의 read timeout을 리셋시키지 않습니다 — 어차피 데이터가 흐르긴 하지만, Nginx는 다음 읽기 이벤트가 오기까지의 간격이 60초를 넘으면 끊어버리기 때문에 ping 간격을 줄이거나 timeout을 올려야 합니다.


권장 설정
location /ws {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# WebSocket 장기 연결용
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;

# 버퍼링 끄기 (실시간성)
proxy_buffering off;
}

추가로 고려할 것

  • 앱 heartbeat 간격은 20~30초로 유지하세요. proxy_read_timeout만 늘리고 heartbeat이 없으면 NAT/방화벽이 중간에 끊는 문제는 남습니다.

  • LB/클라우드 로드밸런서가 앞단에 있다면 거기도 idle timeout이 있습니다. AWS ALB 기본 60초, Cloudflare 100초 등.

  • 모바일 클라이언트는 NAT rebinding이 30~60초 단위로 발생할 수 있어 15~20초 heartbeat이 안정적입니다.

서서버지기영호6개월 전

저는 proxy_read_timeout 86400s 박아두고 heartbeat은 20초로 잡습니다. 모바일 유저 많은 서비스면 15초까지 줄여도 배터리 영향 거의 없고 체감 안정성은 훨씬 좋아져요. 그리고 여러 앱 인스턴스면 sticky session도 잊지 말고요.

풀풀스택지훈6개월 전

proxy_read_timeout 3600s로 올리고 heartbeat을 20초로 줄였더니 30분 연속 테스트에서 한 번도 안 끊겼습니다. NAT rebinding 얘기 덕에 모바일 쪽 재현 방법도 감이 잡혔어요. 감사합니다!

Ctrl+Enter로 등록