안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.
Stomp
SimpleBroker는 발행된 목적지를 보고 구독자들에게 전달해주는 역할! (topic으로 시작하는 주소)
SimpAnnotationMethod는 부가적인 업무를 수행 후 SimpleBroker에게 전달! (app으로 시작하는 주소)
stomp cnd
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js" integrity="sha512-iKDtgDyTHjAitUDdLljGhenhPwrbBfqTKWO1mkhSFH3A7blITC9MhYon6SjnMhp4o0rADGw9yAC6EW4t5a4K3g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
https://cdnjs.com/libraries/stomp.js
pom.xml
stomp 관련 의존 추가
<!-- #14 websocket 관련 의존 추가 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- stomp관련 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${org.springframework-version}</version>
</dependency>
security-context.xml
<intercept-url pattern="/stomp/**" access="permitAll"/>
servlet-context.xml
<websocket:message-broker application-destination-prefix="/app">
<websocket:stomp-endpoint path="/stomp">
<websocket:sockjs />
</websocket:stomp-endpoint>
<websocket:simple-broker prefix="/topic"/>
</websocket:message-broker>
application-destincation-prefix를 먼저 검사 후 해당된다면 (/app이라면), messageMapping을 타게 해주고,
해당하지 않는다면 simpleBroker가 처리해줍니다.
header.jsp
<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" integrity="sha512-iKDtgDyTHjAitUDdLljGhenhPwrbBfqTKWO1mkhSFH3A7blITC9MhYon6SjnMhp4o0rADGw9yAC6EW4t5a4K3g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<!-- 로그인 했을 때만 웹 소켓 연결! -->
<sec:authorize access="isAuthenticated()">
<script src="${pageContext.request.contextPath}/resources/js/ws.js"></script>
</sec:authorize>
</head>
로그인 했을 때만 웹 소켓 연결을 하기 위해 isAuthenticated()일 때만 ws.js 스크립트를 추가해주었습니다.
ws.js
// ws.js
const ws = new SockJS(`http://${location.host}/spring2/stomp`);
// stomp 객체 생성 -> 웹소켓 객체를 직접 제어하지 않고 stomp를 통해서 제어
const stompClient = Stomp.over(ws);
// 연결된 이후 호출해주는 핸들러. {} -> 옵션
stompClient.connect({}, (frame) => {
console.log("connect : ", frame);
// 연결 이후 구독 신청
stompClient.subscribe("/topic/a", (message) => {
console.log("/topic/a : ", message);
});
stompClient.subscribe("/app/a", (message) => {
console.log("/app/a : ", message);
})
});
SockJS를 이용하여 웹 소켓 객체를 생성(/stomp)하고, 직접 제어하지 않고 stomp를 통해 제어하기 위하여 Stomp.over()를 이용해 Stomp 객체를 생성해주었습니다.
사용자가 로그인을 하면 ws.js 스크립트가 실행될 것이고, 객체를 생성함에 따라 웹 소켓에 연결 될 것입니다.
connect()를 이용해 연결된 이후 "/topic/a", "/app/a"에 대해 구독 신청을 하게 됩니다. (subscribe())
로그인 후 콘솔창
따라서 로그인 후 콘솔창을 확인해보면, web socket open 후 connect 핸들러가 실행되어 "/topic/a"와 "/app/a"에 대해 구독 신청이 된 것을 확인할 수 있습니다.
"/topic/a" 구독자들에게 메세지 전송
'/topic/a'를 구독한 사람들에게 '안녕' 메세지를 보내보니, /topic/a를 구독한 현재의 로그인 사용자(honggd, qwerty)에게 메세지가 전달된 것을 확인할 수 있습니다.
SimpAnnotationMethod를 거치는 app
Controller
StompController
@MessageMapping - url은 prefix 제외하고 작성 (ex. /app/a → /a)
@SendTo - prefix부터 모두 작성, simpleBroker에게 전달
@Controller
@Slf4j
public class StompController {
/**
* @MessageMapping
* - url은 prefix를 제외하고 작성
* - /app/a -> /a
*
* @SendTo
* - prefix부터 모두 작성
* - simpleBroker에게 전달
*/
@MessageMapping("/a")
@SendTo("/topic/a")
public String simpleMessage(String message) {
log.debug("message = {}", message);
return message;
}
}
"/app/a"로 받은 메세지를 @SendTo, "/topic/a"를 구독한 구독자들에게 전달하기 위해 simpleBroker에게 전달하여 simpleBroker가 구독자들에게 메세지를 전달합니다.
로그인 후 /app/a 구독자에게 메세지 송부
@콘솔출력값
DEBUG: com.ce.spring2.ws.controller.StompController - message = ㅋㅋ
마찬가지로 "/app/a"의 구독자 (현재 로그인한 사용자 - honggd, qwerty)에게 메세지를 송부한 것을 확인할 수 있습니다.
하지만 @SendTo로 simpleBroker에게는 "/topic/a"을 구독한 사용자에게 메세지를 전달하라고 하였기 때문에 destincation은 "/topic/a"인 것을 확인할 수 있습니다.
여기서 만일! "/app/a"로 보내면 "/topic/a"가 아닌 그대로 "/app/a" 구독자들에게 메세지를 송부하고 싶어서 @SendTo("/app/a")를 하면 simpleBroker는 "/app/a"를 몰라 처리 못해줍니다.
그 이유는 servlet-context.xml에 있습니다.
<websocket:simple-broker prefix="/topic"/>
simple-broker는 "/topic" prefix만 처리해주는 걸로 설정 되어있기 때문입니다.
<websocket:simple-broker prefix="/topic, /app"/>
이처럼 수정해주어 /app 구독자들에게도 메세지를 전달해줄 수 있게 해줍니다.
이번엔 @SendTo를 "/app/a"로 지정해주었습니다.
@MessageMapping("/a")
@SendTo("/app/a")
public String simpleMessage(String message) {
log.debug("message = {}", message);
return message;
}
destincation이 "/app/a"인 것을 확인할 수 있습니다.
'Java > Spring' 카테고리의 다른 글
Spring) Web-Socket - Stomp (게시글 조회 알림 구현) (0) | 2022.09.15 |
---|---|
Spring) Web-Socket - Stomp (전체/개별 공지사항 전송 구현) (0) | 2022.09.15 |
Spring) Spring-WebSocket + SockJS (0) | 2022.09.14 |
Spring) Spring-WebSocket (관련 설정) (2) | 2022.09.14 |
Spring) Security - 인증된 사용자 정보 가져오기, 처리 순서 파악 (2) | 2022.09.11 |