개발일기/TIL(Since24.04.19)

WebSocket을 통한 실시간 데이터 통신

w.llama 2025. 5. 17. 21:15

WebSocket 구동 원리

WebSocket은 클라이언트와 서버 간의 양방향 실시간 통신을 가능하게 하는 프로토콜입니다. 기본적인 연결 과정은 다음과 같습니다.

연결 설정 과정

  1. HTTP 핸드셰이크 시작
    • 클라이언트가 서버에 HTTP/1.1 요청을 보냅니다
    • 요청 헤더에 Upgrade: websocket과 Connection: Upgrade를 포함합니다
  2. 프로토콜 업그레이드
    • 서버가 WebSocket 연결을 수락하면 HTTP 101 상태 코드를 반환합니다
    • 이후 HTTP 프로토콜에서 WebSocket 프로토콜로 전환됩니다
  3. 실시간 통신 시작
    • 연결이 설정되면 클라이언트와 서버 간에 양방향 데이터 전송이 가능해집니다
    • TCP 연결을 유지하면서 지속적인 통신이 이루어집니다
클라이언트 -> 서버: GET /chat HTTP/1.1
                   Upgrade: websocket
                   Connection: Upgrade
                   
서버 -> 클라이언트: HTTP/1.1 101 Switching Protocols
                   Upgrade: websocket
                   Connection: Upgrade

Pub/Sub 통신 방식

WebSocket 기반 시스템에서는 주로 Publisher/Subscriber 패턴을 사용하여 효율적인 메시지 배포를 구현합니다.

STOMP 프로토콜

STOMP(Simple Text Oriented Messaging Protocol)는 WebSocket 위에서 동작하는 메시징 프로토콜로, Pub/Sub 패턴을 구현하는 데 널리 사용됩니다.

STOMP의 특징

  • 텍스트 기반 프로토콜: 사람이 읽기 쉬운 형태
  • 프레임 구조: 명령어, 헤더, 바디로 구성된 메시지 형식
  • 표준화된 명령어: CONNECT, SUBSCRIBE, SEND, DISCONNECT 등

주요 STOMP 명령어

CONNECT
host:localhost
login:guest
passcode:guest

SUBSCRIBE
id:sub-0
destination:/topic/matching

SEND
destination:/topic/chat/room-123
content-type:application/json

{"message": "안녕하세요!", "userId": "user123"}

Pub/Sub 아키텍처의 특징

  • 발행자(Publisher): 메시지를 특정 토픽으로 발행
  • 구독자(Subscriber): 관심 있는 토픽을 구독하여 메시지 수신
  • 브로커(Broker): 메시지 라우팅 및 배포 관리
  • 토픽(Topic): 메시지를 분류하는 채널 역할

장점

  • 확장성: 새로운 구독자 추가가 용이
  • 유연성: 동적인 구독/구독 해제 가능
  • 효율성: 필요한 클라이언트에게만 메시지 전송
  • 표준화: STOMP를 통한 일관된 메시징 인터페이스

프로젝트 구현 사례: 매칭 + 채팅 시스템

백엔드 config

시스템 아키텍처

[클라이언트] <-- WebSocket + STOMP --> [STOMP 브로커] <-- 메시지 큐
     |                                         |
     +-- /user/queue/matching 구독             +-- 개별 매칭 알림
     +-- /user/queue/errors 구독               +-- 에러 처리
     +-- /user/queue/review 구독               +-- 리뷰 알림
     +-- /user/chat/chattingRoomId-{uuid} 구독 +-- 채팅방 구독

구독 관리 패턴( front 코드)

코드에서 보이는 것처럼 subscriptionsRef를 통해 구독을 체계적으로 관리합니다:

// 구독 참조 관리
subscriptionsRef.current.set('matching', matchingSub);
subscriptionsRef.current.set('errors', errorSub);
subscriptionsRef.current.set('review', reviewSub);

// 구독 해제 시
subscriptionsRef.current.forEach(subscription => {
    subscription.unsubscribe();
});

구현 플로우

1. 연결 설정 단계

사용자 로그인 → WebSocket 연결 설정 → 매칭 알림 토픽 구독 → 매칭 대기 상태

2. 매칭 프로세스

매칭 알고리즘 실행 → 매칭 성공 → 브로커를 통한 알림 전송 → 매칭된 사용자들에게 알림

3. 채팅 시스템

활성화

매칭 완료 → 공통 채팅방 토픽 생성 → 각 사용자가 채팅방 구독 → 실시간 채팅 시작

세부 구현 내용

WebSocket 연결 관리

  • 연결 시점: 사용자 로그인과 동시에 WebSocket 연결 설정
  • 해제 시점: 사용자 로그아웃 시 연결 해제
  • 연결 상태 관리: 재연결 로직 및 하트비트 메커니즘 구현

매칭 시스템

  1. 연결 및 구독: 로그인 시 STOMP CONNECT 후 /user/queue/matching 구독
  2. 매칭 대기: 사용자 매칭 풀에 추가
  3. 매칭 완료: 브로커가 /user/queue/matching으로 매칭 알림 SEND
  4. 알림 수신: 구독 중인 사용자들이 매칭 결과 메시지 수신

채팅 시스템

  1. 채팅방 생성: 매칭 완료 후 고유 채팅방 ID 생성 (ChattingRoomID {uuid})
  2. 채팅방 구독: 매칭된 사용자들이 /user/chat/ ChattingRoomID {uuid} 구독
  3. 메시지 전송: STOMP SEND 명령으로 채팅방 토픽에 메시지 발행
  4. 실시간 수신: 구독 중인 모든 사용자가 메시지 실시간 수신
  5. 구독 해제: 채팅 종료 시 UNSUBSCRIBE로 구독 해제

핵심 기술 구성요소

서버 사이드

  • WebSocket + STOMP 서버: 연결 관리 및 STOMP 프로토콜 처리
  • 메시지 브로커: Spring WebSocket, RabbitMQ, ActiveMQ 등
  • 매칭 알고리즘: 사용자 매칭 로직
  • 채팅방 관리: 방 생성, 참여자 관리, 메시지 저장

클라이언트 사이드

  • STOMP 클라이언트: 서버와의 STOMP 프로토콜 통신
  • 구독 관리: 토픽 구독/해제 로직 (SUBSCRIBE/UNSUBSCRIBE)
  • 메시지 송신: SEND 명령을 통한 메시지 발행
  • UI 업데이트: 실시간 메시지 및 알림 표시

고려사항 및 최적화

성능 최적화

  • 연결 풀링: 효율적인 연결 관리
  • 메시지 배치 처리: 대량 메시지 처리 시 성능 향상
  • 로드 밸런싱: 다중 서버 환경에서의 부하 분산

안정성 확보

  • 재연결 메커니즘: 네트워크 불안정 시 자동 재연결
  • 메시지 순서 보장: 메시지 전달 순서 유지
  • 오류 처리: 연결 실패 및 메시지 전송 오류 처리

확장성 고려

  • 수평 확장: 서버 인스턴스 추가를 통한 확장
  • 토픽 파티셔닝: 대규모 사용자 처리를 위한 토픽 분할
  • 캐싱 전략: 자주 사용되는 데이터의 캐시 활용

결론

WebSocket과 Pub/Sub 패턴을 결합한 실시간 통신 시스템은 현대 웹 애플리케이션에서 필수적인 기술입니다. 특히 매칭 시스템과 채팅 기능을 통합한 구현 사례는 사용자 경험을 크게 향상시키며, 확장 가능하고 유지보수가 용이한 아키텍처를 제공합니다.

이러한 시스템을 구축할 때는 성능, 안정성, 확장성을 모두 고려한 설계가 중요하며, 지속적인 모니터링과 최적화를 통해 서비스 품질을 유지해야 합니다.