[Spring boot] stomp를 활용해서 1:1 채팅 만들기

2021. 4. 25. 23:01Spring

1:1 채팅하기

2021-04-22-9-43-39.png

WebSocket & STOMP

  • WebSocket은 웹 상에서 쉽게 소켓통신을 하게 해주는 라이브러리로 실시간 채팅 서비스 등등 여러 유요한 서비스에 기반이 된다. 스프링 부트환경에서는 이러한 서비스를 구현하기 위해서 필요한 2가지가 있다.
    WebSocket의 기능을 보완해주고 향상시켜주는 SockJs라이브러리와 메시징 전송을 좀 더 효율적으로 지원해주기 위한 STOMP 프로토콜이 존재한다.일반 스프링 환경에서는 핸들러만 구현해주고 직접 호출했지만 부트 환경에서는 핸들러와 브로커라는 개념을 이용해서 서로간의 통신을 하게 된다.

STOMP

  • STOMP는 Simple/Streaming Text Oriented Messaging Protocol의 약자이다. 텍스트 기반의 메세징 프로토콜이다. 유사한 프로토콜은 OASIS표준으로 선정된 AMQP가 있다. 웹 소켓을 지원한다. TCP나 WebSocket과 같은 신뢰성있는 양방향 streaming network protocol상에 사용될 수 있다. HTTP에 모델링 된 frame 기반 프로토콜이다.

    • 아래는 해당 frame워크의 구조이다

    2021-04-22-9-52-27.png

  • 헤더와 바디로 구성되어있다. 아래는 STOMP의 구조이다.

    2021-04-22-9-52-34.png

  • 위의 구조에서 중요한 개념은 브로커와 Subscribe의 개념이다. STOMP는 구독이라는 개념을 통해 내가 통신하고자 하는 주체(topic)을 판단하여 브로커라는 개념을 두어 실시간, 지속적으로 관심을 가지며 해당 요청이 들어오면 처리하게 되는 구조이다.

  • Connect

    2021-04-22-10-07-32.png

    연결에 관한 구조이다. 버전정보와 현재의 세션정보를 가져온다. 세션은 스프링 시큐리티를 연동하여 등록한다.

  • Subscribe

    2021-04-22-10-07-41.png

    구독이라는 개념을 이용하여 현재 메세지에 대한 목적지를 설정한다. 구조를 보면 각각의 destination이 있다. Connect 이후에 subscribe를 설정하게 된다. 등록되지 않은 subscribe를 호출 시 찾을 수 없기에 정확한 통신이 되지 않는다.

  • Message

    2021-04-22-10-44-41.png

    메세지를 전송 시 구조이다. 메세지의 전달지(destination)와 해당 메세지의 정보들이 출력된다. 현재 위의 구조는 데이터의 타입은 JSON으로 전송하였고 목적지는 /topic/ + roomId이다.
    데이터는 JSON구조로 key, value로 되어있다. 다양한 데이터 타입을 가질 수 있다.


WebSocket연동

  1. Build.gradle

    implementation 'org.springframework.boot:spring-boot-starter-websocket'
    • 웹 소켓 라이브러리를 등록해준다.
  2. WebSocketConfig.java

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

    WebSocketMessageBrokerConfigure를 implement를 받아서 관련 메소드들을 오버라이드 합니다. 위 STOMP의 구조를 설명했듯이 브로커라는 개념이 적용된다. setApplicationDesinationPrefixes 메소드를 이용하여서 전송할 목적지의 prefix값을 설정한다. 마지막으로 addEndpoint로 웹 소켓에서 활용될 주소를 적어주고 withSockJS를 이용하여서 향상된 SockJS를 사용 하겠다는 것을 알려준다.

  3. ChatMessageController.java

    @Controller
    @RequiredArgsConstructor
    public class ChatMessageController {
        private final SimpMessagingTemplate simpMessagingTemplate;
        private final ChatMessageService chatMessageService;
        @MessageMapping("/chat/send")
        public void sendMsg(ChatMessageForm message) {
            String receiver = message.getReceiver();
            System.out.println(receiver);
            chatMessageService.save(message);
            simpMessagingTemplate.convertAndSend("/topic/" + receiver,message);
        }
    
    }

    다음과 같이 controller단에서 받을 수 있다. /app의 경우 기본 publish로 지정했기 때문에 /app 이후 url만 MessageMapping으로 요청받고 각자 입맛에 맞게 변형한 뒤 SimplMessagingTemplate를 통해서 내가 보내주고자 하는 사람이 subscribe한 링크로 보내주면 됩니다.
    이런식으로 client가 채팅방을 만들 때 publish는 모두 동이랗ㄴ 링크로 두고 subscribe를 개인의 고유한 url로 만들 어서 각각의 유저끼리 1:1 채팅이 가능하도록 합니다.

테이블 설게는 다음에 올리겠씁니다 :)

참고 블로그

'Spring' 카테고리의 다른 글

[Spring Boot] S3 이미지 업로드  (0) 2021.06.02
[Spring Boot]S3 버킷 생성  (0) 2021.06.02
[Spring] @Valid  (0) 2021.04.11
[Spring] Bcrypt로 암호화하기  (0) 2021.04.11
Spring으로 Token 받기  (0) 2021.04.11