
클라이언트와 서버 간의 실시간 양방향 통신을 가능하게 하는 기술로, 특정 플랫폼에 종속되지 않은, 표준화된 네트워크 프로토콜입니다.
Q. 웹이 아닌 네이티브 앱 채팅 애플리케이션을 개발하는데 왜 웹소켓을 이용할 수 있을까요?
웹에서만 사용할 수 있다고 "웹"으로 이름 붙혀진게 아닙니다! 웹 환경에서 처음 도입되었기 때문에 웹이라 이름 붙여졌을 뿐입니다.
웹소켓 프로토콜은 RFC 6455로 표준화되어, 웹 브라우저 뿐만 아니라 모든 네트워크 클라이언트와 서버에서 구현할 수 있습니다. 즉, 웹소켓을 지원하는 라이브러리만 있다면 어떤 네트워크 환경에서도 사용할 수 있습니다.
Q. 그럼 stomp는 뭐고, 웹소켓과 stomp는 무슨 관계일까요?
TCP와 HTTP 와 같이 웹소켓은 전송 계층 프로토콜, 그리고 그 위에서 동작하는 stomp은 응용 계층 프로토콜입니다.
참고 - spring가이드
브라우저와 서버 간에 메시지를 주고 받는 대화형 웹 애플리케이션 구축합니다.
- 메시지를 포함하기 위한 하위 프로토콜로 WebSocket을 사용합니다.
- STOMP 메시징을 사용합니다.
먼저 필요한 기능을 생각해보겠습니다.
객체는 현재 chatroom, chatmessage가 있는 상태고,
각각의 컨트롤러가 있는 상황입니다.
개발이 필요한 부분을 적어보겠습니다.
spring websocket 가이드를 참고할 때 가이드에서는 /topic/greetings에 속해있는 모든 구독자들에게 전체 발송을 했습니다.
그럼 우리는 채팅방을 만들 때 생긴 고유한 chatroom id를 이용해 /topic/chatroomId를 구독해주어야 합니다.
그리고 chatmessage는 자신이 도착할 chatroomid도 알아야 합니다.
sendto는 동적으로 roomid에 맞게 구독할 수 없기 때문에 SimpMessagingTemplate를 사용하겠습니다.
@Controller
public class ChatController {
private final SimpMessagingTemplate messagingTemplate;
@Autowired
public ChatController(SimpMessagingTemplate messagingTemplate) {
this.messagingTemplate = messagingTemplate;
}
@MessageMapping("/chat.sendMessage")
public void sendMessage(ChatMessage chatMessage) {
messagingTemplate.convertAndSend("/topic/" + chatMessage.getRoomId(), chatMessage);
}
@MessageMapping("/chat.addUser")
public void addUser(ChatMessage chatMessage, SimpMessageHeaderAccessor headerAccessor) {
// Add username in web socket session
headerAccessor.getSessionAttributes().put("username", chatMessage.getSender());
messagingTemplate.convertAndSend("/topic/" + chatMessage.getRoomId(), chatMessage);
}
}
postman에서는 Stomp 프로토콜 테스트를 지원해주지 않습니다.
그래서 postman이 아니라 apic로 테스트했습니다.
https://apic.app/online/#/tester

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").setAllowedOrigins("*");
registry.addEndpoint("/ws").withSockJS();
}
}