STOMP는 텍스트 기반으로 간단하게 서버와 클라이언트 간 쉽게 비동기 메시지 전달을 할 수 있도록 도와주는 프로토콜이다.
공식 문서에서는 TCP와 같은 신뢰 가능한 네트워크 프로토콜 상에서 동작하는 것을 가정하고 있다.
또한, 비동기 메시지 처리를 위해 메시지 브로커 기반으로 동작한다.
공식 문서의 서두에서는 STOMP를 HTTP를 모델로 한 프레임 기반 프로토콜이라고 소개하고 있다.
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
id:sub-0
destination:/topic/greetings
SEND
destination:/app/hello
content-length:18
{"name":"developer"}
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!"}
DISCONNECT
receipt:close-1
RECEIPT
receipt-id:close-1
위에 소개한 것 외에도 다양한 command가 있어 상황에 맞게 사용할 수 있다.
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