TIL - 20250916

juni·2025년 9월 16일

TIL

목록 보기
127/316

0916 Full-Stack: Real-time Presence and Architectural Refinements


✅ 1. 백엔드(BE): WebSocket 생명주기 관리 및 시스템 메시징

  • 단순히 메시지를 주고받는 것을 넘어, 사용자의 연결(connect), 구독(subscribe), 연결 해제(disconnect)와 같은 WebSocket의 생명주기 이벤트를 감지하고, 이를 활용하여 시스템 전체에 의미 있는 정보를 전달하는 기능을 구현했습니다.

➕ 주요 개념

  1. WebSocketEventsListener:

    • 역할: Spring의 ApplicationListener를 사용하여 STOMP 세션의 주요 이벤트를 감지하는 중앙 리스너입니다.
    • SessionSubscribeEvent: 사용자가 특정 STOMP 토픽(e.g., 채팅방)을 구독할 때 발생하는 이벤트를 가로챕니다.
    • SessionDisconnectEvent: 사용자의 WebSocket 연결이 끊어질 때 발생하는 이벤트를 가로챕니다.
  2. 시스템 메시지 브로드캐스팅:

    • WebSocketEventsListener는 위 이벤트를 감지한 후, 해당 채팅방을 구독 중인 모든 클라이언트에게 "OOO님이 입장하셨습니다." 또는 "OOO님이 퇴장하셨습니다."와 같은 시스템 메시지를 브로드캐스트합니다.
    • 이를 통해 채팅방에 참여한 모든 사용자가 현재 참여자 현황을 실시간으로 인지할 수 있습니다.

✅ 2. 백엔드(BE): 세션 관리 및 Presence(상태 표시) 기능 구현

  • 사용자가 여러 탭을 열거나 재연결할 때 중복된 입장/퇴장 메시지가 발생하는 문제를 해결하고, 사용자의 현재 상태(온라인, 공부 중 등)를 실시간으로 공유하는 Presence 기능을 구현했습니다.

➕ 주요 개념

  1. UserSessionRegistry (세션 레지스트리):

    • 역할: 어떤 사용자가 어떤 세션 ID를 통해 어떤 채팅방에 참여하고 있는지를 서버 메모리에 실시간으로 기록하고 관리하는 중앙 등록소입니다.
    • 중복 방지: WebSocketEventsListener는 입장/퇴장 메시지를 브로드캐스트하기 전에, 먼저 이 레지스트리를 확인합니다. 만약 사용자가 이미 해당 방에 등록되어 있다면, 중복된 입장 알림을 보내지 않습니다. 이를 통해 알림의 정확성을 보장합니다.
  2. PresenceService 및 상태 관리:

    • 개념: 사용자의 현재 상태(e.g., ONLINE, STUDYING, BREAK, OFFLINE)를 관리하는 서비스입니다.
    • 상태 변경: 사용자는 프론트엔드에서 자신의 상태를 변경할 수 있습니다. 이 요청은 별도의 STOMP 엔드포인트(@MessageMapping)를 통해 PresenceController로 전달됩니다.
    • 상태 업데이트: PresenceControllerPresenceService를 호출하여 사용자의 상태를 변경하고, 이 변경 사항을 해당 스터디룸이나 관련 사용자들에게 실시간으로 브로드캐스트합니다.
    • 자동 상태 변경: WebSocketEventsListener는 사용자가 채팅방에 입장(subscribe)하면 상태를 STUDYING으로, 연결이 끊어지면(disconnect) OFFLINE으로 자동으로 변경하는 로직을 포함하여 Presence 정보의 신뢰성을 높였습니다.

✅ 3. 백엔드(BE): 서비스 계층 리팩토링 (관심사 분리)

  • 기존의 ChatSocketService가 메시지를 DB에 저장하는 책임과 다른 사용자에게 브로드캐스트하는 책임을 모두 가지고 있어 비대해지는 문제를 해결하기 위해, 관심사 분리(Separation of Concerns) 원칙에 따라 서비스를 리팩토링했습니다.
  1. ChatMessageWriteService: 오직 채팅 메시지를 데이터베이스에 저장(Write)하는 책임만 가집니다.
  2. ChatBroadcastService: 오직 채팅 메시지를 WebSocket 브로커를 통해 브로드캐스트(Broadcast)하는 책임만 가집니다.
  3. ChatSocketService (Coordinator): 이제 이 서비스는 직접 로직을 수행하는 대신, WriteServiceBroadcastService를 순서대로 호출하는 조정자(Coordinator) 역할을 수행합니다. 이를 통해 각 서비스의 역할이 명확해지고, 코드의 테스트 용이성과 유지보수성이 크게 향상되었습니다.

✅ 4. 프론트엔드(FE): 전역 상태 관리 및 실시간 UI 업데이트

  • 백엔드에서 오는 다양한 실시간 메시지(채팅, 시스템, Presence)를 효율적으로 처리하고 UI에 반영하기 위해 프론트엔드 아키텍처를 개선했습니다.

➕ 주요 개념

  1. Zustand ChatStore:

    • 역할: 특정 채팅방의 메시지 목록을 관리하는 전역 스토어입니다.
    • 상태 중앙화: WebSocket을 통해 수신되는 모든 메시지(일반, 시스템)는 이 스토어의 상태 배열에 추가됩니다. MessageList 컴포넌트는 이 스토어를 구독하여 항상 최신 메시지 목록을 렌더링합니다.
    • 메모리 관리: 사용자가 채팅방을 나갈 때(컴포넌트 언마운트), 스토어의 메시지 배열을 초기화하는 정리(cleanup) 로직을 추가하여 메모리 누수를 방지했습니다.
  2. 실시간 UI 피드백:

    • 시스템 메시지 UI: MessageList 컴포넌트는 메시지 타입을 구분하여, 시스템 메시지("입장/퇴장")는 일반 채팅 버블과 다른 스타일(e.g., 중앙 라벨)로 렌더링하는 MessageSystemItem을 사용합니다.
    • 토스트 알림: 더 나은 사용자 경험을 위해, 중요한 시스템 메시지(입장/퇴장)는 채팅 목록뿐만 아니라 화면 상단에 토스트 알림으로도 표시하여 사용자가 즉시 인지할 수 있도록 했습니다.
    • Presence UI: 참여자 목록 컴포넌트는 Presence 관련 WebSocket 메시지를 구독하여, 사용자의 상태가 변경될 때마다 UI(e.g., 프로필 옆 상태 아이콘)를 실시간으로 업데이트합니다.

📌 요약

  • 백엔드WebSocket 생명주기 이벤트 리스너세션 레지스트리를 통해 사용자의 입장/퇴장을 정확하게 감지하고, 이를 시스템 메시지로 브로드캐스트하는 기능을 구현했습니다.
  • 사용자의 실시간 상태를 공유하는 Presence 기능을 추가하고, 서비스 계층을 관심사에 따라 분리하여 백엔드 아키텍처의 확장성과 유지보수성을 높였습니다.
  • 프론트엔드Zustand 전역 스토어를 통해 복잡한 실시간 채팅 상태를 중앙에서 관리하고, 토스트 알림실시간 Presence UI 업데이트를 통해 사용자 경험을 크게 향상시켰습니다.

0개의 댓글