Home > Network > 2024 > ๐ŸŒ[Network] STOMP(Simple/Streaming Text Messaging Protocol)๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”?

๐ŸŒ[Network] STOMP(Simple/Streaming Text Messaging Protocol)๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”?
Network

๐ŸŒ[Network] STOMP(Simple/Streaming Text Messaging Protocol)๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”?

  • STOMP(Simple/Streaming Text Messaging Protocol)๋Š” ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜์˜ ๋ฉ”์‹œ์ง• ํ”„๋กœํ† ์ฝœ๋กœ, ํด๋ผ์ด์–ธํŠธ์™€ ๋ฉ”์‹œ์ง• ๋ธŒ๋กœ์ปค(Message Broker) ๊ฐ„์˜ ํ†ต์‹ ์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
    • ์ผ๋ฐ˜์ ์œผ๋กœ WebSocket๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๋ฉฐ, Pub/Sub ํŒจํ„ด์˜ ๋ฉ”์‹œ์ง•์„ ๋” ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค๋‹ˆ๋‹ค.

1๏ธโƒฃ STOMP์˜ ์ฃผ์š” ํŠน์ง•.

1๏ธโƒฃ ๊ฐ„๋‹จํ•œ ๋ฉ”์‹œ์ง• ํ”„๋กœํ† ์ฝœ.

  • STOMP๋Š” ๊ฐ„๋‹จํ•œ ๋ฉ”์‹œ์ง€ ํ”„๋ ˆ์ž„ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ์ดํ•ดํ•˜๊ณ  ๊ตฌํ˜„ํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.
  • ๋ฉ”์‹œ์ง€ ํ”„๋ ˆ์ž„์€ ๋ช…ํ™•ํ•œ ํ—ค๋”์™€ ๋ณธ๋ฌธ(Body)์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

2๏ธโƒฃ WebSocket ์ƒ์œ„ ๋ ˆ์ด์–ด ํ”„๋กœํ† ์ฝœ.

  • STOMP๋Š” WebSocket์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜์ง€๋งŒ, WebSocket์˜ ๋‹จ์ˆœํ•œ ํ†ต์‹  ๋ฐฉ์‹์— Pub/Sub(๋ฐœํ–‰/๊ตฌ๋…) ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
  • WebSocket์€ ๋‹จ์ˆœํžˆ ์–‘๋ฐฉํ–ฅ ์—ฐ๊ฒฐ๋งŒ ์ง€์›ํ•˜์ง€๋งŒ, STOMP๋ฅผ ํ†ตํ•ด ๋” ๋ณต์žกํ•œ ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3๏ธโƒฃ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๊ฐ„์˜ ๋ฉ”์‹œ์ง•.

  • STOMP๋Š” ์„œ๋ฒ„-ํด๋ผ์ด์–ธํŠธ ๋˜๋Š” ํด๋ผ์ด์–ธํŠธ-ํด๋ผ์ด์–ธํŠธ ๊ฐ„์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์ฃผ๋กœ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค(์˜ˆ: ActiveMQ, RabbitMQ)์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

4๏ธโƒฃ Pub/Sub ํŒจํ„ด ์ง€์›.

  • ํด๋ผ์ด์–ธํŠธ๋Š” ํŠน์ • ์ฃผ์ œ(Topic) ๋˜๋Š” ํ(Queue)๋ฅผ ๊ตฌ๋…(Subscribe)ํ•˜์—ฌ, ํ•ด๋‹น ์ฃผ์ œ์— ๋ฐœํ–‰๋œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ STOMP ํ”„๋ ˆ์ž„ ๊ตฌ์กฐ.

  • STOMP ๋ฉ”์‹œ์ง€ ํ”„๋ ˆ์ž„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์š”์†Œ ๊ตฌ์„ฑ.

1๏ธโƒฃ ๋ช…๋ น(command)

  • ํ”„๋ ˆ์ž„์˜ ๋ชฉ์ ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.(์˜ˆ: CONNECT, SEND, SUBSCRIBE, UNSUBSCRIBE)

2๏ธโƒฃ ํ—ค๋”(headers)

  • ํ”„๋ ˆ์ž„๊ณผ ๊ด€๋ จ๋œ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.(์˜ˆ: ๋ชฉ์ ์ง€, ์ฝ˜ํ…์ธ  ํƒ€์ž… ๋“ฑ)

3๏ธโƒฃ ๋ณธ๋ฌธ(body)

  • ๋ฉ”์‹œ์ง€ ๋‚ด์šฉ(์„ ํƒ ์‚ฌํ•ญ)

์˜ˆ์ œ

  • ์•„๋ž˜๋Š” ๋ฉ”์‹œ์ง€ ์ „์†ก(SEND) ํ”„๋ ˆ์ž„ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.
    ```hash
    SEND
    destination:/queue/test
    content-type:text/plain

Hello, STOMP!

- **๋ช…๋ น :** SEND
- **ํ—ค๋” :** destination:/queue/test, content-type:text/plain
- **๋ณธ๋ฌธ :** Hello, STOMP!

## 3๏ธโƒฃ Spring์—์„œ STOMP ์‚ฌ์šฉ ์˜ˆ์ œ.
- Spring Boot๋Š” **STOMP**์™€ **WebSocket**์„ ๊ฒฐํ•ฉํ•˜์—ฌ ๋ฉ”์‹œ์ง•์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ๋ถ„ ์ง€์›์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

### 1๏ธโƒฃ STOMP ์˜์กด์„ฑ ์ถ”๊ฐ€.
- build.gradle ๋˜๋Š” pom.xml์— ๋‹ค์Œ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

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

2๏ธโƒฃ WebSocket ์„ค์ •.

  • STOMP ์—”๋“œํฌ์ธํŠธ์™€ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๋ฅผ ์„ค์ •ํ•˜๋Š” @Configuration ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
    ```java
    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.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
    config.enableSimpleBroker("/topic"); // ํด๋ผ์ด์–ธํŠธ ๊ตฌ๋… ์ฃผ์†Œ
    config.setApplicationDestinationPrefixes("/app"); // ํด๋ผ์ด์–ธํŠธ ๋ฐœํ–‰ ์ฃผ์†Œ
}

@Override
public void registerStompEndpoints(org.springframework.web.socket.config.annotation.StompEndpointRegistry registry) {
    registry.addEndpoint("/ws") // WebSocket ์—”๋“œํฌ์ธํŠธ
            .setAllowedOrigins("*") // CORS ํ—ˆ์šฉ
            .withSockJS(); // SockJS ์ง€์›
} } ```

3๏ธโƒฃ ์ปจํŠธ๋กค๋Ÿฌ

  • STOMP ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•  ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
    ```java
    import org.springframework.messaging.handler.annotation.MessageMapping;
    import org.springframework.messaging.handler.annotation.SendTo;
    import org.springframework.stereotype.Controller;

@Controller
public class ChatController {

@MessageMapping("/sendMessage") // ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰ํ•  ๊ฒฝ๋กœ
@SendTo("/topic/messages") // ๊ตฌ๋…๋œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ณด๋‚ผ ๊ฒฝ๋กœ
public String sendMessage(String message) {
    return "์„œ๋ฒ„ ์‘๋‹ต: " + message;
} } ```

4๏ธโƒฃ ํด๋ผ๋ฆฌ์–ธํŠธ JavaScript

  • JavaScript๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ STOMP ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๊ณ  ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค.
    ```javascript
    const socket = new SockJS(โ€˜/wsโ€™); // ์„œ๋ฒ„ WebSocket ์—”๋“œํฌ์ธํŠธ
    const stompClient = Stomp.over(socket);

stompClient.connect({}, () => {
console.log(โ€˜WebSocket ์—ฐ๊ฒฐ๋จโ€™);

// ๋ฉ”์‹œ์ง€ ๊ตฌ๋…
stompClient.subscribe('/topic/messages', (message) => {
    console.log('์ˆ˜์‹ ํ•œ ๋ฉ”์‹œ์ง€:', message.body);
});

// ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰
stompClient.send('/app/sendMessage', {}, 'Hello from client!'); }); ```

4๏ธโƒฃ ๊ฒฐ๋ก .

  • STOMP๋Š” WebSocket์„ ๋ณด์™„ํ•˜์—ฌ ํšจ์œจ์ ์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•˜๊ณ  ๊ตฌ๋…ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ฃผ๋Š” ๊ณ ์ˆ˜์ค€ ํ”„๋กœํ† ์ฝœ์ž…๋‹ˆ๋‹ค.
  • Spring Boot์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ง€์›ํ•˜๋ฏ€๋กœ, ์‰ฝ๊ฒŒ ์‹ค์‹œ๊ฐ„ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.