본 게시글은 webSocket 과 Stomp의 아주 기초적인 흐름을 파악하기 위한 구현 과정이다
1. 프로젝트 생성하기
spring initializr를 통해 아래와 같이 생성합니다
2, Dependencies 추가하기
build.gradle 파일 내부에 dependencies 블록 안에 아래와 같이 추가해 준다
implementation 'org.webjars:webjars-locator-core'
implementation 'org.webjars:sockjs-client:1.5.1'
implementation 'org.webjars:stomp-websocket:2.3.4'
implementation 'org.webjars:bootstrap:5.2.2'
implementation 'org.webjars:jquery:3.6.1'
3. HelloMessage 클래스 만들기
package com.stomp1.stompPrac.stomp;
public class HelloMessage {
private String name;
public HelloMessage() {
}
public HelloMessage(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4. Greeting 클래스 만들기
package com.stomp1.stompPrac.stomp;
public class Greeting {
private String content;
public Greeting() {
}
public Greeting(String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
5. GreetingController 컨트롤러 클래스 만들기
package com.stomp1.stompPrac.stomp;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.util.HtmlUtils;
@Controller
public class GreetingController {
@MessageMapping("/hello") // 목적지가 path와 일치하는 메시지를 수신했을경우 해당 메서드를 호출
@SendTo("/topic/greetings") // 해당 path의 모든 구독자들에게 반환값이 브로드캐스트된다
public Greeting greeting (HelloMessage helloMessage) throws Exception {
Thread.sleep(1000); // 1초 쉬었다가 전환되도록 지연처리
return new Greeting(HtmlUtils.htmlEscape(helloMessage.getName()));
}
}
6. WebSocketConfig 컨피그 클래스 만들기
package com.stomp1.stompPrac.stomp;
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 // spring configuration 클래스임을 명시한다
@EnableWebSocketMessageBroker // WebSocket의 메시지 브로커에 의해 웹소켓 메시지를 처리할 수 있다 의미
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
// enableSimpleBroker()를 호출해서 간단한 메모리 기반의 메시지 브로커가
// /topic prefix가 붙은 수신처(해당 prefix를 구독중인)의 클라이언트로 메시지를 전달할 수 있도록 한다
// 또한 @MessageMapping 이 붙은 클래스의 Path(/app)도 정의한다
// 예를 들어, /app/hello 는 GreetingCotroller.greeting() 메서드가 처리하도록 매핑된 엔드포인트
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
// registerStompEndpoints() 메서드는 /gs-guide-websocket 엔드포인트를 등록해서
// 웹소켓을 사용할 수 없는 경우 ( ex/ 브라우저 미지원)
// 웹소켓 대신 다른 전송방식을 사용할 수 있도록 SockJS 옵션을 활성화 한다
// gs-guide-websocket에 연결해서 사용 가능한 최적의 전송방식
// ex) 웹소켓, xhr-streaming, xhr-polling, etc / 을 사용할 수 있도록 시도 한다
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/gs-guide-websocket").withSockJS();
}
}
7. index.html 만들기
src -> main -> resources -> static -> index.html
<!DOCTYPE html>
<html>
<head>
<title>Hello WebSocket</title>
<link href="/webjars/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/main.css" rel="stylesheet">
<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/sockjs-client/sockjs.min.js"></script>
<script src="/webjars/stomp-websocket/stomp.min.js"></script>
<script src="/app.js"></script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websocket relies on Javascript being
enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div id="main-content" class="container">
<div class="row">
<div class="col-md-6">
<form class="form-inline">
<div class="form-group">
<label for="connect">WebSocket connection:</label>
<button id="connect" class="btn btn-default" type="submit">Connect</button>
<button id="disconnect" class="btn btn-default" type="submit" disabled="disabled">Disconnect
</button>
</div>
</form>
</div>
<div class="col-md-6">
<form class="form-inline">
<div class="form-group">
<label for="name">chat here : </label>
<input type="text" id="name" class="form-control" placeholder="">
</div>
<button id="send" class="btn btn-default" type="submit">Send</button>
</form>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table id="conversation" class="table table-striped">
<thead>
<tr>
<th>Greetings</th>
</tr>
</thead>
<tbody id="greetings">
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
8. app.js 만들기
src -> main -> resources -> static -> app.js
var stompClient = null;
function setConnected(connected) {
$("#connect").prop("disabled", connected);
$("#disconnect").prop("disabled", !connected);
if (connected) {
$("#conversation").show();
}
else {
$("#conversation").hide();
}
$("#greetings").html("");
}
// SockJS와 stomp.js를 사용해서 /gs-guide-websocket에 대한 커넥션을 생성한다
// 이때 SockJS 서버는 연결을 대기하고 성공 시 클라이언트는 서버가 greeting message를
// publish할 path인 /topic/greetings 를 subscribe(구독) 한다
// 해당 topic에서 greeting 메시지를 수신하면 이를 표시하기 위해 DOM에 paragraph 요소를 추가한다
function connect() {
var socket = new SockJS('/gs-guide-websocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/greetings', function (greeting) {
showGreeting(JSON.parse(greeting.body).content);
});
});
}
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
// sendName() 메서드는 사용자가 입력한 이름을 STOMP 클라이언트를 이용해서 /app/hello로 전송한다
// 이 메시지는 GreetingController의 greeting() 메서드로 전달된다
function sendName() {
stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
}
function showGreeting(message) {
$("#greetings").append("<tr><td>" + message + "</td></tr>");
}
$(function () {
$("form").on('submit', function (e) {
e.preventDefault();
});
$( "#connect" ).click(function() { connect(); });
$( "#disconnect" ).click(function() { disconnect(); });
$( "#send" ).click(function() { sendName(); });
});
9. 완성
서버를 돌리고 localhost:8080 을 치고 확인해 본다
'Spring' 카테고리의 다른 글
[Spring] static과 templates (0) | 2022.10.31 |
---|---|
[Spring] webSocket + Stomp 연습(2) (0) | 2022.10.30 |
[Spring] CORS 설정하기 (0) | 2022.10.24 |
[Spring] EC2 배포하기 (0) | 2022.10.24 |
[Spring] Swagger활용 API문서 자동화 (0) | 2022.10.20 |