STOMP(Simple Text Oriented Messaging Protocol)

DY·2026년 1월 28일

STOMP란?

STOMP는 텍스트 기반으로 간단하게 서버와 클라이언트 간 쉽게 비동기 메시지 전달을 할 수 있도록 도와주는 프로토콜이다.
공식 문서에서는 TCP와 같은 신뢰 가능한 네트워크 프로토콜 상에서 동작하는 것을 가정하고 있다.
또한, 비동기 메시지 처리를 위해 메시지 브로커 기반으로 동작한다.
공식 문서의 서두에서는 STOMP를 HTTP를 모델로 한 프레임 기반 프로토콜이라고 소개하고 있다.

  • HTTP를 모델로 함 : HTTP와 유사한 형태로 설계됨을 의미 -> HTTP에 익숙한 개발자들이 어렵지 않게 사용할 수 있도록 함
  • 프레임 기반 프로토콜 : 메시지를 전송/수신할 때 지정된 규격의 프레임을 이용

STOMP와 WebSocket의 관계

STOMP는 WebSocket을 이용한 웹 애플리케이션을 만들 때 많이 사용되곤 한다.
WebSocket 자체는 TCP를 통한 양방향 통신 통로만을 만들어줄 뿐,
그 통로를 통해 주고받을 메시지 규격 등은 전혀 정의되어 있지 않기 때문에
애플리케이션 개발을 위해 메시지 포맷 등을 함께 개발해 주어야 하기 때문이다.
하지만 STOMP를 활용하게 되면 이런 부분에 대한 고민 없이 양방향 비동기 애플리케이션을 구현할 수 있다.
위 내용이 WebSocket을 이용할 때 STOMP를 함께 사용하는 이유라면, 반대의 경우는 어떨까?
STOMP는 TCP 기반의 프로토콜이라고 했다. 꼭 WebSocket과 함께 써야 할까?
여기에 대한 답은 "브라우저는 TCP 직접 연결을 허용하지 않는다"는 것이다.
TCP 직접 연결을 우회하기 위해 웹 애플리케이션 개발 시에는 WebSocket 위에서 STOMP를 사용하는 것이다.

프레임 구조

STOMP 프레임은 아래와 같은 형태로 이루어져 있다.

COMMAND
header1:value1
header2:value2

Body^@

헤더에 중복된 키가 있을 경우, 첫 번째 값만 적용된다는 점을 참고해야 하며
텍스트 기반의 프로토콜이지만 바이너리 전송도 지원한다고 한다.

클라이언트와 서버 간 연결

클라이언트는 CONNECT command를 보내고, 서버에서 이를 수락할 경우 CONNECTED command를 보낸다.

클라이언트에서 연결 시도

CONNECT
accept-version:1.2,1.1,1.0
heart-beat:10000,10000

서버에서 연결 수락

CONNECTED
version:1.2
heart-beat:0,0

만약, 서버에서 연결을 거절할 경우 ERROR command와 함께 거부 이유를 전송한다.

클라이언트에서 전송하는 프레임

클라이언트는 SEND/SUBSCRIBE를 통해 서버와 상호작용 한다.

SUBSCRIBE : 특정 목적지의 메시지를 수신(구독)

SUBSCRIBE
id:sub-0
destination:/topic/greetings
  • 위와 같이 전송하여 클라이언트는 /topic/greetings라는 메시지 큐를 구독하기 시작한다.

SEND : 메시지를 서버로 전송

SEND
destination:/app/hello
content-length:18

{"name":"developer"}
  • 클라이언트에서 서버로 메시지를 전송하는데, 이 메시지의 목적지는 서버의 /app/hello 이다.

서버에서 전송하는 프레임

MESSAGE : 메시지를 클라이언트로 전송

MESSAGE
destination:/topic/greetings
content-type:application/json
subscription:sub-0
message-id:ab8f61e6-d1e7-572b-3060-9bbd965fc1a2-0
content-length:31

{"content":"Hello, developer!"}
  • 서버에서 메시지를 /topic/greetings라는 메시지 큐에 넣었고,
    클라이언트는 이 메시지 큐를 구독하고 있었으므로 메시지가 전달된다.
  • 마치 HTTP 응답을 받는 것 같이 미리 정의된 헤더가 세팅되어 함께 전달된다.

연결 해제

DISCONNECT : 서버에 연결 해제 요청

DISCONNECT
receipt:close-1
  • 클라이언트에서는 DISCONNECT 프레임을 보내 연결 해제를 요청한다.

RECEIPT : 연결 해제

RECEIPT
receipt-id:close-1
  • 서버에서 RECEIPT 프레임을 보내 정상적으로 연결이 종료되었음을 알린다.

그 외 command

위에 소개한 것 외에도 다양한 command가 있어 상황에 맞게 사용할 수 있다.

  • UNSUBSCRIBE
    구독을 해제한다.
  • BEGIN
    트랜잭션을 시작한다. 아래 command들은 트랜잭션과 연관이 있다.
  • COMMIT
    진행 중인 트랜잭션을 커밋한다.
  • ABORT
    진행 중인 트랜잭션을 롤백한다.
  • ACK
    클라이언트에서 메시지를 정상적으로 수신하였음을 서버에 알린다.
  • NACK
    ACK과 반대로 클라이언트에서 메시지를 정상적으로 수신하지 못했음을 서버에 알린다.

References

https://stomp.github.io/stomp-specification-1.2.html#RECEIPT
https://docs.spring.io/spring-framework/reference/web/websocket/stomp/overview.html
https://stomp-js.github.io/faqs/faqs.html#p-what-are-stomp-and-webstomp-p
https://www.toptal.com/developers/java/stomp-spring-boot-websocket

0개의 댓글