← 뒤로

프로젝트 요약

문제(AS-IS)

목표(TO-BE)

설계/선택(Key decisions)

WebSocket (STOMP) 방식 최종 선택

결과(Impact)

아래 링크에서 실제 구현 확인 가능 message.rahoon.site/websocket-docs/index.html


목차


구현 상세

1) 기술 비교 및 선택

배경: 실시간 통신을 위해 WebSocket/SSE 각각의 기술을 이론 비교 및 POC 구현 후 비교

이론 비교

특징 SSE 웹소켓
데이터 전송 방향 단방향 양방향
프론트 개발 난이도 (웹)간단, (모바일) 보통 보통
연결 감지 서버에서 클라이언트 종료 감지 지연 즉각적인 연결 상태 변화 감지
데이터 유형 텍스트만 지원 텍스트 및 바이너리 지원
프로토콜 HTTP 기반 TCP 기반
사용 사례 주식 시세, SNS 알림 등.. 채팅, 멀티플레이게임, 협업도구 등..

참고:

-> 양방향성이 중요한 메시지 서비스에서는 Websocket이 유리해보임

POC 구현 방법

  1. WebSocket (STOMP):
    • 서버: Spring WebSocket + STOMP 메시징 프로토콜
    • 클라이언트: Nodejs, Sockjs + WebStomp-client
  2. SSE
    • 서버: SseEmitter 기반 Server-Sent Events
    • 클라이언트: Nodejs, EventSource 라이브러리

테스트 1: 연속 3개 메시지 수신 테스트

방법) 10명 구독자, 메시지 3개 연속 전송(50ms 간격), 200회 반복

결과)

결론) 큰 차이 없음

테스트 2: 동시 연결 부하 테스트

방법) 동시 연결을 50개부터 300개까지 단계별로 증가하며 메시지 수신 확인

결과)

결론) Websocket을 선택할 이유가 늘어남

최종 결론: WebSocket 채택

근거)

2) 깔끔한 코드 구조: @WebsocketSend AOP

목적:

변화

// MessageWebsocketController class -- Before
@Async
@EventListener
fun sendCreatedMessage(message: MessageEvent.Created){
  simpleMessagingTemplate.convertAndSend(
    "/topic/chat-rooms/${message.chatRoomId}/messages",
    MessageWsSend.Detail.from(message)
  )
}

// MessageWebsocketController class -- After
@Async
@EventListener
@WebsocketSend("/topic/chat-rooms/{chatRoomId}/messages")
fun sendCreatedMessage(event: MessageEvent.Created): MessageWsSend.Detail {
    return MessageWsSend.Detail.from(message)
}
// WebsocketSend의 chatRoomId는 응답값 MessageWsSend.Detail을 SPEL로 조회하여 조합됨

3) 수평 확장 지원: Redis Pub/Sub

배경:

  1. 서버-A와 서버-B로 수평 확장된 상황에서
  2. 유저가 서버-A에 WebSocket을 Connect 한 상황일때
  3. 서버-B에서 메시지 생성 요청을 처리한 경우 MessageEvent.Created발급됨
  4. 이렇게 발급된 MessageEvent.Created는 서버-A까지 전달되지 않음

해결:

  1. 서버-A와 서버-B로 수평 확장된 상황에서
  2. 유저가 서버-A에 WebSocket을 Connect 한 상황일때
  3. 서버-B에서 메시지 생성 요청을 처리한 경우 MessageEvent.Created발급됨
  4. 서버-B에서는 MessageEvent.Created를 수신하여 MessageCommandEvent.Send로 변환한 뒤 Redis를 통해 적절한 서버로 전송
  5. 각 서버는 MessageCommandEvent.Send를 구독했다가 내부 이벤트로 발행
  6. MessageCommandEvent.Send를 수신하여 Websocket 전송

4) 프로토콜 문서화: AsyncAPI 3.0

배경: WebSocket 프로토콜 문서화 부재로 클라이언트 개발자와의 협업 어려움이 예상됨

접근:

포인트:


어떠한 날카로운 피드백이더라도 환영합니다. 사소한 의견도 괜찮습니다.

citron0137@gmail.com 또는 LinkedIn 을 통해 피드백을 보내주세요.