WebSocketとリアルタイム通信 — 「更新ボタン」なしで最新情報が届く仕組み
バイブコーディング入門 — 第22回
前回のおさらいと、今回のテーマ
前回(第21回)では、SPA・SSR・SSGというWebページの「描き方」の違いを学んだ。ブラウザ側で描くのか、サーバー側で描くのか、あらかじめ描いておくのか。アプリの性質によって最適な方式が変わることがわかった。
今回のテーマは「リアルタイム通信」だ。
あなたが8人のデザイン事務所の代表だとしよう。バイブコーディングで社内チャットアプリを作ろうとした。AIに「メンバー同士がメッセージをやり取りできるアプリを作って」と伝えたところ、AIがこう返してきた。
「WebSocketを使ってリアルタイム通信を実装します。Supabase Realtimeでチャンネルをサブスクライブして、新しいメッセージをリアルタイムに受信できるようにしますね」
WebSocket。リアルタイム通信。サブスクライブ。チャンネル。何のことだかわからない。でも、AIが自信たっぷりに進めているから、とりあえず「はい」と答えてしまう。
この記事を読み終えると、次のことがわかるようになる。
- HTTPの「手紙方式」ではなぜ限界があるのか
- WebSocket(電話回線方式)とSSE(ラジオ放送方式)の違い
- どんなアプリにどの方式が合うのか
- Supabase Realtimeとは何か
- AIにリアルタイム機能を依頼するテンプレート
第1回で学んだ「Webは手紙のやりとり」という知識が、ここでもう一段深まる。
HTTPの限界 — 「手紙のやりとり」では間に合わない場面
第1回で、Webの通信は「手紙のやりとり」だと学んだ。ブラウザが「このページを見せて」と手紙を送り(リクエスト)、サーバーが「はい、どうぞ」と手紙を返す(レスポンス)。この仕組みがHTTPだった。
HTTPには大事なルールがある。「必ずブラウザ側から手紙を出さないと、サーバーは返事を返せない」というルールだ。第11回で学んだ「ステートレス」の特徴でもある。サーバーは、聞かれないかぎり何も言えない。
このルールが問題になる場面がある。具体的に3つの例を挙げる。
1つ目: チャットアプリ。相手がメッセージを送ったら、あなたの画面にすぐ表示されてほしい。しかしHTTPでは、あなたのブラウザが「新しいメッセージある?」と聞かないかぎり、サーバーは教えてくれない。
2つ目: 共同編集ツール。Googleドキュメントのように、複数人が同じ文書を同時に編集する場面。誰かが1文字タイプするたびに、他の全員の画面に反映されてほしい。しかしHTTPでは、自分から聞きにいかないと変更がわからない。
3つ目: 通知機能。「新しい問い合わせが入りました」「タスクの期限が近づいています」といった通知をリアルタイムに受け取りたい。しかしHTTPでは、定期的に「通知ある?」と聞きにいかないかぎり、永遠に届かない。
これらすべてに共通するのは、「サーバー側で何かが起きたとき、すぐにブラウザに伝えたい」という要求だ。HTTPの「聞かれないと答えられない」ルールでは、これに対応できない。
ポーリング — 力業の解決策とその限界
HTTPのまま、なんとかリアルタイムっぽい動きを実現する方法がある。「ポーリング」と呼ばれる手法だ。
ポーリングとは、ブラウザが一定間隔でサーバーに「新しい情報ある?」と聞きにいく仕組みだ。たとえば3秒ごとに「メッセージある?」「メッセージある?」「メッセージある?」と繰り返し問い合わせる。
これは手紙のたとえで言えば、3秒ごとに郵便ポストを覗きに行くようなものだ。ほとんどの場合、ポストは空っぽだ。でも万が一に備えて、3秒ごとに確認しにいく。
問題は明らかだ。
- 無駄が多い。新しい情報がないときでも、ずっと問い合わせ続ける。8人のチャットアプリで全員が3秒ごとにポーリングすれば、1分間に160回のリクエストがサーバーに飛ぶ。情報がないのに、だ
- タイムラグがある。3秒ごとの確認なら、最大3秒の遅延が発生する。チャットで3秒待たされると、ストレスを感じる
- サーバーの負荷が高い。ユーザーが増えるほど、無駄なリクエストが倍増する
ポーリングは「動くけれど、筋がよくない」解決策だ。もっとスマートな仕組みが必要になる。
WebSocketとは — 「電話回線」を開きっぱなしにする
WebSocketは、HTTPの限界を解決するために生まれた通信方式だ。
たとえで説明しよう。HTTPが「手紙のやりとり」なら、WebSocketは「電話をかけて、つなぎっぱなしにする」ようなものだ。
手紙は、1通送って1通返ってくるまでに時間がかかる。送るたびに封筒に入れて、宛名を書いて、切手を貼って、ポストに入れて、配達を待つ。返事を受け取るのにも同じ手間がかかる。
電話なら、最初にダイヤルしてつながったら、あとはお互いに好きなタイミングで話せる。「今から言うよ」「聞いてるよ」のやりとりが瞬時にできる。手紙のような手間は毎回かからない。
WebSocketもまったく同じ構造だ。
- 最初に「接続を確立する」(電話をかけて相手が出る)
- 接続が確立したら、ブラウザからもサーバーからも、好きなタイミングでデータを送れる
- 用が済んだら「接続を切る」(電話を切る)
重要なのは2番目だ。HTTPでは「ブラウザからしか手紙を出せない」ルールがあった。WebSocketでは、サーバー側からもデータを送れる。新しいチャットメッセージが届いたら、サーバーがすぐにブラウザに「新着メッセージだよ」と伝えられる。ブラウザが聞きにいく必要がない。
WebSocketが使われている身近なアプリ
WebSocketは、あなたが日常的に使っているアプリの裏側で動いている。
- Slack: メッセージを送ると、相手の画面にすぐ表示される。裏でWebSocketが動いている
- Googleドキュメント: 同僚が文字を打つと、自分の画面にもリアルタイムで反映される
- Uber / Grab: 配車アプリで車の現在位置がリアルタイムに動く地図表示
- 株価チャート: 数字が1秒ごとに変わるリアルタイムチャート
- オンラインゲーム: プレイヤーの動きが即座に他のプレイヤーの画面に反映される
どれも共通しているのは「ページを更新しなくても、新しい情報が次々に届く」という体験だ。この「更新ボタンを押さなくていい」という快適さの裏には、WebSocketがある。
WebSocketの仕組み — 3ステップ
もう少し具体的に見てみよう。
ステップ1: ハンドシェイク(握手)。ブラウザがサーバーに「HTTPからWebSocketに切り替えたい」とお願いする。サーバーが「いいよ」と応じる。この最初のやりとりだけはHTTPで行う。握手が済むと、通信方式がHTTPからWebSocketに切り替わる。
ステップ2: 双方向通信。握手が済んだら、ブラウザとサーバーの間に「常時接続された回線」ができる。この回線を通じて、どちらからでもデータを送信できる。ブラウザがメッセージを送る。サーバーがそれを他の参加者のブラウザに転送する。すべてが即座に行われる。
ステップ3: 切断。ユーザーがページを閉じるか、アプリを終了すると、接続が切断される。電話を切るのと同じだ。
SSE(Server-Sent Events)— 「ラジオ放送」方式
WebSocketは「電話」だった。お互いに話せる双方向通信だ。
しかし、すべての場面で双方向が必要とは限らない。「サーバーからブラウザへ、一方的にデータを送り続けたい」という場面も多い。そんなときに使うのがSSE(Server-Sent Events、サーバー・セント・イベンツ)だ。
SSEを一言で言えば「ラジオ放送」だ。
ラジオ放送では、放送局(サーバー)が一方的に情報を流す。リスナー(ブラウザ)はそれを聞くだけだ。リスナーから放送局に話しかけることはできない。でも、新しいニュースや音楽が入ったら、すぐにリスナーに届く。
SSEも同じ構造だ。サーバーがブラウザに対して、一方向にデータを送り続ける。ブラウザ側からサーバーにデータを送る必要がない場面では、SSEの方がWebSocketよりシンプルで扱いやすい。
SSEが使われている身近な例
SSEが最もわかりやすい例は、あなたも使ったことがあるはずだ。
Claude(このメディアの主役)にチャットで質問すると、回答が1文字ずつ流れるように表示される。あの「タイプライターのように文字が次々に現れる」演出は、SSEで実現されていることが多い。サーバー側でAIが1単語ずつ回答を生成し、生成されるたびにブラウザに送っている。全部の回答が完成するまで待つのではなく、できたところから順次届けるのだ。
他にも:
- ニュースサイトの速報テロップ。新しいニュースが入ると、ページ上部のテロップが自動で更新される
- SNSの通知バッジ。「新しいいいね」「新しいコメント」の数字がリアルタイムに増える
- ダッシュボードの数値更新。売上、アクセス数、在庫数などの数字が定期的に最新値に切り替わる
どれも「サーバーからの一方通行」だ。ブラウザからサーバーに何かを送る必要がない。
SSEの仕組み
SSEの仕組みはWebSocketよりシンプルだ。
- ブラウザがサーバーに「データを送り続けて」とリクエストする(これは普通のHTTPリクエスト)
- サーバーがレスポンスを「閉じずに」、データが発生するたびに少しずつ送り続ける
- ブラウザがページを閉じると、接続が終了する
イメージとしては、手紙を1通送ったら、返事がものすごく長い巻物で返ってくるようなものだ。巻物はまだ書き終わっていないけれど、書けたところから順次あなたの手元に届く。
HTTPの枠組みの中で動くので、WebSocketのような「通信方式の切り替え」は必要ない。そのため、導入がWebSocketより手軽だ。
WebSocket vs SSE vs ポーリング — 3つの選択肢の使い分け
3つの方式をまとめよう。
では、ポーリングを含めた3つを、どう使い分ければよいのか。
チャットアプリを作りたい → WebSocket。双方向のやりとりが必要だからだ。メッセージの送信(ブラウザ→サーバー)と受信(サーバー→ブラウザ)の両方がリアルタイムに必要。
通知機能を付けたい → SSE。サーバーからブラウザへ「新着がありますよ」と一方的に送ればよい。ブラウザからサーバーにリアルタイムで何かを送る必要はない。
AIの回答をストリーミング表示したい → SSE。AIの回答はサーバーからブラウザへの一方通行だ。ユーザーの入力は通常のHTTPリクエストで送ればよい。
1日に数回しか更新されないデータを表示したい → ポーリング。リアルタイム性がそこまで重要でないなら、30秒〜1分ごとの確認で十分だ。WebSocketやSSEの仕組みを入れるほどでもない。
共同編集ツールを作りたい → WebSocket。複数人の入力を即座に全員に反映する必要がある。双方向かつ低遅延が求められる。
バイブコーディングでの判断基準
バイブコーディングでは、AIがこれらの方式を自動で選んでくれることが多い。しかし、AIの選択が適切かどうかを判断するために、次の2つの質問を自分に投げかけてみよう。
質問1: ブラウザからサーバーにもリアルタイムでデータを送る必要があるか? → Yes ならWebSocket。No ならSSEを検討。
質問2: そもそもリアルタイムである必要があるか? 数秒〜数十秒の遅延は許容できるか? → 遅延OK ならポーリングで十分。リアルタイム必須ならWebSocketまたはSSE。
Supabase Realtime — バイブコーダーの味方
第18回でSupabaseを学んだ。データベース、認証、RLSを提供するサービスだった。実は、SupabaseにはもうひとつWebSocket技術を使った機能がある。「Supabase Realtime」だ。
Supabase Realtimeは、データベースの変更をリアルタイムにブラウザに届ける機能だ。たとえば、誰かがチャットメッセージをデータベースに保存した瞬間、他の全員のブラウザにそのメッセージが届く。自分でWebSocketの仕組みをゼロから作る必要がない。
Supabase Realtimeの3つの機能
Supabase Realtimeには3つの使い方がある。
1つ目: データベース変更の監視。テーブルに新しい行が追加されたり、既存の行が更新されたりしたとき、自動的にブラウザに通知が届く。チャットアプリの「新しいメッセージが来たら即表示」はこれで実現できる。
2つ目: ブロードキャスト。特定の「チャンネル」(部屋のようなもの)に参加しているブラウザ全員にメッセージを送る。グループチャットやリアルタイムのアンケート結果表示に向いている。
3つ目: プレゼンス。「今、誰がオンラインか」をリアルタイムに追跡する。Googleドキュメントで「田中さんが編集中」と表示されるのと同じ仕組みだ。
AIに依頼するテンプレート
バイブコーディングでリアルタイム機能を作る場面が来たら、次のテンプレートを使うとAIへの指示が正確になる。
テンプレート: リアルタイム機能の依頼
「このアプリにリアルタイム機能を追加したい。
実現したいこと:
- (例: 新しいメッセージが投稿されたら、全員の画面に即座に表示される)
- (例: 今オンラインのメンバーをアイコン表示する)
- (例: 在庫数が変わったら、管理画面の数字が自動更新される)
技術的な条件:
- Supabase Realtimeを使ってほしい
- 接続が切れた場合は自動で再接続してほしい
- ユーザーがページを離れたら接続をクリーンアップ(後片付け)してほしい
- 同時接続数の上限を教えてほしい(Supabaseのプランによる制限)
心配な点:
- 10人同時に使っても問題ないか
- 月額費用に影響はあるか
- 接続が不安定な環境(モバイル回線など)でも動くか
上記を踏まえた実装を提案してほしい。通信方式(WebSocket、SSE、ポーリング)の選定理由も説明してほしい。」
ポイントは「通信方式の選定理由も説明してほしい」という一文だ。AIがなぜWebSocketを選んだのか、SSEでもよかったのではないか、と聞くことで、自分のアプリに本当に合った方式かどうかを確認できる。
リアルタイム通信の注意点 — 知っておくべき3つのこと
リアルタイム通信は便利だが、HTTPのシンプルな「手紙方式」にはない注意点がある。
1. 接続管理が必要になる
HTTPでは、1回手紙を送って返事が来たら終わりだった。接続が途切れても、次のリクエストを送ればいい。
WebSocketでは「つなぎっぱなし」なので、接続の管理が必要になる。回線が途切れたらどうする? ユーザーがスマートフォンの電波が悪い場所に移動したら? パソコンがスリープから復帰したら? これらのケースで「自動的に再接続する」仕組みを入れておかないと、画面が固まったように見えてしまう。
バイブコーディングでは、AIにこう伝えるとよい。「接続が切れた場合の再接続処理も入れてほしい。再接続中は画面に『接続中...』と表示してほしい」。
2. サーバーの負荷が変わる
HTTPでは、リクエストが来たときだけサーバーが働く。アクセスがなければ、サーバーはほとんど何もしていない。
WebSocketでは、接続している全員分の「回線」をサーバーが保持し続ける。10人が接続していれば10本、100人なら100本の回線を同時に維持する。ユーザー数が増えると、サーバーの負荷も増える。
Supabaseの無料プランでは、Realtime接続の同時接続数に上限がある(200接続)。8人のデザイン事務所なら余裕だが、将来ユーザーが増えることを見越して、プランの確認はしておこう。
3. データの順序と整合性
リアルタイムにデータが飛び交うと、順序がずれる場合がある。チャットで「A」「B」「C」と送ったのに、受信側では「A」「C」「B」の順に届くことがある。ネットワークの遅延や経路の違いによるものだ。
バイブコーディングでは、AIに「メッセージの表示順はタイムスタンプ(送信時刻)でソートしてほしい」と伝えておけば、表示上の順序は正しく保たれる。
よくある不安と答え
WebSocketを使うと料金が高くなるのか
Supabase無料プランでもRealtime機能は使える。同時接続数200、1秒あたり100メッセージまでは無料枠に含まれる。8人の社内チャットなら無料枠で十分だ。ただし、接続を切り忘れる実装にすると、不要な接続がたまってしまうことがある。AIに「ページを離れたら接続を切る処理を入れて」と伝えておこう。
リアルタイム通信はセキュリティが心配
第17回で学んだHTTPSは、WebSocket通信にも適用される。WebSocketをHTTPS上で使う場合、通信は暗号化される(この場合、ws://ではなくwss://というURLになる)。また、Supabase RealtimeはRLS(行レベルセキュリティ)と連動するので、第18回で学んだアクセス制御がリアルタイム通信にも効く。
自分のアプリにリアルタイム通信は本当に必要か
不要なケースも多い。たとえば、顧問先管理アプリで「顧問先一覧を表示する」だけなら、リアルタイムは不要だ。ページを表示するときに最新データを取得すればよい。
「リアルタイムが必要か」の判断基準は、「2人以上が同時に同じ画面を見ていて、一方の操作がもう一方にすぐ反映されてほしいか」だ。YesならWebSocketかSSEを検討する。Noなら通常のHTTPで十分だ。
AIがWebSocketを提案してきたが、SSEでよいのではないか
よい質問だ。AIは「とりあえずWebSocket」と提案しがちだ。しかし、サーバーからブラウザへの一方通行で済む場面なら、SSEの方がシンプルで管理も楽だ。AIに「この機能はSSEでも実現できるか? WebSocketにした理由を教えて」と聞いてみよう。理由が「双方向通信が必要だから」なら、WebSocketが適切だ。明確な理由がなければ、SSEに切り替えてもらうことを検討してよい。
まとめ
HTTPの「手紙方式」は、聞かないと答えてもらえない。チャットや通知など「サーバーからすぐ届けたい」場面では限界がある。WebSocket(電話方式)は双方向の常時接続、SSE(ラジオ方式)はサーバーからの一方向通信。双方向が必要ならWebSocket、一方向で済むならSSE、リアルタイム不要ならHTTPのままで十分だ。Supabase Realtimeを使えば、自分でWebSocketの仕組みをゼロから作る必要はない。
次回は最終回。「これからのWeb — バイブコーダーが知っておくべき未来」をテーマに、HTTP/3、GraphQL、Edge Computing、AIとWebの融合など、今後あなたのバイブコーディング体験に影響を与える技術トレンドを概観する。
参考リファレンス
- 前回: 第21回「SPA・SSR・SSG — レンダリング方式の選び方」(/articles/vc-021)
- 次回: 第23回「これからのWeb — バイブコーダーが知っておくべき未来」(/articles/vc-023)
- 第1回「あなたのWebアプリは『手紙のやりとり』で動いている」(/articles/vc-001)
- 第11回「ステートレスとCookie/セッション — 『ログイン状態』の正体」(/articles/vc-011)
- 第17回「HTTPS・セキュリティの基本」(/articles/vc-017)
- 第18回「データベースの基本 — Webアプリの『記憶』を理解する」(/articles/vc-018)
- バイブコーディング入門 カリキュラム(/vibe-coding)




