[Spring] 웹소켓을 이용한 간단한 채팅 시스템 (Feat.WebSocket)

kjoo0·2024년 6월 17일

Spring 이모저모

목록 보기
1/7
post-thumbnail

사전 지식

웹소켓

클라이언트와 서버 간의 실시간 양방향 통신을 가능하게 하는 기술로, 특정 플랫폼에 종속되지 않은, 표준화된 네트워크 프로토콜입니다.

Q. 웹이 아닌 네이티브 앱 채팅 애플리케이션을 개발하는데 왜 웹소켓을 이용할 수 있을까요?
웹에서만 사용할 수 있다고 "웹"으로 이름 붙혀진게 아닙니다! 웹 환경에서 처음 도입되었기 때문에 웹이라 이름 붙여졌을 뿐입니다.

웹소켓 프로토콜은 RFC 6455로 표준화되어, 웹 브라우저 뿐만 아니라 모든 네트워크 클라이언트와 서버에서 구현할 수 있습니다. 즉, 웹소켓을 지원하는 라이브러리만 있다면 어떤 네트워크 환경에서도 사용할 수 있습니다.

Q. 그럼 stomp는 뭐고, 웹소켓과 stomp는 무슨 관계일까요?

TCP와 HTTP 와 같이 웹소켓은 전송 계층 프로토콜, 그리고 그 위에서 동작하는 stomp은 응용 계층 프로토콜입니다.

Spring WebSocket

참고 - spring가이드

브라우저와 서버 간에 메시지를 주고 받는 대화형 웹 애플리케이션 구축합니다.

  • 메시지를 포함하기 위한 하위 프로토콜로 WebSocket을 사용합니다.
  • STOMP 메시징을 사용합니다.

Simple Chat System

기획과 개발 계획

먼저 필요한 기능을 생각해보겠습니다.

  • 사용자들은 메인 페이지에서 채팅방을 선택하고 생성할 수 있습니다.
  • 그리고 사용자들은 그 채팅방을 선택하고, 채팅방에 메시지를 보낼 때 그 채팅방을 구독합니다.
  • 사용자가 보낸 메시지는 그 채팅방을 구독한 사용자들에게 전달됩니다.
    - 메시지마다 roomId를 넣어서 sendMessage에서 해당 roomId를 구독하는 사용자에게만 보내줍니다.

객체는 현재 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);
    }
}

API 테스트 방법

postman에서는 Stomp 프로토콜 테스트를 지원해주지 않습니다.
그래서 postman이 아니라 apic로 테스트했습니다.

https://apic.app/online/#/tester

config 수정

@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();

    }
}
profile
티스토리 이사 준비 중..

0개의 댓글