【JS応用|実務向け】実務で使えるWebSocket:リアルタイム双方向通信の設計と実装の勘所

導入:なぜ今、WebSocketが重要なのか

現代のWebアプリケーションにおいて、チャット機能、ライブダッシュボード、通知システムなど、サーバーからクライアントへ能動的に情報を送る仕組みは不可欠です。従来のHTTPリクエスト(ポーリング)では、サーバーへの接続を繰り返すためオーバーヘッドが大きく、リアルタイム性に欠けていました。WebSocketは一度のハンドシェイクで持続的なコネクションを確立し、低遅延かつ双方向の通信を実現します。これにより、UXの向上とサーバー負荷の軽減を同時に達成できます。

基礎知識:WebSocketの仕組み

WebSocketは、HTTPの「リクエスト・レスポンス」モデルとは異なり、TCP通信をベースとしたステートフルなプロトコルです。クライアントがHTTPで「アップグレードリクエスト」を送り、サーバーがそれを承認することで接続が確立されます。一度接続されると、メッセージはフレームとして送受信され、HTTPヘッダーのような冗長なオーバーヘッドなしにデータ通信が行われます。

実装:WebSocketの基本フロー

ブラウザ標準のWebSocket APIを使用する場合、主要なイベントは「open(接続開始)」「message(受信)」「error(エラー)」「close(接続終了)」の4つです。実装時は「自動再接続ロジック」を組み込むことが実務上の必須要件となります。接続が切断された際、指数バックオフアルゴリズムを用いてサーバーへの負荷を抑えつつ再接続を試みる設計が推奨されます。

サンプルプログラム:堅牢なWebSocket接続クラスの実装例

以下は、実務レベルで最低限備えておくべき自動再接続機能を持つクライアント実装です。

class RealtimeClient {
  constructor(url) {
    this.url = url;
    this.socket = null;
    this.reconnectAttempts = 0;
    this.connect();
  }

  connect() {
    this.socket = new WebSocket(this.url);

    this.socket.onopen = () => {
      console.log("サーバーと接続しました");
      this.reconnectAttempts = 0; // 接続成功時に試行回数をリセット
    };

    this.socket.onmessage = (event) => {
      // サーバーからのデータ受信処理
      const data = JSON.parse(event.data);
      console.log("受信データ:", data);
    };

    this.socket.onclose = () => {
      console.log("接続が切れました。再接続を試みます...");
      this.attemptReconnect();
    };
  }

  // 指数バックオフを用いた再接続処理
  attemptReconnect() {
    const delay = Math.min(1000  Math.pow(2, this.reconnectAttempts), 30000);
    setTimeout(() => {
      this.reconnectAttempts++;
      this.connect();
    }, delay);
  }

  send(data) {
    if (this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(JSON.stringify(data));
    }
  }
}

// 利用例
const client = new RealtimeClient("wss://example.com/socket");

応用・注意点:現場で陥りやすい罠

実務でWebSocketを扱う際は、以下の点に注意してください。

1. プロキシとファイアウォールの透過性
一部の企業ネットワーク環境では、WebSocket接続が遮断されることがあります。この場合、Socket.ioなどのライブラリを使い、HTTPロングポーリングへのフォールバックを自動で行う構成が安全です。

2. メモリリークの防止
コンポーネントが破棄される際には、必ず socket.close() を呼び出し、イベントリスナーを解除してください。これを怠ると、SPA(Single Page Application)ではメモリリークの原因となります。

3. セキュリティ対策
WebSocket通信は標準のHTTPと同様に、Originヘッダーを確認して不正なドメインからの接続をサーバーサイドで拒否してください。また、認証が必要な場合は接続確立時にトークンをヘッダー(またはクエリパラメータ)に含める設計が一般的です。

リアルタイム通信は強力な武器ですが、ネットワーク切断やサーバーのダウンタイムを考慮した「壊れても復旧する設計」が、フロントエンドエンジニアには強く求められます。

タイトルとURLをコピーしました