천만 명 브로드캐스트 아키텍처: WebSockets와 SSE(Server-Sent Events) 커넥션 레이어의 딜레마
증권사 MTS(모바일 트레이딩) 앱의 메인 호가창 서버가 급락장 사이드카(Sidecar) 발동 시점에 접속자 폭주로 무너져 내린 메멘토 모리와 같은 날이 있었습니다. 원인은 모든 유저의 단말과 서버 사이에 양방향 WebSockets 커넥션이 무겁게 맺어져 있었기 때문이었습니다.
웹소켓은 클라이언트와 서버가 서로 자유롭게 말을 건네기 위한 프로토콜(Full Duplex)입니다. 이를 위해 핸드셰이크가 터널링되며 전용 프론트엔드 프레임들을 유지하느라 각 소켓 당 TCP 오버헤드와 메모리를 과다하게 소비합니다. 그런데 주식 호가창의 도메인 특성을 재분석해 보니, 사용자가 서버로 "내 호가 내놔"라고 메시지를 쏠 일은 아예 없으며 오직 "서버가 시세 변동을 무차별로 브로드캐스트" 하는 일만 일어나고 있었습니다(단방향). 양방향이라는 오버스펙이 서버의 목을 조르고 있던 것입니다.
저희는 즉시 아키텍처를 웹소켓에서 SSE(Server-Sent Events)로 전면 이관했습니다. SSE는 일반적인 HTTP GET 요청 하나를 보낸 뒤 끊지 않고 유지(Keep-Alive)하면서, 서버가 text/event-stream 포맷으로 문자열 조각만을 끝없이 밀어내는 극도로 단순하고 우아한 단방향 프로토콜입니다. HTTP 규격을 그대로 사용하므로 브라우저 내장 EventSource API로 즉시 수신되며, 로드 밸런서의 압박, 복잡한 핑퐁 유지비, 메모리 파편화 문제가 순식간에 소거되었습니다. 커넥션 유지 비용은 절반 이하로 극감했고, 동일 스펙 노드로 감당 가능한 동시 접속자 수는 3배 펌핑되었습니다. 무조건 실시간이라고 양방향 고도화 기술(WebSocket)에 맹목적으로 집착했던 저의 오만함을, 단방향 원초적 기술(SSE)의 문제 해결력으로 부수게 된 계기였습니다.
Related Posts
JVM JIT 컴파일러의 극단적 런타임 최적화: 탈출 분석(Escape Analysis)과 스칼라 치환의 마법
정적 컴파일 언어를 압도하는 자바 머신의 동적 스크립트 프로파일링 및 객체 힙 버림 최적화 기법.
리눅스 eBPF와 XDP를 활용한 커널 바이패스(Kernel Bypass) 초저지연 패킷 필터링 아키텍처
운영체제 네트워크 스택의 병목을 우회하여 디바이스 드라이버 레벨에서 직접 샌드박스 코드를 주입하는 eBPF의 혁명.
스플릿 브레인(Split-Brain) 붕괴를 막는 분산 락(Distributed Lock) 시스템과 펜싱(Fencing) 토큰의 도입
Zookeeper, Redis Redlock의 시계 위임 맹점을 찌르는 가비지 컬렉션 시간 정지(Stop-the-World) 현상 롤백 설계.