WebSocket 완전 정복 · 3부. 심화: 확장, 인프라, 운영, 보안 · 16편 중 13편
이전 편: 12편 — 수평 확장
12편에서 서버를 여러 대로 늘려 연결을 나눠 받았습니다. 이번 편은 그 연결 하나하나의 속도 차이를 다룹니다 — 서버가 보내는 속도를 클라이언트가 따라오지 못할 때 무슨 일이 생기고, 무엇을 버리고 무엇을 지킬지를 어떻게 정하는지.
slow consumer — 느린 클라이언트가 서버를 무너뜨린다
서버가 클라이언트 수신 속도보다 빨리 보내면 메모리에 데이터가 쌓입니다. 느린 클라이언트 몇 개가 서버 메모리를 고갈시킬 수 있습니다(slow consumer).
bufferedAmount로 방어하기
ts
const HIGH_WATER = 1 * 1024 * 1024; // 1MB
function safeSend(ws: WebSocket, data: string) {
if (ws.readyState !== WebSocket.OPEN) return;
if (ws.bufferedAmount > HIGH_WATER) {
// 정책 선택:
// (a) 이 메시지 버리기 (실시간 시세처럼 최신값만 의미 있을 때)
// (b) 최신 상태로 덮어쓰기 (conflation)
// (c) 연결 끊기 (계속 못 따라오는 클라이언트)
ws.close(1013, "slow consumer"); // 1013: Try Again Later
return;
}
ws.send(data);
}데이터 성격에 맞는 정책
- 최신값만 중요한 데이터(시세, 센서, 게이지): conflation(중간값 버리고 최신값만).
- 유실 불가 데이터(채팅): 버리지 말고 끊은 뒤 seq 재전송으로 복구.
- 반대 방향: 연결별 rate limit(토큰 버킷), 초과 시 1008.
더 깊이
- 풀스택 개발자를 위한 네트워크 12장 — 네트워크 성능과 안정성 설계: 타임아웃, 재시도와 백오프, 커넥션 풀 같은 네트워크 전반의 안정성 설계입니다. 느린 소비자 문제를 연결 하나 밖으로 꺼내 그 축 위에서 다시 보는 데 좋습니다.
- 15편 — 보안 체크리스트: 마지막 줄의 연결별 rate limit과 1008이 보안 점검 항목으로 다시 나옵니다.