2024. 2. 19. 21:17ㆍSpring Boot
단방향 연결인 http 통신을 보완해
양방향 통신을 구축하기 위해서 web socket을 설정해 보겠다
flask나 node.js express는 socketio를 사용했으나
Spring Boot에서 socket.io 라이브러리를 사용하기 위해서는 Netty 프레임 워크를 사용해야되서
Stomp를 이용하여 구현하였다
우선
build.gradle에

를 추가해 주었다
그후
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/sub");
config.setApplicationDestinationPrefixes("/pub");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/endpoint");
}
}
WebSocketConfig를 등록해여 사용할 Broker와 Endpoint를 설정한다
Endpoint를 이용하여 통신을 구축하고
Broker를 이용하여 특정 Topic을 Subscribe하고
Destination을 이용하여 /pub로 시작하는 주소로 Message를 Publish한다
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.util.HtmlUtils;
import com.example.demo.test;
@Controller
public class socket_controller {
@GetMapping("/socket/test1")
public String test() {
return "chatting/index";
}
@GetMapping("/socket/test2")
public String test2() {
return "chatting/test";
}
@SendTo("/sub/test1")
@MessageMapping("/test1")
public String test_socket(test msg) throws Exception {
System.out.println(msg.getData());
return msg.getData() + " from server";
}
@SendTo("/sub/greeting")
@MessageMapping("/testMsg")
public test greeting(test msg) throws Exception {
Thread.sleep(1000); // simulated delay
System.out.println(msg.getData());
return new test("Hello", msg.getData());
}
}
@SendTO("/sub/test1")는 위 topic을 subscribe하고 있는 client에 전송을 한다는 의미다
@MessageMapping("/test1")은 prefix /pub와 합쳐 /pub/pub 주소로 Message를 Publish 하면 그에 응답 한다는 의미이다
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@stomp/stompjs@7.0.0/bundles/stomp.umd.min.js"></script>
</head>
<body>
<input type="text" id="username" placeholder="Username"><br>
<input type="text" id="fromS" placeholder="From Server"><br>
<button id="join-btn">JOIN</button>
<script>
const stompClient = new StompJs.Client({
brokerURL: 'wss://localhost:5000/endpoint'
});
stompClient.onConnect = (frame) => {
stompClient.subscribe('/sub/test1', (test) => {
document.getElementById("fromS").value = test.body;
});
}
stompClient.activate();
document.getElementById("join-btn").addEventListener("click", function () {
let username = document.getElementById("username").value;
stompClient.publish({
destination: "/pub/test1",
body: JSON.stringify({'data': username})
});
})
</script>
</body>
</html>
클라이언트 측은 이전과 다르게 Stomp
즉 Simple Text Oriented Messaging Protocol를 이용하여 웹소켓 연결을 구현하는데
이때 Https를 이용하여 서버를 구축한 경우 wss로 연결해야 한다
우선 설정한 Endpoint 주소를 이용하여 client를 만든다
그후 .onConnect로 서버와 연결을 설정한다
위 케이스는 연결 후 바로 subscribe로 /sub/test1의 주소의 topic을 subscribe했다.
뒤의 함수는 subscribe 중인 topic으로 부터 전송이 오면 처리하는 함수다
아래에는 button을 클릭 시 원하는 주소에 값을 publish 하도록 설정 하였다.


위와 같이 서로 다른 두 Client로 접속 후 값을 전송하면 둘 다 Subscribe 중이므로
Publish된 값이 둘 다에 전송됨을 확인 할 수 있다
'Spring Boot' 카테고리의 다른 글
| CORS (1) | 2024.02.24 |
|---|---|
| Naver Login (0) | 2024.02.19 |
| Redis Pub/Sub (0) | 2024.02.19 |
| Elasticsearch (0) | 2024.02.13 |
| Image File Handling (0) | 2024.02.03 |