๐ป ๊ณต๋ถ ๊ธฐ๋ก/๐ Spring
Spring | STOMP
- -
ํด๋น ๋ด์ฉ์ ๊ณต๋ถ์ ๋ชฉ์ ์ผ๋ก ๊ธฐ๋ก๋์์ผ๋ฉฐ,
์๋ ๋ด์ฉ์ ๋ชจ๋ ๊ตฌ๊ธ ๊ฒ์์ผ๋ก ๊ณต๋ถ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํ์ฌ ์์ฑํ์ต๋๋ค.
์ด์ฌํ ๋ฐฐ์ฐ๋ ์ค์ ๋๋ค. ๊ฐ์ฌํฉ๋๋ค.
๐ STOMP
STOMP(Streaming Text Oriented Messaging Protocol)์ ๋ฉ์ธ์ง ๊ธฐ๋ฐ ํต์ ํ๋กํ ์ฝ ์ค ํ๋๋ก, ํ ์คํธ ๊ธฐ๋ฐ์ ๋ฉ์ธ์ง๋ฅผ ์ ์กํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค.
์ด ํ๋กํ ์ฝ์ ๋๋ถ๋ถ์ ๋ฉ์ธ์ง ๋ธ๋ก์ปค์์ ์ง์๋๋ฉฐ, ๋ค๋ฅธ ๋ฉ์ธ์ง ๊ธฐ๋ฐ ํ๋กํ ์ฝ์ ๋นํด ๋ ๊ฐ๋ณ๊ณ ๊ฐ๋จํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
STOMP๋ ์๋ฒ์ ํด๋ผ์ด์ธํธ ๊ฐ์ ์๋ฐฉํฅ ํต์ ์ ์ ๊ณตํ๋ฉฐ, ํ๋์ ์ฐ๊ฒฐ๋ก ์ฌ๋ฌ ๊ฐ์ ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ผ ์ ์๋ค. ๋ํ, ๋ฉ์ธ์ง์ ๊ตฌ๋ (subscription)๊ณผ ๋ฐํ(publish)์ ์ง์ํ๋ฉฐ, ๋ฉ์ธ์ง์ ํ์(queueing)๊ณผ ํธ๋์ญ์ (transaction) ์ฒ๋ฆฌ๋ ๊ฐ๋ฅํ๋ค.
๋ง์ ์ธ์ด์์ STOMP๋ฅผ ๊ตฌํํ ์ ์์ผ๋ฉฐ, ์น ์์ผ(WevSocket)๊ณผ ์ฐ๋ํ์ฌ ์ค์๊ฐ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ํ๋๋๊ธฐ๋ ํ๋ค. ์ด๋ฌํ ํน์ง์ผ๋ก ์ธํด STOMP ๋ ๋ฉ์ธ์ง ๊ธฐ๋ฐ ์์คํ ์ ๊ตฌํํ๋๋ฐ ๋งค์ฐ ์ ์ฉํ ํ๋กํ ์ฝ ์ค ํ๋์ด๋ค.
๐ Maven(์์กด์ฑ)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${Spring ๋ฒ์ ๊ณผ ๋์ผํ๊ฒ}</version>
</dependency>
๐ servlet-context.xml
์ธํฐ๋ท์ ๊ฒ์๋๋ ์ ๋ณด๋ค ์ค config ๋ฅผ ์ค์ ํด์ stomp์ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ด ํํ ์๋ ค์ ธ ์๋ค.
๋๋ Spring-legarcy ํ๋ก์ ํธ๋ก MVC ํจํด์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ config ๋ณด๋จ servlet-context.xml์ ์ค์ ํด์ stomp๋ฅผ ์ฌ์ฉํ๋ค.
<!-- chat stomp config -->
<websocket:message-broker application-destination-prefix="/">
<websocket:stomp-endpoint path="/stompTest">
<websocket:sockjs/>
</websocket:stomp-endpoint>
<websocket:simple-broker prefix="/topic, /queue"/> <!-- /topic + /addr ์ถ๊ฐํ์ฌ ํ์
๋ณ ํต์ -->
</websocket:message-broker>
- <websocket:message-broker>
- WebSocket ๋ฉ์์ง์ ์ฒ๋ฆฌํ๋ ๋ฐ ์ฌ์ฉ๋๋ฉฐ, application-destination-prefix ์์ฑ์ ๋ฉ์์ง ๋ธ๋ก์ปค์์ ์ฒ๋ฆฌ๋๋ ๋ฉ์์ง์ ๋ชฉ์ ์ง๋ฅผ ์ง์ ํ๋ค. ์ด ๊ฒฝ์ฐ, ๋ชจ๋ ๋ชฉ์ ์ง๋ ๋ฃจํธ("/")๋ก ์ค์ ํ๋ค.
- <websocket:stomp-endpoint>
- WebSocket ์๋ํฌ์ธํธ๋ฅผ ์ค์ ํ๋ค. path ์์ฑ์ STOMP ํด๋ผ์ด์ธํธ๊ฐ ์ฐ๊ฒฐํ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ค. ์ด ์์ ์์๋ "/stompTest" ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๋ค.
- <websocket:sockjs/> SockJS ํ๋กํ ์ฝ์ ์ง์ํ๋๋ก ์ค์ .
- <websocket:simple-broker>
- ๋ฉ์์ง ๋ธ๋ก์ปค๋ฅผ ์ค์ ํ๋ค. prefix ์์ฑ์ ๋ฉ์์ง ๋ชฉ์ ์ง์ prefix๋ฅผ ์ง์ ํฉ๋๋ค. ์ด ์์ ์์๋ "/topic"๊ณผ "/queue" prefix๋ฅผ ์ฌ์ฉํ๋ค. ์ด๋ ๊ฒ ์ง์ ํ ๋ฉ์์ง ๋ชฉ์ ์ง์ ๋ฉ์์ง๋ฅผ ์ ์กํ๋ฉด, ํด๋น ๋ชฉ์ ์ง๋ฅผ ๊ตฌ๋ ํ๋ ๋ชจ๋ ํด๋ผ์ด์ธํธ๋ค์ด ๋ฉ์์ง๋ฅผ ์์ ํ ์ ์๋ค.
๐ StompController
ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ๋ฉ์ธ์ง๋ฅผ ๋ฐ์ ์ฒ๋ฆฌํ๊ณ , ํด๋น ๋ฉ์ธ์ง๋ฅผ ๋ค์ ํด๋ผ์ด์ธํธ์๊ฒ ์ ์กํ๋ ์ปจํธ๋กค๋ฌ.
@Controller
public class StompController {
@Autowired
private SimpMessagingTemplate messagingTemplate;
@MessageMapping("/{roomNumber}/TTT") // html stompClient.send("/app/send", {}, message);
public void onReceivedMessage(ChatMessage obj) throws Exception {
messagingTemplate.convertAndSend("/topic/message/" + obj.getRoomNumber(), obj);
}
}
- SimpMessagingTemplate
- Spring์์ STOMP ๋ฉ์ธ์ง ์ฒ๋ฆฌ๋ฅผ ํ๊ธฐ ์ํด ์ ๊ณต๋๋ ํ ํ๋ฆฟ์ด๋ค. ์ฌ์ฉํ๊ธฐ ์ํด์ @Autowired ์ด๋ ธํ ์ด์ ์ผ๋ก ์์กด์ฑ์ ์ฃผ์ ํ๋ค.
- @MessageMapping("/{roomNumber}/TTT")
- STOMP ํด๋ผ์ด์ธํธ์์ ๋ฉ์ธ์ง๋ฅผ ๋ฐ์ ๊ฒฝ๋ก๋ฅผ ์ค์ ํ๋ค.
- ํด๋ผ์ด์ธํธ์์ ๋ณด๋ธ ๋ฉ์ธ์ง ์ฒ๋ฆฌ๋ฅผ ํ๊ธฐ ์ํด์ ChatMessage์ ๊ตฌ์กฐ ํด๋์ค๋ฅผ ๋ง๋ค์๋ค.
- .convertAndSend(' ๊ฒฝ๋ก ', ' ๋ค์ ๋ณด๋ผ ๋ฉ์ธ์ง ')
- ๋ฉ์ธ์ง๋ฅผ ๋ค์ ํด๋ผ์ด์ธํธ์๊ฒ ์ ์กํ๋ค.
- "/topic/message"/{roomNumber}" ๊ฒฝ๋ก๋ก ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ด๋ฉด, ํด๋น ๊ฒฝ๋ก๋ฅผ ๊ตฌ๋ ํ ๋ชจ๋ ํด๋ผ์ด์ธํธ์๊ฒ ๋ฉ์ธ์ง๋ฅผ ์ ์กํ๋ค.
๐ Clinent
์๋ฒ์ ์ฐ๊ฒฐํ๊ธฐ ์ํด SockJS ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ค.
function stompOpen() {
// endpoint ์ค์
sock = new SockJS("/stompTest");
client = Stomp.over(sock);
// sock connect event ์คํ
stompEvent();
}
- new SockJS("/stompTest")
- STOMP ์๋ฒ์ endpoint ๊ฒฝ๋ก๋ฅผ ์ค์ ํ๋ค.
- Stomp.over(sock)
- SockJS ๊ฐ์ฒด๋ฅผ ์ด์ฉํด STOMP ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
- STOMP ํ๋กํ ์ฝ์ ์ฌ์ฉํ์ฌ ์๋ฒ์ ๋ฉ์ธ์ง๋ฅผ ์ฃผ๊ณ ๋ฐ์ ์ ์๋ค.
function stompEvent() {
// connect ํจ์ ์ฌ์ฉ
client.connect({}, function(frame) {
client.subscribe("/topic/message/" + roomNumber, function(message) {
console.log(" :: subscribe: ", message);
// msg >>> stomp controller
client.send("/" + roomNumber + "/TTT", {}, message);
});
});
}
- client.connect({}, function(frame)) { ... }
- STOMP ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ฅผ ํตํด ์๋ฒ์ ์ฐ๊ฒฐํ๋ ํจ์.
- ์ฒซ ๋ฒ์งธ ์ธ์: ํค๋๋ฅผ ์ค์ ํ๋ ๊ฐ์ฒด
- ๋ ๋ฒ์จฐ ์ธ์: ํจ์ ์ฐ๊ฒฐ์ด ์ฑ๊ณตํ์ ๋ ์คํ๋๋ ์ฝ๋ฐฑ ํจ์
- client.subscribe("/topic/message/" + roomNumber, function(message) { ... }
- /topic/message/ ๊ฒฝ๋ก์ ์๋ ๋ฉ์ธ์ง๋ฅผ ๊ตฌ๋ ํ๋ ํจ์
- ์ฒซ ๋ฒ์งธ ์ธ์: ๊ฒฝ๋ก + roomNumber ๋ณ์ (์ฑํ ๋ฐฉ์ ๊ตฌ๋ถํ๊ธฐ ์ํ ๋ณ์)
- ๋ ๋ฒ์งธ ์ธ์: ๋ฉ์ธ์ง๋ฅผ ์์ ํ์ ๋ ์คํ๋๋ ์ฝ๋ฐฑ ํจ์
- client.send("/" + roomNumber + "/TTT", {}, message)
- ๊ฒฝ๋ก์ message ๊ฐ์ฒด๋ฅผ ๋ฉ์ธ์ง๋ก ๋ฐ์ ํ๋ ํจ์
์ถ์ฒ | ๊ฐ๋ฐ ํ์ ๋จ๊ธฐ๊ธฐ
'๐ป ๊ณต๋ถ ๊ธฐ๋ก > ๐ Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Spring | DI(Dependency Injection) (0) | 2023.06.14 |
---|---|
Spring | Reflection์ ์ฌ์ฉํ์ฌ Annotation ๊ฐ์ ธ์ค๊ธฐ (0) | 2023.06.13 |
Spring | Model๊ณผ ModelAndView (0) | 2023.04.07 |
Spring | Interceptor(์ธํฐ์ ํฐ) / ๋ก๊ทธ์ธ ยท ์์ ์ฒ๋ฆฌ (0) | 2023.02.28 |
Spring | File Upload (0) | 2023.02.06 |
Contents
์์คํ ๊ณต๊ฐ ๊ฐ์ฌํฉ๋๋ค