"WebSocket은 REST를 대체하는 상위 버전이 아니야. 양쪽이 하나의 연결에서 서로 독립적으로 메시지를 보내야 한다는 요구에 답하는 별도의 도구지. 요청과 응답, 단방향 스트림, 전이중 채널의 경계를 알면 필요 이상의 복잡성도 부족한 설계도 피할 수 있어."
요청과 응답에서 전이중 연결까지
통신 패턴을 단순한 쪽부터 나열하면 다음과 같아:
- REST 요청과 응답 — 클라이언트가 요청하고 서버가 응답하면 교환이 끝나. 리소스 생성·조회·수정·삭제와 일회성 명령에 잘 맞아.
- 고정 주기 폴링 — 같은 조회를 일정 간격으로 반복해. 몇 초의 지연을 허용할 수 있고 단순성이 중요할 때 유용해.
- 롱 폴링 — 서버가 이벤트나 시간 만료까지 응답을 보류해. 낮은 알림 지연을 얻는 대신 오래 대기하는 요청을 관리해야 해.
- SSE — HTTP 응답 하나에 서버 이벤트를 계속 기록하는 단방향 스트림이야. AI 응답, 알림, 실시간 로그에 잘 맞아.
- WebSocket — 하나의 장기 연결에서 양쪽이 서로 기다리지 않고 메시지를 보낼 수 있는 전이중 채널이야.
뒤로 갈수록 무조건 더 좋은 것이 아니라 연결 상태와 복구, 용량 계획 같은 운영 책임이 늘어나. 필요한 통신 모양을 만족하는 가장 단순한 방식을 고르는 게 핵심이야.
WebSocket을 검토할 판단 기준
1. 트래픽 방향. 클라이언트가 보통의 HTTP 요청과 별개로 서버에 자주 실시간 메시지를 보내야 하는지 살펴봐. 입력 중 표시, 멀티플레이어 입력, 협업 커서 위치는 양방향 채널의 이점이 커. 반면 사용자가 요청 하나를 보내고 서버 응답만 길게 받는 AI 채팅은 일반 POST와 SSE 조합으로 충분할 수 있어.
2. 지연과 전달 방식. 특정 숫자 하나로 프로토콜이 결정되지는 않아. SSE도 서버에서 클라이언트로 낮은 지연의 이벤트를 보낼 수 있어. 양쪽이 독립적으로 빠르게 반응해야 하고, 매번 새 HTTP 요청을 만드는 왕복과 헤더 비용이 실제 병목이 되는지를 측정해야 해.
3. 메시지 빈도와 연결 상태. 클라이언트가 초당 여러 번 작은 상태 변화를 보내는 게임이나 공동 편집은 WebSocket에 잘 맞아. 드문 알림이나 상태 변경은 SSE나 폴링으로 더 단순하게 처리할 수 있어. 순서, 재연결 후 복구, 느린 소비자에 대한 정책도 함께 설계해야 해.
세 기준은 체크박스 하나로 결론 내리는 시험이 아니야. 방향과 빈도, 요구되는 전달 의미, 프록시 지원, 운영 인력을 함께 따져 WebSocket의 이점이 연결 관리 비용보다 큰지 판단해야 해.
고전적인 HTTP/1.1 WebSocket 핸드셰이크
널리 쓰이는 HTTP/1.1 방식에서는 클라이언트가 업그레이드 헤더를 담은 요청을 보내고, 서버가 이를 수락하면 101 Switching Protocols로 응답해. 그 뒤 같은 TCP 연결에서 HTTP 메시지 대신 WebSocket 프레임을 주고받아:
GET /ws/chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
101 응답 뒤에는 양쪽이 작은 이진 헤더와 페이로드로 이루어진 WebSocket 프레임을 교환해. 한쪽이 닫기 핸드셰이크를 시작하거나 네트워크가 끊길 때까지 연결이 유지돼. HTTP/2에서는 확장 CONNECT를 사용하는 별도 부트스트랩 방식도 있으므로 모든 환경이 101 응답만 쓰는 것은 아니야.
상태 API와 실시간 채널을 함께 쓰기
많은 서비스는 REST와 WebSocket을 역할별로 조합해. 로그인, 기록 조회, 초안 저장처럼 재조회 가능한 상태와 명령은 REST 리소스로 다루고, 채팅 이벤트, 공동 편집, 접속 상태처럼 즉시 전파해야 하는 변화는 WebSocket으로 전달해. 영구 상태를 실시간 연결에만 가두지 않으면 재연결한 클라이언트가 REST로 기준 상태를 다시 가져오고 이후 이벤트를 이어 받을 수 있어.