WebSocket 완전 정복 16편 — 생태계와 대안, 그리고 시리즈 정리와 실습 과제
Socket.IO가 WebSocket이 아닌 이유부터 STOMP·GraphQL Subscriptions·SSE·HTTP/2 위 WebSocket·WebTransport·WebRTC까지 생태계와 대안을 정리하고, DevTools·wscat·k6 같은 도구, 시리즈 핵심 요약 일곱 가지와 난이도별 실습 과제 다섯 가지, 참고 문서를 담았습니다.
blog92@web:~$ grep -rl "#WebSocket" posts/
이 태그가 달린 글
Socket.IO가 WebSocket이 아닌 이유부터 STOMP·GraphQL Subscriptions·SSE·HTTP/2 위 WebSocket·WebTransport·WebRTC까지 생태계와 대안을 정리하고, DevTools·wscat·k6 같은 도구, 시리즈 핵심 요약 일곱 가지와 난이도별 실습 과제 다섯 가지, 참고 문서를 담았습니다.
전송·핸드셰이크·메시지·연결 수명·운영 다섯 묶음으로 나눈 WebSocket 보안 점검 목록입니다. wss 강제, Origin 허용 목록, maxPayload 축소, 입력 스키마 검증, 메시지별 인가, rate limit, 미인증 연결 타임아웃, 로그 마스킹, 1006 비율 모니터링까지 담았습니다.
Upgrade와 Connection이 hop-by-hop 헤더라 기본 전달되지 않는다는 사실에서 출발해 Nginx 설정을 줄 단위로 읽고, L7과 L4 로드밸런서의 차이, 파일 디스크립터와 에페메랄 포트라는 OS 한계, 메모리 산정과 Node.js 단일 이벤트 루프의 특성을 다룹니다.
느린 클라이언트 몇 개가 서버 메모리를 고갈시키는 slow consumer 문제를 bufferedAmount 임계값으로 방어하는 코드와, 메시지를 버릴지 최신값으로 덮어쓸지 연결을 끊을지 데이터 성격에 따라 정하는 정책, 그리고 반대 방향의 rate limit을 다룹니다.
연결 자체가 상태이기 때문에 서버를 늘리는 것만으로는 끝나지 않는 이유와 Redis Pub/Sub 백플레인 구현을 코드로 살펴보고, Redis·NATS·Kafka 선택지, 스티키 세션이 보통 불필요한 이유, 연결 불균형과 무중단 배포, 프레즌스 관리까지 다룹니다.
Sec-WebSocket-Protocol로 애플리케이션 프로토콜과 버전을 핸드셰이크 단계에서 협상하는 법과 협상이 어긋났을 때의 동작, 그리고 permessage-deflate 압축 확장이 주는 이득과 연결당 컨텍스트 메모리·CPU·CRIME류 위험이라는 대가를 다룹니다.
쿠키·쿼리스트링 토큰·티켓·첫 메시지 네 가지 인증 방식을 주의사항과 함께 비교하고, Upgrade 단계에서 Origin을 검사하고 일회용 티켓을 소모하는 서버 코드, CORS가 적용되지 않아 생기는 CSWSH 공격의 원리, 그리고 연결 이후의 인가와 토큰 재검증을 다룹니다.
연결은 반드시 끊긴다는 전제에서 출발해 thundering herd를 막는 지수 백오프와 full jitter, 재연결하면 안 되는 상황을 코드로 구분하는 법, 그리고 스냅샷·seq 재전송·하이브리드 세 가지 상태 복구 방식과 그에 필요한 저장소를 다룹니다.
WebSocket이 메시지의 의미를 정해 주지 않으므로 직접 설계해야 하는 애플리케이션 프로토콜을 다룹니다. 타입 유니온으로 표현한 봉투 형식, 요청-응답을 잇는 correlation id, 재연결 복구의 토대가 되는 seq, 버전 관리 원칙과 RPC 클라이언트 구현을 담았습니다.
half-open 연결과 유휴 타임아웃 때문에 하트비트가 필요한 이유, ws로 구현하는 서버 주도 Ping/Pong과 주기를 정하는 기준, 그리고 1000부터 4999까지 Close 코드 표와 실무에서 가장 흔한 1006의 원인을 다룹니다.
WebSocket 프레임의 비트 레이아웃을 도식으로 읽고 FIN·RSV·opcode·Payload len·Masking-key를 필드별로 해설한 뒤, 클라이언트에서 서버로 가는 프레임만 마스킹하는 이유가 프록시 캐시 오염 방지라는 점과 학습용 파서 코드를 다룹니다.
Node.js의 ws 라이브러리로 연결을 받고 모든 클라이언트에 브로드캐스트하는 30줄짜리 서버를 만들고, wscat으로 터미널 두 개를 열어 확인하는 법, 그리고 maxPayload 기본값 100MiB를 처음부터 줄여 둬야 하는 이유를 다룹니다.
브라우저 WebSocket 객체의 생성·전송·종료를 예제로 훑고, readyState 네 상태와 bufferedAmount·protocol 속성의 쓰임, 그리고 임의 헤더를 붙일 수 없다는 제약과 onerror 대신 onclose의 코드로 판단해야 하는 이유를 다룹니다.
클라이언트의 Upgrade 요청 헤더와 서버의 101 Switching Protocols 응답을 줄 단위로 읽고, Sec-WebSocket-Accept가 고정 GUID와 SHA-1으로 계산되는 과정을 코드로 확인한 뒤, 이 절차가 보안 장치가 아니라는 사실과 101 이후 이 연결이 더는 HTTP가 아니라는 사실을 다룹니다.
WebSocket이 RFC 6455로 표준화되기까지의 경로와 Sec-WebSocket-Version 13에 남은 흔적, ws와 wss의 기본 포트·URI 규칙, 평문 Upgrade가 중간 장비에서 망가지는 이유, 그리고 핸드셰이크에서 Close까지 연결의 생애주기를 다룹니다.
HTTP가 서버에서 먼저 말을 걸 수 없다는 제약에서 출발해 Short Polling·Long Polling·SSE·WebSocket 네 가지 선택지를 장단점으로 비교하고, 전이중·연결 유지·메시지 단위라는 WebSocket의 핵심 세 가지와 SSE로 충분한 경우의 선택 기준을 다룹니다.
Polling·SSE·WebSocket·WebRTC를 요구사항 기준으로 비교하고, Nginx 버퍼링과 Upgrade 헤더, "정확히 60초마다 끊김"의 원인, WebRTC 시그널링과 STUN/TURN/SFU의 네트워크 포인트를 다룬다.