WebSockets를 이용한 실시간 앱 구축하기
폴링(Polling)은 앱에 좋지 않습니다.
예전에 AJAX 폴링을 사용하여 채팅 위젯을 만든 적이 있습니다. 앱이 1초마다 서버에 새 메시지가 있는지 묻도록 설정했습니다. 작동은 했지만 느렸습니다. UI는 버벅거리는 느낌이었고, 서버는 너무 과하게 일했습니다. 대부분의 요청은 빈 데이터를 반환했습니다. 마치 티스푼으로 욕조에 물을 채우려는 것 같았습니다.
WebSockets는 이를 바꿔 놓습니다.
지속적인 요청 대신, 하나의 지속적인 연결을 엽니다. 이를 통해 양방향 데이터 흐름이 가능해집니다. 서버는 클라이언트에 즉시 데이터를 푸시할 수 있고, 클라이언트는 서버에 즉시 데이터를 보낼 수 있습니다.
왜 WebSockets를 사용해야 할까요?
• 지연 시간(Latency)이 수백 밀리초에서 수십 밀리초로 줄어듭니다. • 서버 부하를 예측할 수 있게 됩니다. • 반복되는 HTTP 헤더를 제거하여 대역폭을 절약할 수 있습니다. • 채팅, 실시간 알림, 멀티플레이어 게임 등에 적합합니다.
작동 방식:
연결은 HTTP 업그레이드 요청으로 시작됩니다. 서버가 동의하면 101 상태 코드를 보냅니다. 그 이후에는 가공되지 않은(raw) 바이너리 또는 텍스트 프로토콜을 사용합니다. 더 이상 속도를 늦추는 쿠키나 헤더가 없습니다.
피해야 할 흔한 함정들:
- 연결 끊김: 네트워크는 실패할 수 있습니다. 지수 백오프(exponential backoff)와 같은 재시도 전략을 구현해야 합니다.
- 메모리 누수: 사용자가 떠날 때는 항상 소켓을 닫으세요. 좀비 연결은 서버 메모리를 잡아먹습니다.
- 메시지 루프: 메시지를 브로드캐스팅할 때 원래 발신자는 제외하세요. 그렇지 않으면 사용자가 자신의 메시지를 두 번 보게 됩니다.
- 유휴 연결: 일부 프록시는 조용한 연결을 끊어버립니다. 소켓을 활성 상태로 유지하려면 핑/퐁(ping/pong) 하트비트를 사용하세요.
무언가 변했는지 서버에 계속 묻는 것을 멈추세요. 필요할 때마다 대화할 수 있도록 연결 통로를 열어두기 시작하세요.
여러분의 도전 과제:
기본적인 채팅 예제를 하나 가져와 보세요. "typing..."(입력 중...) 표시를 추가해 보세요. Render나 Fly.io 같은 호스트에 배포해 보세요. 폴링 없이 실시간으로 해당 표시가 움직이는 것을 확인하는 순간, 여러분의 실력은 한 단계 업그레이드될 것입니다.