Spring WebSocket × STOMPメッセージングの基本(publish/subscribe)を初心者向けに解説
新人
「Spring BootでWebSocketを使ったリアルタイム通信の記事を読んでいたら、STOMPという言葉が出てきたんですが、正直よく分かりません」
先輩
「WebSocketだけでも通信はできますが、処理が増えてくると管理が大変になるんです」
新人
「管理が大変というのは、どういう点ですか?」
先輩
「誰に、どのメッセージを送るのかを自分で全部考えないといけない点ですね」
新人
「それを楽にしてくれるのがSTOMPなんですね」
先輩
「そうです。では、STOMPが何者なのかから順番に見ていきましょう」
1. STOMPとは何か(WebSocketだけでは足りない理由)
STOMPとは、WebSocket通信の上で使われるメッセージングのルールです。 Spring WebSocket STOMP を理解するためには、まずWebSocket単体の特徴を振り返る必要があります。
WebSocketは、サーバーとクライアントの間で通信を維持しながら、 双方向にデータをやり取りできる仕組みです。 しかし、WebSocketだけを使う場合、 「どのクライアントに」「どのメッセージを」 送るのかを、すべて自分で制御しなければなりません。
利用者が増えたり、通信の種類が増えたりすると、 処理は一気に複雑になります。 この状態は、宛先を書かずに手紙を大量に配るようなもので、 管理が難しくなりがちです。
そこで登場するのが STOMP です。 STOMPとは、メッセージの送り先や役割を 分かりやすく整理するための仕組みです。 WebSocketだけでは足りない部分を補い、 通信を整理整頓してくれます。
2. publish / subscribe とはどういう仕組みか
publish / subscribe 仕組みは、 メッセージの送信者と受信者を直接つなげない考え方です。 送る側は「どこに送るか」だけを意識し、 受け取る側は「どこを監視するか」だけを意識します。
比喩で考えると、掲示板に近い仕組みです。 誰かが掲示板に情報を書き込むと、 その掲示板を見ている人全員が内容を確認できます。 誰が誰に届けるかを、個別に指定する必要はありません。
publish は「情報を発信する側」、 subscribe は「情報を受信する側」です。 この役割分担によって、 通信の流れが非常に分かりやすくなります。
Spring WebSocket STOMP では、 この publish / subscribe の考え方を使って、 リアルタイム通信をシンプルに実装できます。 これが STOMP とは何かを理解するうえでの重要なポイントです。
3. Spring WebSocketとSTOMPの関係性
Spring WebSocket と STOMP は、 それぞれ役割が異なります。 WebSocket は通信の通り道を提供し、 STOMP はその上を流れるメッセージのルールを提供します。
Spring Boot では、 WebSocket と STOMP を組み合わせることで、 publish / subscribe 仕組みを簡単に導入できます。 開発者は細かい通信制御を意識せずに、 メッセージの内容と流れに集中できます。
まず @Controller を使って画面を表示し、 画面が表示されたあとに WebSocket 接続を開始します。 その WebSocket 通信の中で STOMP が使われ、 メッセージの送受信が整理されます。
@Controller
public class HomeController {
@GetMapping("/")
public String index() {
return "index";
}
}
このコントローラは、 Spring MVC による通常の画面表示を担当します。 STOMP は画面表示の代わりをするものではなく、 画面表示のあとに行われる通信を支える存在です。
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {
}
この設定クラスによって、 Spring WebSocket STOMP の仕組みが有効になります。 WebSocket が通信路を作り、 STOMP がその中のメッセージの流れを整理する、 この関係性を押さえることが大切です。
ここまで理解できれば、 なぜ publish / subscribe 仕組みが必要なのか、 そして WebSocket だけでは不便な理由も、 自然と見えてくるようになります。
4. STOMPメッセージングの基本構成(broker・destination)
STOMP メッセージングを理解するうえで、必ず押さえておきたいのが、 broker と destination という二つの考え方です。 Spring WebSocket STOMP の仕組みは、この二つを中心に成り立っています。
broker は、メッセージの中継役です。 誰かが送信したメッセージを受け取り、 そのメッセージを適切な宛先に配信します。 掲示板や放送局のような存在だと考えると分かりやすくなります。
destination は、メッセージの行き先を表します。 掲示板でいう「掲示板の名前」や、 放送でいう「チャンネル番号」に近いイメージです。 送信する側も受信する側も、 同じ destination を指定することで、 同じ情報を共有できます。
STOMP メッセージングでは、 「誰が送ったか」よりも 「どの destination に送ったか」 が重要になります。 この考え方があることで、 publish / subscribe の通信がシンプルに保たれます。
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}
この設定では、 broker が扱う destination の範囲を指定しています。 初心者の段階では、 「broker がメッセージを配る役割を持つ」 という点だけ理解していれば十分です。
5. publish / subscribe の通信の流れ
publish / subscribe の通信の流れは、 時系列で考えると理解しやすくなります。 Spring WebSocket publish subscribe の流れでは、 まずクライアントが WebSocket 接続を確立します。
接続が完了すると、 クライアントは「この destination を購読します」 という形で subscribe を行います。 これは掲示板の前に立って、 「この掲示板を見ます」と宣言するようなものです。
一方で、サーバー側や別のクライアントが、 ある destination に対してメッセージを publish します。 すると、その destination を購読している全員に、 broker を通じてメッセージが配信されます。
この流れの中で重要なのは、 送信者が受信者を意識していない点です。 publish する側は、 「誰が受け取るか」を知らなくても問題ありません。 これが STOMP 通信 流れの最大の特徴です。
放送に例えるなら、 テレビ局が番組を放送すると、 そのチャンネルを見ている視聴者全員が 同じ内容を受け取るのと同じ仕組みです。
6. Spring WebSocketでのSTOMP処理の位置づけ
Spring WebSocket における STOMP 処理は、 WebSocket 通信の上に乗った「整理役」として位置づけられます。 WebSocket 自体は通信路を提供するだけで、 メッセージの意味や流れは管理しません。
STOMP を使うことで、 メッセージの送信先や購読先が明確になり、 アプリケーション全体の見通しが良くなります。 これは、通信処理が増えてきたときに 特に大きな効果を発揮します。
Spring MVC の @Controller は、 画面表示や通常のリクエスト処理を担当します。 STOMP は、その後のリアルタイム通信部分を支える存在です。 両者は役割が重ならず、補い合う関係にあります。
@MessageMapping("/send")
@SendTo("/topic/messages")
public String sendMessage(String message) {
return message;
}
このような処理では、 STOMP を通じて受け取ったメッセージを、 broker に渡して配信しています。 細かい内部処理を理解する必要はなく、 「STOMP がメッセージの流れを制御している」 と捉えるだけで十分です。
7. Spring MVCの通常通信とSTOMP通信の違い
Spring MVC の通常通信と、 STOMP を使った通信の違いを整理してみましょう。 Spring MVC の通信は、 リクエストとレスポンスが一対一で対応します。
ブラウザがリクエストを送信し、 コントローラが処理を行い、 レスポンスを返した時点で通信は終了します。 次の処理は、別のリクエストとして扱われます。
一方で STOMP 通信では、 WebSocket 接続が維持されたまま、 メッセージの送受信が繰り返されます。 通信が一回で終わらない点が、 通常通信との大きな違いです。
また、Spring MVC は 「このリクエストに対してこのレスポンス」 という明確な対応関係を持ちますが、 STOMP 通信では、 一つの publish が複数の subscribe に届きます。
この違いを理解していないと、 「なぜレスポンスが返らないのか」 「どこで処理が止まっているのか」 といった疑問を持ちやすくなります。 通信の性質が違うという前提を押さえることが、 STOMP メッセージングを理解するための重要なポイントです。
8. STOMPを使うときに初心者がつまずきやすいポイント
Spring WebSocket STOMP 注意点として、初心者が最もつまずきやすいのは、 WebSocket と STOMP の役割を混同してしまう点です。 WebSocket はあくまで通信の通り道であり、 STOMP はその上でメッセージを整理するための仕組みです。 この前提を理解しないまま実装を進めると、 仕組みが分からなくなりやすくなります。
例えば、「WebSocket はつながっているのにメッセージが届かない」 というケースは非常によくあります。 これは通信自体が失敗しているのではなく、 publish した destination と、 subscribe している destination が一致していない場合がほとんどです。 STOMP は宛先を非常に厳密に扱うため、 少しの違いでもメッセージは届きません。
また、Spring MVC の感覚で処理を書いてしまうことも混乱の原因になります。 通常のコントローラ処理では、 リクエストを受け取ると必ずレスポンスが返ってきます。 しかし STOMP 通信では、 レスポンスという概念が存在しない場面も多くあります。
そのため、 「メソッドを呼び出したのに画面に何も返らない」 と感じてしまうことがありますが、 これは STOMP の仕組みを理解していないことが原因です。 STOMP はレスポンスを返すのではなく、 メッセージを broker に流す仕組みだからです。
さらに、WebSocket 単体と STOMP を同時に理解しようとすると、 情報量が多くなりすぎて混乱しがちです。 まずは、 「STOMP は WebSocket を便利に使うための整理役」 というイメージだけをしっかり持つことが大切です。
@MessageMapping("/chat")
@SendTo("/topic/chat")
public String chat(String message) {
return message;
}
このような処理では、 メソッドの戻り値が直接画面に返るわけではありません。 broker を経由して、 subscribe している全員に配信される点を理解していないと、 動作が分からなくなってしまいます。
9. publish / subscribe が向いている処理・向いていない処理
publish subscribe 使いどころを正しく理解することは、 STOMP を使うかどうかを判断するうえで非常に重要です。 STOMP は万能ではなく、 向いている処理と向いていない処理がはっきり分かれます。
publish / subscribe が向いているのは、 同じ情報を複数の利用者に同時に届けたい処理です。 チャット、通知、ステータス更新など、 リアルタイム通信 Spring の代表的なユースケースがこれに当たります。 誰が受け取るかを個別に管理せずに済むため、 実装と設計がシンプルになります。
一方で、向いていないのは、 一人の利用者だけに対して確実に結果を返したい処理です。 例えば、ログイン処理や登録処理のように、 成功や失敗を明確に返す必要がある場合は、 Spring MVC の通常通信の方が適しています。
publish / subscribe は、 「誰かが発信した情報を、興味のある人が受け取る」 という構造に強く、 「この人にだけ返したい結果がある」 という処理とは相性がよくありません。
WebSocket 単体でも、 個別通信は実装できますが、 STOMP を使うと publish / subscribe 前提の設計になります。 そのため、用途を誤ると、 かえって設計が分かりにくくなる場合があります。
初心者のうちは、 「リアルタイムで複数人に同じ情報を届けたいかどうか」 を基準に考えると、 STOMP を使うかどうかの判断がしやすくなります。
10. Spring WebSocket × STOMPの仕組みを理解するための重要ポイント整理
Spring WebSocket と STOMP の仕組みを理解するために、 最後に重要なポイントを整理しておきましょう。 一番大切なのは、 WebSocket と STOMP の役割が明確に分かれていることです。
WebSocket は通信を維持するための土台であり、 STOMP はその上でメッセージの流れを整理します。 WebSocket 単体では自由度が高い反面、 管理が難しくなりやすいという特徴があります。
STOMP を使う理由は、 その複雑さを減らすためです。 destination という概念を使い、 publish / subscribe の形で通信を整理することで、 「誰に何を送るのか」を意識しすぎずに済むようになります。
エラーや混乱の多くは、 実装ミスではなく仕組みの理解不足から生まれます。 メッセージが届かない場合でも、 まずは destination の一致や、 subscribe の有無を確認することが重要です。
また、Spring MVC の通常通信と、 STOMP を使った通信は別物であることを、 常に意識する必要があります。 通常通信の感覚をそのまま STOMP に当てはめると、 挙動が分からなくなりやすくなります。
実務経験がない段階では、 完璧に理解しようとする必要はありません。 「リアルタイム通信を分かりやすく整理するために STOMP を使う」 という大枠の理解ができていれば十分です。 その理解があれば、 Spring WebSocket × STOMP の仕組みは、 少しずつ自然と身についていきます。
@EnableWebSocketMessageBroker
@Configuration
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
}
この設定が、 Spring WebSocket × STOMP の世界への入り口になります。 仕組みを正しく理解することで、 リアルタイム通信 Spring の学習は、 ぐっと進めやすくなるはずです。