웹페이지와 API는 정상인데 실시간 알림만 WebSocket connection failed로 끊긴다면 일반 HTTP 응답과 WebSocket 연결을 구분해 확인하세요. Nginx 앞뒤의 프로토콜 전환 헤더, 앱의 WebSocket 경로, 인증·Origin 검사, 유휴 시간 제한이 서로 맞아야 합니다. 먼저 연결 시작에 실패하는지, 시작 후 일정 시간이 지나 끊기는지 나누면 불필요한 설정 변경을 줄일 수 있습니다.
1. 브라우저 오류 문구보다 실제 연결 요청을 확인하세요
이 글은 일반적인 HTTP/1.1 Upgrade 방식으로 Nginx가 앱 서버에 WebSocket을 전달하는 구성을 설명합니다. MDN WebSocket 서버 안내의 핸드셰이크처럼 성공한 전환은 101 Switching Protocols 응답으로 확인할 수 있습니다. 다른 프로토콜 확장이나 특정 프레임워크의 폴링 연결은 별도 문서를 따라야 합니다.
브라우저 개발자 도구의 Network에서 실제 WebSocket 요청 URL과 응답 상태를 기록합니다. HTTPS 페이지에서는 MDN 클라이언트 안내의 보안 조건을 따라 wss:// 연결과 인증서를 확인하세요. 혼합 콘텐츠로 브라우저가 요청을 막았다면 Nginx 설정을 바꾸기 전에 콘솔의 차단 이유부터 해결해야 합니다.
| 관찰 결과 | 첫 확인 항목 |
| 요청이 보내지지 않음 | URL·혼합 콘텐츠·인증서·클라이언트 코드 |
| 200·301·404 응답 | WebSocket 경로·라우팅·리다이렉트 |
| 400·403 응답 | 전환 헤더·인증·앱의 Origin·프로토콜 검사 |
| 502 응답 | Nginx에서 앱까지 주소·포트·연결 상태 |
| 101 후 연결 종료 | 앱 종료·프록시 유휴 제한·하트비트 |
상태 코드만으로 한 원인을 확정할 수는 없습니다. 동일 시각의 Nginx와 앱 로그를 맞추고, 앞에 CDN이나 로드 밸런서가 있다면 그 구간의 응답과 제한도 확인하세요. 요청 경로나 쿼리에는 인증 정보가 포함될 수 있으므로 기록을 공유할 때 민감한 값은 제거합니다.
2. Upgrade와 Connection 헤더를 앱 서버에 전달하세요
Nginx WebSocket 프록시 안내는 Upgrade·Connection이 구간별 헤더여서 역방향 프록시에 명시적인 전달 설정이 필요하다고 설명합니다. 다음은 일반 Nginx HTTP 프록시의 예시입니다. 기존 http 블록에 병합해 사용하고, 이미 운영 중인 server·TLS 구성을 이 예시로 통째로 덮어쓰지 마세요. realtime:8080은 Nginx 환경에서 해석·접근 가능한 실제 앱 주소로 바꿔야 합니다.
http {
map $http_upgrade $ws_connection {
default upgrade;
'' close;
}
upstream realtime_app {
server realtime:8080;
}
server {
listen 80;
server_name ws.example.com;
location /ws/ {
proxy_pass http://realtime_app;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $ws_connection;
proxy_read_timeout 120s;
}
}
}
예시는 내부 HTTP 전달과 설정 위치를 설명하기 위한 조각이며 공개 HTTPS 서비스의 완성 설정이 아닙니다. 외부 wss://는 인증서와 TLS가 설정된 해당 server에서 처리해야 합니다. 버전별 기본값에 의존하지 않도록 upstream HTTP/1.1을 명시했고, 120초는 설명용 값입니다. 헤더 전달만으로 앱의 WebSocket 엔드포인트나 인증 검사를 대신할 수는 없습니다.
3. proxy_pass의 끝 슬래시와 앱 경로를 맞추세요
proxy_pass 공식 설명처럼 전달 URL에 URI를 붙이면 location에 해당하는 요청 경로가 치환됩니다. 예시의 location /ws/에서 proxy_pass http://realtime_app;는 URI를 별도로 지정하지 않아 /ws/room 같은 경로를 유지합니다. 반면 proxy_pass http://realtime_app/;라면 일반적인 이 구성에서 /room으로 바뀝니다. 어느 쪽이 맞는지는 앱이 등록한 경로에 따라 달라집니다.
Docker 안의 Nginx에서 localhost는 같은 컨테이너를 의미할 수 있습니다. 별도 앱 컨테이너가 있다면 공통 네트워크의 서비스 이름과 실제 리슨 포트를 확인하세요. 일반 upstream 연결부터 실패하면 Nginx 502와 Docker upstream 점검을 참고해 문제를 좁힐 수 있습니다. 앱 경로의 인증·쿠키·Origin 허용 목록도 함께 비교하고 보안 검사를 통째로 끄지 않습니다.
4. 101 이후 끊긴다면 유휴 시간과 하트비트를 확인하세요
proxy_read_timeout은 전체 연결 수명이 아니라 upstream에서 연속된 읽기 사이의 대기 제한입니다. Nginx의 기본값은 60초이며, 앞단의 다른 프록시나 앱도 자체 제한을 둘 수 있습니다. “항상 60초가 지나면 끊긴다”는 관찰만으로 Nginx가 유일한 원인이라고 확정하지 마세요.
앱이 연결을 유지해야 한다면 실제 메시지 간격과 프로토콜 Ping 등을 설계하고 각 구간의 제한을 맞춰야 합니다. 브라우저의 일반 WebSocket API에는 프로토콜 Ping을 직접 보내는 메서드가 없으므로, 앱 메시지를 통한 하트비트는 서버와 합의한 별도 동작입니다. 제한을 크게 늘리는 수정만으로 끊어진 연결 감지나 재접속 설계가 완료되지는 않습니다.
종료 시각, 마지막 메시지 시각, 클라이언트 close 이벤트의 코드·이유, 앱 로그를 모으세요. 초기 연결 실패에는 타임아웃을 늘려도 효과가 없을 수 있습니다. 일반 HTTP 지연과의 구분은 Nginx 504 Gateway Timeout 점검을 함께 참고하면 도움이 됩니다.
5. 설정 문법과 실제 연결을 각각 검증하세요
설정 변경 전 사본을 보관하고 Nginx 공식 초보자 안내에 따라 문법 확인 후 정상인 설정만 반영합니다. 아래는 nginx라는 컨테이너를 가정한 예입니다. 배포 도구가 구성을 관리한다면 해당 배포 방식으로 반영하세요. 문법 검사가 성공해도 WebSocket 경로와 인증이 작동한다는 뜻은 아닙니다.
docker exec nginx nginx -t
# 문법 검사가 성공하고 반영이 승인된 경우
docker exec nginx nginx -s reload
- 브라우저의 실제 요청에서 URL·전환 응답·메시지 송수신 확인
- 앱 로그와 upstream 상태를 비교해 어느 구간이 거부했는지 확인
- 유휴 상태와 주기적 메시지 상태를 나눠 예상 시간 이후까지 관찰
- 앱 재배포·네트워크 변경 후 재접속과 중복 구독 방지 확인
- 변경 전후의 응답·종료 시각·오류 로그를 비교하고 부작용 점검
일반 HTTP GET에 200이 나오는 시험은 WebSocket 전환 성공을 증명하지 않습니다. 테스트용 클라이언트도 실제 앱과 같은 경로·인증·서브프로토콜 조건으로 사용해야 합니다. 본문의 설정은 진단 방법을 설명하는 예이며 해당 도메인이나 사용자의 서버에서 실행한 결과가 아닙니다.
6. 자주 묻는 질문
웹페이지는 열리는데 WebSocket만 실패할 수 있나요?
가능합니다. 페이지 응답과 전환 요청의 경로·헤더·인증 조건이 다르므로 실제 WebSocket 요청을 따로 확인해야 합니다.
CORS 허용 헤더를 추가하면 403이 해결되나요?
일반 HTTP CORS 헤더 추가가 앱의 WebSocket Origin·인증 정책을 대신하지 않습니다. 거부한 구간과 앱의 검증 조건을 먼저 확인하세요.
proxy_read_timeout을 늘리면 모든 끊김이 해결되나요?
앱 종료·앞단 프록시 제한·브라우저 네트워크 변경·인증 만료는 별도 원인입니다. 연결 시작과 유지 단계의 증거를 나누어 판단해야 합니다.
확인 기준: 2026-10-03 Nginx·MDN 공식 문서. 예시 경로·주소·시간 제한은 실제 앱의 요구에 맞춰 검증해야 합니다.

'소프트웨어개발' 카테고리의 다른 글
| Docker bind mount permission denied 해결: 경로·UID·GID·SELinux 점검 (0) | 2026.10.04 |
|---|---|
| Amazon SES와 SendGrid 비교: 인증·주문 메일 발송 비용과 운영 기준 (0) | 2026.10.04 |
| AWS EFS와 EBS 비교: 공유 파일·컨테이너 저장소 비용과 선택 기준 (0) | 2026.10.04 |