실시간 알림에 웹소켓(Socket.IO)을 쓰는데, 연결은 잘 되다가 1분 정도 조용하면 툭 끊깁니다. 로컬에서 앱에 직접 붙으면 안 끊기는데, nginx 리버스 프록시를 통하면 이래요. 클라이언트는 자동 재연결돼서 동작은 하지만, 끊길 때마다 알림이 잠깐 누락돼서 문제입니다.
실시간 알림에 웹소켓(Socket.IO)을 쓰는데, 연결은 잘 되다가 1분 정도 조용하면 툭 끊깁니다. 로컬에서 앱에 직접 붙으면 안 끊기는데, nginx 리버스 프록시를 통하면 이래요. 클라이언트는 자동 재연결돼서 동작은 하지만, 끊길 때마다 알림이 잠깐 누락돼서 문제입니다.
댓글 2
nginx 리버스 프록시 뒤 웹소켓의 아주 전형적인 증상입니다. 원인은 nginx의 프록시 타임아웃이에요. 기본값이 60초라, 60초 동안 데이터가 안 오가면 nginx가 "죽은 연결"로 보고 끊어버립니다.
1. 웹소켓 업그레이드 헤더 + 타임아웃
2. 앱 레벨 heartbeat (더 근본적)Upgrade/Connection헤더가 없으면 애초에 웹소켓 핸드셰이크가 일반 HTTP로 격하돼 폴링으로만 동작합니다. 이미 연결은 된다고 하셨으니 이 부분은 있을 거고, 끊김의 직접 원인은proxy_read_timeout입니다.타임아웃을 늘리는 것만으로는 부족할 때가 있어요. 주기적으로 ping을 보내 연결을 "살아있게" 유지하는 게 정석입니다. Socket.IO는 기본 heartbeat가 있지만 간격을 프록시 타임아웃보다 짧게 맞춰야 합니다.
ping 간격(25초)이 nginx 타임아웃(위에서 3600초로 늘렸지만, 안 늘렸다면 60초)보다 짧으면 연결이 유휴로 판정되지 않습니다.
정리proxy_read_timeout을 늘리고 + 앱 heartbeat 간격을 프록시 타임아웃보다 짧게 — 이 조합이면 유휴 끊김이 사라집니다.