카테고리 없음

[Websocket] Redis pub/sub, WebSocket 기반 실시간 채팅 구현

KJihun 2025. 5. 8. 21:19
728x90

 

1. RedisConfig

 

RedisMessageListenerContainer

Redis에서 발생하는 이벤트를 수신하는 리스너를 관리하는 빈 객체

  • setConnectionFactory: Redis와의 연결을 담당하며 Redis 채널에서 들어오는 메시지를 수신하기 위해 사용한다

RedisTemplate

Redis 서버와의 데이터 전송 시 직렬화 및 역직렬화를 처리하고, Redis와의 상호작용을 담당한다

Redis는 다양한 데이터 구조를 지원하지만, Java 객체를 Redis에 저장하려면 직렬화가 필요하다

 

Jackson2JsonRedisSerializer
Redis에 저장되는 객체가 JSON 형태로 직렬화되고, Redis에서 가져온 데이터를 JSON으로 역직렬화할 수 있도록 설정한다.

 

 

 

2. WebsocketConfig

클라이언트와 서버 간의 실시간 양방향 통신을 위한 WebSocketSTOMP(Simple Text Oriented Messaging Protocol)

기반의 메시지 브로커를 설정하는 클래스

 

 

@EnableWebSocketMessageBroker

WebSocket 메시지 브로커를 활성화하여 WebSocket 연결을 설정하고, 메시지 전송 및 수신을 처리할 수 있도록 한다

 

configureMessageBroker

  • enableSimpleBroker("/sub")
    • 클라이언트가 구독할 수 있는 엔드포인트. 클라이언트가 해당 경로로 메시지를 구독할 수 있도록 허용한다.
    • 클라이언트는 /sub ... 과 같은 경로로 구독할 수 있다.
    • spring Framework에서 제공하는 기본 메시지 브로커로 구현하였으며, RabbitMQ, ActiveMQ, Kafka 등 외부 메시지 브로커로 수정할 예정
  • setApplicationDestinationPrefixes("/pub")
    • 클라이언트가 서버에 메시지를 보낼 때 사용되는 엔드포인트
    • 클라이언트는/pub ... 과 같은 경로로 메시지를 전송할 수 있다

 

registerStompEndpoints

  • addEndpoint("/ws-stomp")

    클라이언트가 WebSocket 연결을 할 수 있도록 엔드포인트를 추가한다.

    이 엔드포인트(/ws-stomp)를 통해 클라이언트는 WebSocket 연결을 할 수 있다.

     

     

  • setAllowedOriginPatterns("*")
    CORS(Cross-Origin Resource Sharing) 설정. 모든 출처의 요청을 허용("*")하여, 다른 도메인에서도 연결할 수 있도록 한다

 

  • withSockJS()
    WebSocket을 지원하지 않는 브라우저에서는 WebSocket 대신 사용할 수 있는 폴백(fallback) 기술을 제공한다.
    일반적으로 polling 방식을 지원한다

 

 

configureMessageConverters

STOMP 메시지는 일반적으로 JSON 형식으로 처리되기에, 받은 메시지를 JSON 형식으로 직렬화 해주어야 한다.

이 메서드를 통해 서버와 클라이언트 간에 주고받는 메시지가 JSON으로 직렬화 및 역직렬화되어 작업을 수행할 수 있도록 한다.

 

configureWebSocketTransport

메시지의 최대 크기, 최대 시간, 메시지 전송 버퍼의 크기등 WebSocket 전송 관련 설정을 담당하는 메서드

 

 

채팅방 생성

1. UserId 및 RoomId 전달

 

2. RoomId와(랜덤 난수) 전달받은 userId로 채팅방 생성

 

 

채팅방 입장

  1. SockJS('/ws-stomp'):
    • SockJS를 사용하여 WebSocket을 지원하지 않는 환경에서도 연결을 유지할 수 있도록 한다
    • /ws-stomp는 앞서 WebSocketConfig에서 설정한 endpoint
  2. this.stompClient = Stomp.over(socket):
    • Stomp : 메시지 브로커와의 상호작용을 위해 사용하는 프로토콜
    • WebSocket 연결을 기반으로 STOMP를 생성하여 메시지 전송 및 구독 등의 작업을 처리한다
  3. this.stompClient.subscribe(/sub...)
    • 서버에서 전송되는 메시지를 수신하기 위해 채팅방에 구독하는 역할
    • /ws-stomp 와 마찬가지로 /sub... 은 WebSocketConfig에서 설정하여 해당 경로로 구독요청을 보낸다.
    • 메시지를 받을 때마다 this.handleMessage(message)를 호출한다.
  • handlerMessage : 메시지를 보내는 메서드
    • 요청에 따라 TALK, TYPING, JOIN , LEAVE 등으로 나뉜다

   4. this.sendSocketMessage({ ... })

  • 현재 채팅방(this.currentRoom)이 존재하면, 채팅방에 'JOIN' 메시지를 보낸다.
  • 해당 채팅방을 구독중인 유저에게 참여했음을 알리는 메시지

 

전송

WebSocket을 통해 서버로 메시지를 보내면, 해당 메시지의 목적지가 @MessageMapping으로 지정된 메서드와 매핑되어 요청을 처리한다.

 

 

 

 

앞서 Redis로 구현한 publisher를 통해 채팅방을 구독한 유저에게 메시지를 전송한다.