カテゴリ: SpringのWeb開発(Spring MVC) 更新日: 2026/02/28

Spring WebSocket の仕組み(ハンドシェイク・双方向通信)を初心者向けに解説

Spring WebSocket の仕組み(ハンドシェイク・双方向通信)
Spring WebSocket の仕組み(ハンドシェイク・双方向通信)

新人と先輩の会話形式で理解しよう

新人

「Spring BootでWebSocketを使う記事を見たんですが、そもそも普通のHTTP通信と何が違うのかが分からなくて…」

先輩

「HTTP通信は、リクエストを送ってレスポンスを受け取ったら、そこで通信が終わる仕組みですね」

新人

「画面を表示するたびに、毎回通信が終わっているイメージです」

先輩

「その通りです。一方でWebSocketは、一度つながると通信を切らずにやり取りが続きます」

新人

「だからリアルタイム通信ができるんですね」

先輩

「そうです。では、まずWebSocketの基本から整理していきましょう」

1. WebSocketとは何か(HTTP通信との違い)

1. WebSocketとは何か(HTTP通信との違い)
1. WebSocketとは何か(HTTP通信との違い)

Spring WebSocket 仕組みを理解するためには、まずHTTP通信との違いを押さえる必要があります。 HTTP通信は、クライアントがリクエストを送信し、サーバーがレスポンスを返した時点で通信が終了します。 このやり取りは毎回独立しており、通信が継続されることはありません。

そのため、サーバー側からクライアントへ何かを通知したい場合でも、 クライアント側から定期的に問い合わせる必要があります。 これがHTTP通信だけではリアルタイム性を実現しにくい理由です。

一方でWebSocketは、最初に接続を確立すると、 サーバーとクライアントの間で通信を維持したままデータをやり取りできます。 この状態では、どちらからでも自由にメッセージを送信できます。 これが HTTP WebSocket 違いの最も大きな特徴です。

チャット機能や通知機能のように、 画面を更新しなくても情報を受け取りたい場面では、 WebSocket の仕組みが非常に有効になります。

2. なぜWebSocketではハンドシェイクが必要なのか

2. なぜWebSocketではハンドシェイクが必要なのか
2. なぜWebSocketではハンドシェイクが必要なのか

WebSocket ハンドシェイクとは、 WebSocket通信を始める前に行われる最初の確認処理のことです。 いきなりWebSocket通信が始まるわけではなく、 最初はHTTP通信を使って接続の合意を行います。

これは、WebSocketがHTTP通信の仕組みを拡張して作られているためです。 クライアントとサーバーの双方が、 「これからWebSocket通信を始めます」 という合意を取る必要があります。 この合意の工程がハンドシェイクです。

比喩で考えると、ハンドシェイクは最初のあいさつのようなものです。 お互いに相手を確認し、 通信方法を切り替える準備が整ったことを確認してから、 双方向通信が始まります。

この工程があることで、 WebSocket通信は安全に、かつ確実に開始されます。 仕組みを知らないと、 「なぜすぐにつながらないのか」 と疑問に感じやすいポイントでもあります。

3. Spring WebSocketで扱う通信の全体像

3. Spring WebSocketで扱う通信の全体像
3. Spring WebSocketで扱う通信の全体像

Spring WebSocketでは、 通常のSpring MVCの画面表示と、 WebSocketによるリアルタイム通信が共存します。 最初の画面表示は、これまで通り @Controller を使って行います。

画面が表示されたあとに、 クライアント側でWebSocket接続が開始され、 ハンドシェイクを経て双方向通信に切り替わります。 この流れを理解することで、 Spring WebSocket 仕組みの全体像が見えてきます。


@Controller
public class HomeController {

    @GetMapping("/")
    public String index() {
        return "index";
    }
}

このコントローラは、HTTP通信による通常の画面表示を担当します。 WebSocketを使う場合でも、 最初のリクエストはこのような形で処理されます。


@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new SimpleWebSocketHandler(), "/ws");
    }
}

この設定によって、 「/ws」というエンドポイントでWebSocket通信を受け付ける準備が整います。 HTTP通信とWebSocket通信は役割が分かれており、 それぞれが適切な場面で動作します。

この全体像を押さえることで、 なぜWebSocketが必要なのか、 そしてHTTP通信だけでは足りない理由が、 自然と理解できるようになります。

4. WebSocketハンドシェイクの仕組みをやさしく理解する

4. WebSocketハンドシェイクの仕組みをやさしく理解する
4. WebSocketハンドシェイクの仕組みをやさしく理解する

WebSocket ハンドシェイク 仕組みを正しく理解することは、 Spring WebSocket を使いこなすための重要な第一歩です。 ハンドシェイクとは、WebSocket通信を始める前に行われる 「最初のあいさつ」のような工程だと考えると分かりやすくなります。

WebSocket通信は、いきなり専用の通信に切り替わるわけではありません。 最初は必ず HTTP 通信としてサーバーにアクセスします。 この段階で、クライアントは 「このあと WebSocket に切り替えたい」 という意思をサーバーに伝えます。

サーバー側も、その要求を確認し、 問題なければ 「では WebSocket 通信に切り替えましょう」 という返答を行います。 このやり取り全体がハンドシェイクです。

比喩で表すなら、 電話をかけて相手が出るまでのやり取りがハンドシェイクにあたります。 いきなり会話が始まるのではなく、 お互いに準備ができたことを確認してから、 本格的な双方向通信が始まるのです。

WebSocket ハンドシェイクは、 通信を安全に切り替えるための大切な工程であり、 省略することはできません。 この仕組みを理解していないと、 「なぜ WebSocket がすぐにつながらないのか」 という疑問を持ちやすくなります。

5. Spring WebSocketでのハンドシェイク処理の位置づけ

5. Spring WebSocketでのハンドシェイク処理の位置づけ
5. Spring WebSocketでのハンドシェイク処理の位置づけ

Spring WebSocket では、 ハンドシェイク処理はフレームワーク側で自動的に行われます。 開発者が一つ一つの通信内容を実装する必要はありません。 その代わり、どこでハンドシェイクが行われているのかを 概念として理解しておくことが重要です。

Spring MVC の @Controller が担当するのは、 あくまで通常の HTTP リクエストとレスポンスです。 WebSocket のハンドシェイクは、 WebSocket 用に設定したエンドポイントにアクセスされたときに 内部的に処理されます。

つまり、@Controller のメソッドが直接 ハンドシェイク処理をしているわけではありません。 Spring WebSocket の設定クラスが、 ハンドシェイクを含む通信の切り替えを担当しています。


registry.addHandler(new SimpleWebSocketHandler(), "/ws");

この設定があることで、 「/ws」にアクセスがあった場合、 Spring は WebSocket 通信を開始する準備に入ります。 最初は HTTP 通信として受け付け、 ハンドシェイクが成功した時点で、 WebSocket 双方向通信へと切り替わります。

初心者のうちは、 「ハンドシェイクは Spring が裏側でやってくれている」 と理解しておくだけで十分です。 重要なのは、 通常の HTTP 処理とは別の場所で動いている、 という点を意識することです。

6. 双方向通信とは何か(リクエストとレスポンスの違い)

6. 双方向通信とは何か(リクエストとレスポンスの違い)
6. 双方向通信とは何か(リクエストとレスポンスの違い)

WebSocket 双方向通信を理解するためには、 HTTP通信のリクエストとレスポンスの考え方と 比較するのが効果的です。 HTTP通信では、 必ずクライアントからリクエストを送り、 それに対してサーバーがレスポンスを返します。

この関係は一方向的で、 サーバーから先に何かを送ることはできません。 クライアントが何もしなければ、 通信は発生しない仕組みです。

一方で WebSocket の双方向通信では、 接続が確立されたあと、 サーバーとクライアントのどちらからでも メッセージを送信できます。 これが双方向通信と呼ばれる理由です。

例えるなら、 HTTP通信は質問と回答が一回ずつのやり取りで、 WebSocket通信は会話が続くチャットのようなものです。 どちらが先に話し出しても問題ありません。


protected void handleTextMessage(WebSocketSession session, TextMessage message)
        throws Exception {
    session.sendMessage(new TextMessage("サーバーから返信"));
}

この処理では、 クライアントからのメッセージを受信したあと、 サーバー側から即座にメッセージを返しています。 これが WebSocket 双方向通信の基本的な動きです。

この仕組みがあるからこそ、 リアルタイム性の高い Web アプリケーションが実現できます。

7. Spring MVCの通常通信とWebSocket通信の流れ比較

7. Spring MVCの通常通信とWebSocket通信の流れ比較
7. Spring MVCの通常通信とWebSocket通信の流れ比較

Spring WebSocket 通信 流れを正しく理解するためには、 Spring MVC の通常通信と並べて考えることが重要です。 まず、通常の Spring MVC 通信では、 ブラウザが URL にアクセスし、 @Controller がリクエストを受け取ります。

コントローラは処理を行い、 レスポンスとして画面やデータを返します。 この時点で通信は終了し、 次の処理は新しいリクエストとして始まります。

一方で WebSocket 通信では、 最初のアクセスは HTTP 通信として始まりますが、 ハンドシェイクを経て通信が切り替わります。 切り替え後は、 通信が終了せずに維持され続けます。

Spring MVC が 「画面を表示する役割」 を担っているのに対し、 WebSocket は 「画面が表示されたあとのリアルタイム通信」 を担当していると考えると理解しやすくなります。

この役割の違いを意識することが、 Spring WebSocket を正しく使うための重要なポイントです。 通常通信と WebSocket 通信は競合するものではなく、 それぞれが補い合う関係にあります。

8. WebSocket通信で初心者がつまずきやすいポイント

8. WebSocket通信で初心者がつまずきやすいポイント
8. WebSocket通信で初心者がつまずきやすいポイント

Spring WebSocket 注意点として、初心者が最初につまずきやすいのは、 「HTTP通信と同じ感覚で考えてしまうこと」です。 WebSocketはHTTP通信を土台にしていますが、 接続が確立されたあとは、まったく異なる性質を持つ通信になります。

例えば、HTTP通信では、 リクエストを送れば必ずレスポンスが返ってきます。 しかしWebSocketでは、 接続が成功しても、何も送られてこない状態が普通に存在します。 この挙動を知らないと、 「通信が失敗しているのではないか」 と不安になりやすくなります。

また、ハンドシェイクが終わる前に WebSocket通信が始まると思い込んでしまうのも、 よくあるつまずきポイントです。 実際には、最初はHTTP通信として処理され、 その後に双方向通信へ切り替わります。 この順序を理解していないと、 なぜ処理が呼ばれないのか分からなくなります。

さらに、WebSocket通信は 「常につながっている状態」が前提になります。 そのため、画面遷移や再読み込みが行われると、 接続が切断されることがあります。 この挙動を知らないと、 動いたり動かなかったりする不安定な印象を受けがちです。


@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    // 接続が確立されたときに呼ばれる
}

このようなメソッドが存在することからも分かるように、 WebSocketでは「接続状態」という概念が重要になります。 エラーや動かない原因の多くは、 実装ミスではなく、 仕組みの理解不足によるものです。

9. 双方向通信が向いている処理・向いていない処理

9. 双方向通信が向いている処理・向いていない処理
9. 双方向通信が向いている処理・向いていない処理

双方向通信 仕組みを理解するうえで大切なのは、 WebSocketが万能ではないという点です。 リアルタイム通信 Spring の文脈では非常に強力ですが、 すべての処理に適しているわけではありません。

WebSocketが向いている処理は、 サーバー側から即座に通知したい場面です。 例えば、チャット、通知、状態の変化の即時反映などが挙げられます。 これらはHTTP通信だけで実現しようとすると、 頻繁な問い合わせが必要になり、効率が下がります。

一方で、画面表示や画面遷移、 データ登録や検索のような処理は、 通常のHTTP通信の方が適しています。 これらの処理は、 リクエストとレスポンスが明確で、 通信が継続する必要がないからです。

WebSocketを使うべきかどうか迷った場合は、 「通信を維持する必要があるか」 「サーバーから自発的に送る必要があるか」 という二点を基準に考えると判断しやすくなります。

双方向通信は便利ですが、 使いどころを誤ると、 かえって設計が複雑になります。 HTTP通信とWebSocket通信を 適切に使い分ける意識が重要です。

10. Spring WebSocketの仕組みを理解するための重要ポイント整理

10. Spring WebSocketの仕組みを理解するための重要ポイント整理
10. Spring WebSocketの仕組みを理解するための重要ポイント整理

Spring WebSocket 仕組みを整理すると、 いくつかの重要な考え方に集約できます。 まず、WebSocketはHTTP通信の延長線上にあるという点です。 最初は必ずHTTP通信から始まり、 ハンドシェイクを経て双方向通信へ切り替わります。

次に、Spring MVCとWebSocketは役割が異なるという点です。 @Controllerは画面表示や通常のリクエスト処理を担当し、 WebSocketは画面表示後のリアルタイム通信を担当します。 この役割分担を意識することが、 設計をシンプルに保つコツです。

また、WebSocketでは 接続状態が継続することが前提になります。 そのため、接続の開始と終了、 どのタイミングで通信が行われるかを イメージできるようになることが重要です。


@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status)
        throws Exception {
    // 接続が切断されたときの処理
}

このような処理が存在することからも、 WebSocketでは通信のライフサイクルを 意識する必要があることが分かります。 これらのポイントを押さえておくことで、 Spring WebSocket に対する理解が一段深まります。

11. 次に学ぶとよい関連トピック(非同期処理・STOMP・リアルタイム通信)

11. 次に学ぶとよい関連トピック(非同期処理・STOMP・リアルタイム通信)
11. 次に学ぶとよい関連トピック(非同期処理・STOMP・リアルタイム通信)

Spring WebSocket の基本的な仕組みを理解できたら、 次に学ぶとよい関連トピックがいくつかあります。 その一つが非同期処理です。 WebSocket通信は非同期で動作するため、 非同期処理の考え方を知ることで理解が深まります。

また、STOMPという仕組みも、 WebSocketと一緒によく使われます。 STOMPはメッセージのやり取りを整理するための仕組みで、 大規模なリアルタイム通信を扱う際に役立ちます。 ただし、初心者の段階では 概要を知る程度で十分です。

さらに、リアルタイム通信 Spring という観点では、 WebSocket以外の方法と比較することも学習になります。 なぜWebSocketが選ばれるのか、 どんな場面で強みを発揮するのかを 改めて整理すると理解が定着します。

これらの関連トピックに進む前に、 HTTP通信とWebSocket通信の違い、 ハンドシェイクと双方向通信の意味を しっかり言葉で説明できる状態にしておくことが大切です。 それが、次のステップへ進むための確かな土台になります。

コメント
コメント投稿は、ログインしてください

まだ口コミはありません。

カテゴリの一覧へ
新着記事
New1
Springの基本
Spring Bootの@ConfigurationPropertiesScanとは?設定クラス自動検出の仕組みを解説
New2
SpringのAPI開発(REST & GraphQL)
Spring Boot GraphQLでResolverを理解しよう!初心者でもわかるデータ取得の基本
New3
SpringのAPI開発(REST & GraphQL)
Spring Boot GraphQL入門!Query・Mutation・Subscriptionの基本を初心者向けに解説
New4
SpringのDB操作
JPQLのパラメータバインド(:name / ?1)の使い方を完全解説!初心者でも迷わない基本の考え方
人気記事
No.1
Java&Spring記事人気No1
Thymeleaf
Thymeleaf とは?初心者向けにThymeleafの基本を徹底解説
No.2
Java&Spring記事人気No2
SpringのWeb開発(Spring MVC)
DispatcherServletの仕組みを理解する!初心者向け完全ガイド
No.3
Java&Spring記事人気No3
Springの基本
Spring Bootのデフォルトログ設定を徹底解説(Logback / SLF4J)
No.4
Java&Spring記事人気No4
SpringのDB操作
JPAの標準クエリメソッド(findById, findAll)を完全解説!初心者でもわかるデータ取得の基本
No.5
Java&Spring記事人気No5
SpringのWeb開発(Spring MVC)
Spring Bootでの@GetMappingと@PostMappingの基本を完全解説!初心者でも理解できる使い方
No.6
Java&Spring記事人気No6
SpringのWeb開発(Spring MVC)
@Controller と @RestController の違いを完全解説!初心者向けSpring MVC入門
No.7
Java&Spring記事人気No7
Spring認証(Spring Security)
セッション管理の基本(@SessionAttributes)を完全解説!初心者でもわかるセッションの仕組み
No.8
Java&Spring記事人気No8
SpringのWeb開発(Spring MVC)
ループ処理(th:each)の基本を完全ガイド!Thymeafの繰り返し処理の使い方