このレッスンのロックを解除するには、まず「接続のライフサイクル、エラー、ハートビートの管理」を完了してください。前のレッスンに戻る

はじめに

リアルタイムアプリケーションでは、WebSocket単独で完結することはほとんどありません。クライアントにはターゲティングされたメッセージ(特定の1つのソケットへの送信)とブロードキャストイベント(接続中のすべてのクライアントへの送信)の両方が必要になります。さらに、ほとんどの実用的なプロダクトでは依然としてREST APIを公開しています。例えば、ユーザーがHTTP経由でフォームを送信したとき、その変更を開いているすべてのWebSocketセッションに即座に表示したいはずです。このレッスンではまさにそこを扱います。Node.jsサーバーからイベントを送受信する方法、およびRESTエンドポイントとWebSocketレイヤーを橋渡しして両方のインターフェースを同期させる方法を学びます。

RESTクライアント、RESTエンドポイント、WebSocketサーバー、複数のWebSocketクライアントを含む全体的なアーキテクチャ図と双方向の矢印

1つのクライアントへの送信とブロードキャスト

接続されているすべてのソケットにはサーバーによって一意のidが割り当てられます。そのidを使ってプライベートメッセージを送信できます。

javascript
io.to(socket.id).emit("private:message", { text: "only you see this" });

接続中のすべてのクライアントに同じペイロードを受信させたい場合は、ルート名前空間に対してターゲット引数なしでブロードキャストします:

javascript
io.emit("announcement", { text: "Server restarts in 5 minutes" });

`socket.broadcast.emit`もあり、これはイベントをトリガーしたソケット以外の全員に送信します。これは送信者にメッセージをエコーバックしたくないチャットルームなどで便利です。

RESTエンドポイントとWebSocketイベントの橋渡し

一般的なパターンは次のとおりです。RESTハンドラーが自身の処理(DB書き込み、入力検証など)を実行し、続いてWebSocketレイヤーに更新をプッシュするよう依頼します。ExpressとSocket.IOを併用した最小限の例を示します:

javascript
const express = require("express");
const http = require("http");
const { Server } = require("socket.io");
const app = express();
app.use(express.json());
const server = http.createServer(app);
const io = new Server(server);
app.post("/orders", (req, res) => {
const order = { id: Date.now(), item: req.body.item, status: "created" };
io.emit("order:new", order);
res.status(201).json(order);
});
io.on("connection", (socket) => {
console.log("client connected:", socket.id);
});
server.listen(3000);

HTTPクライアントはRESTレスポンスで作成されたオーダーを取得し、WebSocket経由で接続されているすべてのブラウザタブが同時に`order:new`イベントを受信します。一度の書き込みで二つのインターフェースへ配信されます。

REST POSTからデータベース、ブロードキャストイベント、クライアントへのレスポンスまでの4ステップのフロー図

特定のルームへの配信

「全員」や「1つのソケット」より細かい制御が必要な場合は、ルームを使います。ルームはソケットが参加・退出できる名前付きのチャンネルに過ぎません:

javascript
io.on("connection", (socket) => {
socket.join("orders");
socket.to("orders").emit("order:new", order);
});

`socket.to("orders")`はそのルーム内のソケットのうち送信者以外に到達します。`io.to("orders").emit(...)`は送信者を含むルーム内の全員に到達します。ルームはユーザー単位・チーム単位・トピック単位のフィードをカスタムルーティングロジックなしで実装する標準的な手段です。

よくある間違い

RESTハンドラー内で`io.emit`を呼ぶこと自体は問題ありませんが、RESTレスポンスとWebSocket emitは独立している点に注意してください。WebSocketレイヤーがクラッシュしてもHTTPリクエストは成功を返します。重要なフローでは、ブロードキャストをtry/catchで囲み失敗をログに残してください。もう一つのよくある間違いは、`socket.emit`(現在のソケットのみ送信)と`io.emit`(全体に送信)の挙動を同じと勘違いすることです。意図に合わせて適切な方を選んでください。最後に、クライアントから送られる`socket.id`は決して信用せず、プライベートデータを送る前に必ずサーバー側で認証済みセッションから照合してください。

まとめ

これで3つの配信モードが揃いました。現在のクライアント向けの`socket.emit`、全体ブロードキャストの`io.emit`、そして特定グループ向けのルームです。RESTハンドラーと`io.emit`(または`io.to(room).emit`)を組み合わせるのが、HTTPとWebSocketのインターフェースを整合させる標準的なブリッジパターンです。主要なビジネスロジックの後でブロードキャストを行い、WebSocketの失敗には適切に対処し、プライベートペイロードを送る前に必ずサーバー側で身元を確認してください。

レッスンの練習

レッスンのチェックポイント

学んだ内容を復習し、回答へのフィードバックを受けましょう。

0/1
回答済み · 0/1