TIL - 20250920

juni·2025년 9월 19일

TIL

목록 보기
131/317

0920 Full-Stack: Real-time Communication Systems (WebSocket & SSE)


✅ 1. WebSocket & STOMP: 양방향 실시간 통신 구축

  • 서버와 클라이언트가 지속적인 연결을 통해 실시간으로 데이터를 주고받는 양방향(Bidirectional) 통신 채널을 구축하기 위해 WebSocket 기술을 도입했습니다.
  1. WebSocket: HTTP와 달리 하나의 TCP 연결 위에서 양방향 데이터 전송을 지원하는 독립적인 프로토콜입니다. 실시간 채팅 기능의 기반이 됩니다.
  2. STOMP: 순수 WebSocket의 복잡성을 줄여주는 상위 레벨 메시징 프로토콜입니다. "구독(Subscribe)""발행(Publish)"이라는 직관적인 모델을 제공하여, 메시지 브로커를 통해 특정 주제(Topic)를 중심으로 메시지를 쉽게 주고받을 수 있게 합니다.

✅ 2. WebSocket 연결 보안 및 생명주기 관리

  • 단순히 메시지를 주고받는 것을 넘어, WebSocket 연결을 안전하게 인증하고, 사용자의 연결 상태 변화를 감지하여 시스템 전체에 의미 있는 정보를 전달하는 기능을 구현했습니다.
  1. JWT 기반 인증 (Handshake Interceptor):

    • WebSocket 연결은 최초에 HTTP "핸드셰이크(Handshake)" 과정을 거쳐 수립됩니다. 이 요청을 가로채는 인터셉터를 구현하여, 클라이언트가 보낸 Http-Only 쿠키(JWT 포함)의 유효성을 검증했습니다.
    • 인증에 성공하면, 해당 사용자 정보가 WebSocket 세션에 안전하게 연결되어, 이후 모든 메시지는 인증된 사용자의 메시지로 간주됩니다.
  2. WebSocket 생명주기 관리 (WebSocketEventsListener):

    • Spring의 이벤트 리스너를 사용하여 STOMP 세션의 주요 이벤트(구독, 연결 해제)를 감지했습니다.
    • 이 이벤트를 기반으로 "OOO님이 입장/퇴장하셨습니다."와 같은 시스템 메시지를 해당 채팅방에 브로드캐스트하여, 모든 참여자가 실시간으로 현황을 인지할 수 있도록 했습니다.
  3. 세션 관리 및 중복 방지 (UserSessionRegistry):

    • 어떤 사용자가 어떤 세션으로 어떤 방에 참여 중인지를 서버 메모리에 기록하는 중앙 등록소를 구현했습니다.
    • 이를 통해 사용자가 여러 탭을 여는 등의 이유로 중복된 입장/퇴장 알림이 발생하는 것을 방지하여 알림의 정확성을 보장했습니다.

✅ 3. Presence(상태 표시) 기능 및 서비스 아키텍처 개선

  • 사용자의 현재 상태(온라인, 공부 중 등)를 실시간으로 공유하는 Presence 기능을 구현하고, 백엔드 서비스의 구조를 개선했습니다.
  1. Presence 기능:

    • 사용자는 STOMP 엔드포인트를 통해 자신의 상태를 변경할 수 있습니다.
    • WebSocketEventsListener는 사용자의 연결/해제 이벤트에 따라 상태를 자동으로 STUDYING 또는 OFFLINE으로 변경합니다.
    • 이 상태 변경 정보는 관련 사용자들에게 실시간으로 브로드캐스트되어 UI에 반영됩니다.
  2. 서비스 계층 리팩토링 (관심사 분리):

    • 기존의 비대했던 채팅 서비스를 ChatMessageWriteService(DB 저장 책임)와 ChatBroadcastService(메시지 전송 책임)로 분리했습니다.
    • 기존 서비스는 두 서비스를 순서대로 호출하는 조정자(Coordinator) 역할만 수행하게 되어, 각 서비스의 역할이 명확해지고 코드의 테스트 용이성과 유지보수성이 크게 향상되었습니다.

✅ 4. SSE(Server-Sent Events): 단방향 실시간 알림 시스템

  • 채팅 외에, 서버에서 클라이언트로 단방향(Unidirectional) 알림을 보내기 위해 SSE 기술을 도입했습니다.
  1. SSE의 특징: HTTP 기반으로 동작하며, 서버가 클라이언트에게 지속적으로 데이터 스트림을 보낼 수 있습니다. WebSocket보다 가볍고, 브라우저의 자동 재연결을 지원하는 장점이 있습니다.
  2. 구현: Spring의 SseEmitter를 사용하여 각 클라이언트와의 연결을 관리하고, 특정 이벤트(e.g., 스터디룸 입장)가 발생했을 때 NotificationService를 통해 관련 사용자들에게 실시간 알림을 전송했습니다.

📌 요약

  • 양방향 실시간 통신이 필요한 채팅 기능은 WebSocket과 STOMP를 기반으로 구축했으며, 핸드셰이크 인터셉터를 통해 JWT로 연결을 안전하게 인증했습니다.
  • WebSocket의 생명주기 이벤트를 감지하여 시스템 메시지Presence(상태 표시) 기능을 구현하고, 세션 레지스트리로 알림의 정확성을 높였습니다.
  • 단방향 데이터 스트리밍이 필요한 알림 기능은 SSE 기술을 사용하여 효율적으로 구현했습니다.
  • 백엔드 서비스는 관심사 분리 원칙에 따라 리팩토링하여 코드의 품질을 향상시켰습니다.

0개의 댓글