
1. 메시지 프로토콜의 부재
2. Session 및 사용자 관리의 어려움
3. Pub/Sub 구조 직접 구현이 어려움
Pub/Sub 구조를 직접 구현해야 한다.4. 메시지 타입이나 상태 구분이 어려움
STOMP, SockJS와 같은 상위 메시징 프로토콜이 등장했다.1. 구독 기반 메시징 지원
Pub/Sub 구조를 쉽게 구현할 수 있도록 /topic/roomId 같은 경로 기반 구독을 지원한다.2. 메시지 목적지를 명확하게 지정 가능
3. 메시지 타입과 헤더 관리 지원
4. Spring과의 통합이 용이함
@MessageMapping, @SendTo, SimpleMessagingTemplate등을 활용해 손쉽게 메시지를 송수신 할 수 있어 생산성이 높다.5. Session 연결 및 인증과 연동 가능
Principl, HanshakeInterceptor 등을 통해 로그인 사용자 정보를 WebSocket 세션에 연동 할 수 있다.
Pub/Sub는 발행/구독 모델이라고 하며, 다음과 같은 구조로 이루어짐
이 구조의 핵심은 발행자와 구독자가 서로를 알 필요가 없고, 모든 통신이 메시지 브로커를 통해 중개됨
메시지 브로커는 발행자와 구독자 사이에서 메시지를 중개하는 역할을 하는 컴포넌트, 쉽게 말해 전달 담당자 역할을 함
필터링, 로깅, 변환 등을 쉽게 끼워넣을 수 있음
// WebSocketConfig
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// 클라이언트가 구독할 prefix 설정 (예: /topic)
config.enableSimpleBroker("/topic");
// 클라이언트가 메시지를 보낼 때 사용하는 prefix 설정 (예: /app)
config.setApplicationDestinationPrefixes("/app");
}
/topic의 경우 클라이언트가 직접 구독하는 경로로, 브로커가 그대로 메시지를 전달해주는 역할을 한다./app은 클라이언트가 서버로 메시지를 보내는 경로이며, 서버는 해당 메시지를 받아 로직을 처리하거나 가공 한 뒤 필요시 /topic을 통해 다시 클라이언트에게 메시지를 보낼 수 있다.// ChatController
@RequiredArgsConstructor
@Controller
public class ChatController {
private final MessageService messageService;
// /app/chat.sendMessage 로 들어오는 메시지를 처리하여 /topic/public 로 전송
@MessageMapping("/chat.sendMessage")
@SendTo("/topic/public")
public ChatMessage sendMessage(ChatMessage chatMessage) {
return chatMessage;
}
// /app/chat.addUser 로 들어오는 메시지를 처리하여 /topic/public 로 전송
@MessageMapping("/chat.addUser")
@SendTo("/topic/public")
public ChatMessage addUser(ChatMessage chatMessage) {
return messageService.createWelcomeMessage(chatMessage);
}
}
@MessageMapping은 클라이언트가 /app/~로 보낸 메시지를 처리하는 역할을 한다.@SendTo는 해당 메서드가 반환된 데이터를 브로커를 통해 구독자에게 전달할 경로를 지정한다./app/~로 메시지를 보내면@MessageMapping에 매핑하여 @SendTo를 통해 브로커에게 요청하여 해당 경로를 구독하고 있는 사용자들에게 메시지를 브로드캐스팅 해준다.
개인적인 회고