반응형

스프링부트에서 STOMP를 이용한 메세지 pub/sub 예시

build.gradle에서 라이브러리를 추가해주십쇼 

implementation 'org.springframework.boot:spring-boot-starter-websocket'

 

웹소켓 설정파일 WebsocketConfig.java 을 아래와 같은 내용으로 생성

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import lombok.RequiredArgsConstructor;

@Configuration
@EnableWebSocketMessageBroker
@RequiredArgsConstructor
public class WebsocketConfig implements WebSocketMessageBrokerConfigurer {

@Override
    public void configureMessageBroker(MessageBrokerRegistry registry){
        // /pub으로 시작하는 요청은 @Controller의 @MessageMapping 메소드로 라우트됨
        // 클라이언트가 서버로 메세지를 보낼 때 붙여야하는 prefix
        registry.setApplicationDestinationPrefixes("/pub"); 

         //해당 문자열로 시작하는 message 주소값을 받아서 처리하는 Broker를 활성화한다.
        registry.enableSimpleBroker("/sub"); //메세지 구독 주소값
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry){
        registry.addEndpoint("/websocket")  //클라이언트가 연결할 url
        .setAllowedOriginPatterns("*")
        .withSockJS(); 
        //withSockJS : 웹소켓을 지원하지 않는 환경에서도 웹소켓 사용을 가능하게 해주는 옵션
        //이 옵션을 달면 클라이언트에서 SockJS 라이브러리를 사용해야 함
        //http 아니면 https 로 연결가능(sockJS가 http를 ws로 변환해줌)
    }
}

 

서버에서 STOMP 메세지 보내기

- convertAndSend 메소드를 호출하면 클라이언트가 구독하고 있는 주소로 메세지가 발행됨.

- /sub/** 주소를 구독하고 있는 클라이언트에게 메세지를 전달하는 예시 

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;


@Component
@RequiredArgsConstructor
public class sendService{
    private final SimpMessagingTemplate messagingTemplate;

    public void sendMessageToSubOrderTopic(String message,String id) {
        messagingTemplate.convertAndSend("/sub/"+id, message);
    }
}

 

 

 

서버에서 STOMP 메세지 받아서 전달하기

- 서버가 메세지 브로커 역할 수행

- 특정 클라이언트가 /sub/test 주소로 메세지를 보내면 @MessageMapping에서 받아 @SendTo에 설정된 쪽으로 전달

- /sub/** 을 구독하는 클라이언트가 메세지를 받아볼 수 있는 예시

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class StompMessageController {
/* 클라이언트에서 웹소켓을 연결한 뒤 /pub/test 로 메세지를 보내면
 여기서 받아 SendTo에 명시된 구독 링크로 메세지를 발행
 prefix는 생략
*/
    @MessageMapping("/test")
    @SendTo("/sub")
    public String processMessage(String message){
        System.out.println("message : " + message);
        return message;

    }

    //STOMP를 쓰면 좋은점
   	/* @Controller 적용된 객체를 이용해 조직적으로 관리할 수 있다.
    	STOMP의 Destination 경로를 기반으로 Spring Security를 적용할 수 있다
    	외부 브로커를 이용해 여러 서버를 관리할 수 있다.
    */


}

 


그럼 메세지를 구독하고 보내는 클라이언트 페이지를 띄워 테스트를 해보자..

검색해보면 전부 다 APIC으로 테스트를 하던데 APIC자체를 못찾아서 javascript로 짜서 했음. 

html 페이지에 javascript 소스를 넣는다.

 

메세지 구독하는 클라이언트 페이지 소스 예시 (javascript)

서버에 withSockJS() 설정이 되어있다면 SockJS 를 이용하여 연결해야 하며 이 경우엔 http나 https 로 접속을 해야함.

서버에서 /sub 주소로 구독하고 있는 클라이언트에 메세지를 전달해주므로 

/sub/aaa이나  /sub/bbb 를 구독하는 쪽은 메세지를 다 받을 수 있음. 

<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js" integrity="sha512-1QvjE7BtotQjkq8PxLeF6P46gEpBRXuskzIVgjFpekzFVF4yjRgrQvTG1MTOJ3yQgvTteKAcO7DSZI92+u/yZw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>

<script type="text/javascript">
var socket = new SockJS("http://localhost:8081/websocket");
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
    console.log("연결 완료");
    stompClient.subscribe("/sub/aaa",function(response){
        console.log(response.body);
  });	
});
</script>

 

메세지를 발행하는 클라이언트 페이지 소스 예시(javascript)

<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js" integrity="sha512-1QvjE7BtotQjkq8PxLeF6P46gEpBRXuskzIVgjFpekzFVF4yjRgrQvTG1MTOJ3yQgvTteKAcO7DSZI92+u/yZw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>

<script type="text/javascript">
var socket = new SockJS("http://localhost:8081/websocket");
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
    console.log("연결 완료");
    stompClient.send("/pub/test",{},"test메시지입니다.");
});
</script>

 

SockJS를 안 쓰고 싶다면

서버에서 해당 설정을 없애주고

클라이언트에서는 stomp 라이브러리로 바로 연결하면 댐

<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js" integrity="sha512-1QvjE7BtotQjkq8PxLeF6P46gEpBRXuskzIVgjFpekzFVF4yjRgrQvTG1MTOJ3yQgvTteKAcO7DSZI92+u/yZw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
<script type="text/javascript">
var client = Stomp.client("ws://localhost:8081/websocket");
client.connect({},function(){
    console.log("연결 완료");
    client.subscribe("/sub/aaa",function(message){
        console.log("받은 메세지 : " + mesasge);
    });
})
	
</script>
반응형

+ Recent posts