웹소켓은 기본적으로 TCP 기반의 지속적인 연결 상태를 유지하지만, 연결이 실제로 살아있는지는 네트워크 단절, 브라우저 종료, 서버 다운 등 다양한 원인으로 예기치 않게 끊길 수 있기 때문에, 명시적으로 연결 상태를 확인하는 로직이 필요합니다.
이를 확인하는 방법으로는 대표적으로 다음과 같은 방식들을 사용합니다
일정 주기로 클라이언트가 서버에 Ping 메시지를 보내고, 서버는 Pong으로 응답합니다.
응답이 없으면 연결이 끊어진 것으로 간주하여 재연결을 시도합니다.
예: STOMP에서는 heart-beat 설정이 대표적입니다.
클라이언트에서는 onclose, onerror 이벤트 리스너를 통해 연결 종료 여부를 감지합니다.
서버 측에서도 세션 상태를 추적하며, 종료된 세션을 정리하거나 reconnect 로직을 유도할 수 있습니다.
따라서, 웹소켓 연결이 살아있다는 보장을 위해서는 단순히 연결 여부를 믿는 것이 아니라, 클라이언트와 서버 양쪽에서 정기적인 하트비트나 핑/퐁 메시지를 통해 연결 상태를 능동적으로 확인하고, 끊겼을 때 재연결 로직까지 구현하는 것이 중요하다고 생각합니다.
웹소켓은 기본적으로 TCP 기반 프로토콜이라 패킷 자체가 유실되는 경우는 거의 없습니다.
하지만 실제 애플리케이션에서는 다음과 같은 상황에서 메시지 유실이 발생할 수 있습니다:
- 클라이언트가 연결 종료 직전 메시지를 못 받았을 때
- 서버가 비정상 종료되었을 때
- 브라우저 탭이 갑자기 닫혔을 때
- 네트워크 지연/단절 후 자동 복구가 안 된 경우
이런 실질적인 "메시지 유실"을 방지하기 위한 보완 방법으로는 다음과 같은 전략을 사용합니다
연결이 끊긴 후 재연결되었을 때, 클라이언트는 서버에 "마지막으로 받은 메시지 ID"를 보내고, 누락된 메시지를 요청합니다.
→ 이 기능을 위해 서버에 단기 메시지 캐시 또는 로그 저장소가 필요합니다. (ex. Redis, Kafka, DB 등)
클라이언트가 메시지를 수신하면 "받았다"는 ACK 메시지를 서버에 전송하고,
서버는 ACK가 올 때까지 재전송 시도 또는 대기 상태 유지.
→ 실시간성보다 신뢰성 위주인 시스템에서 사용 (ex. 금융 채팅, 알림 등)
유실된 메시지를 REST API 등을 통해 다시 받아올 수 있도록 구성 (CQRS 구조 활용)
예: 과거 채팅 메시지 또는 알림 내역을 WebSocket과 별도로 HTTP로 조회
요약하자면, 웹소켓 자체는 TCP 기반이라 유실 확률이 낮지만, 클라이언트 또는 서버의 상태 변화, 네트워크 문제 등으로 인해 애플리케이션 수준의 메시지 유실은 언제든 발생할 수 있습니다.
이를 보완하기 위해서는 메시지 ID + 재전송 + ACK + 캐시 저장소 조합을 통해 신뢰성을 높이는 전략이 중요하다고 생각합니다.