プロトコル

gRPCとWebSocketの違いは?双方向通信の仕組み・ブラウザ到達性・LB通過性で使い分ける

gRPCとWebSocketの違いは?双方向通信の仕組み・ブラウザ到達性・LB通過性で使い分ける

双方向でリアルタイムに、という要件が出た時点で候補に挙がるのがWebSocketとgRPCです。どちらも一度つないだ接続の上を双方から流せる点は同じで、速度やデータ形式を並べた比較表を眺めても決め手が出てきません。判断が割れる場所は3つだけ。呼び出し元がブラウザかどうか、経路にどんな中継装置があるか、インタフェースを何人で共有するかです。プロトコル単体の成り立ちはgRPCの仕組みとRESTとの違いとWebSocketの仕組みとハンドシェイクに譲り、ここでは選定に効く差だけを扱います。

まとめ|先に決める3項目と選定が分かれる境界

両者は「双方向」という言葉が重なっているだけで、担っている層が違います。WebSocketは接続を全二重のバイト列チャネルに切り替えるトランスポート寄りの仕組み、gRPCはHTTP/2の上に載るRPCフレームワークです。片方はパイプ、もう片方はパイプの上に敷かれた呼び出し規約だと捉えると、比較の軸がはっきりします。

設計に入る前に、次の3項目を先に決めてください。ここが決まれば選択肢はほぼ1つに絞られます。

決める項目 WebSocket寄り gRPC寄り
呼び出し元 ブラウザから直接 サーバー間・モバイル
経路の装置 Upgradeを通せる HTTP/2を通せる
インタフェース 自前で規約を書く protoから生成する
通信の形 任意のメッセージ列 メソッド単位のRPC
ペイロード テキストまたはバイナリ Protocol Buffers
向く用途 チャット・実況・共同編集 サービス間連携・内部API
詰まりやすい所 切断と再接続の設計 ブラウザ到達性と中継

境界は単純です。ブラウザのJavaScriptから双方向にやり取りするならWebSocket。サーバー同士やモバイルアプリからの内部通信で、インタフェースを複数チームで共有するならgRPC。この2つが重なる領域、つまりブラウザからgRPCを呼びたい場合だけ、後述する制約を踏まえた追加の判断が要ります。

gRPCとWebSocketの違い|双方向の実現方法が根本から別

まず、双方向をどう作っているかを見ます。ここを押さえると、後段のブラウザ制約も中継装置の話も同じ理屈から導けます。

WebSocket|HTTP/1.1のUpgradeで全二重チャネルを開く

WebSocketはRFC 6455で定義された仕組みで、最初にHTTPのリクエストを投げ、Upgrade: websocketヘッダでプロトコルの切り替えを申し込みます。サーバーが承諾すると101が返り、以降そのTCP接続はHTTPを話すのをやめ、WebSocketのフレームを流す全二重のチャネルになります。

切り替わった後に流れるのはテキストかバイナリのフレームだけで、中身の意味は仕様が定めていません。何をどんな形で送るかは、つくる側が決める領域です。仕様に含まれているのは、フレームの分割、close時のコード、そして死活確認のping/pongといった土台の部分にとどまります。

HTTP/2やHTTP/3の上でWebSocketを張る方法も、RFC 8441とRFC 9220で拡張CONNECTとして定義済みです。ただしブラウザとサーバー実装で対応状況に差があり(2026年9月時点)、実務では今もHTTP/1.1でのUpgradeを前提に組むほうが安全に倒れます。

gRPC|HTTP/2のストリーム上でRPCとして双方向を実現する

gRPCはプロトコルを切り替えません。HTTP/2をそのまま使い、1回のRPCをHTTP/2の1本のストリームに対応させます。HTTP/2は1つの接続に多数のストリームを多重化でき、各ストリームは双方向に流れるため、その性質をそのままRPCの双方向性として利用しているわけです。

そのため、gRPCの通信は常に「メソッドの呼び出し」という枠を持ちます。任意のタイミングで任意のメッセージを投げつけるのではなく、定義されたメソッドを呼び、その中でメッセージを流す。方式はunary・サーバーストリーミング・クライアントストリーミング・双方向ストリーミングの4種類で、どれになるかはprotoのstreamキーワードの置き位置で決まります。

この構造の副産物として、gRPCはHTTP/2のフロー制御をそのまま受け継ぎます。受信側の処理が追いつかないと送信側の書き込み呼び出しが戻らずに待つ、という挙動が標準で備わっている点は、WebSocketとの大きな差です。WebSocketにはメッセージ単位の背圧の仕組みが仕様として無く、送りすぎたときの詰まりは実装側で面倒を見ることになります。

通信層が異なるため「どちらが速いか」は利用条件だけでは決まらない

比較記事でよく見る「gRPCのほうが速い」という表現は、Protocol Buffersのバイナリ符号化とHTTP/2のヘッダ圧縮を前提にした話で、条件次第で逆転します。WebSocketもバイナリフレームでMessagePackやProtocol Buffersを流せますし、その場合のフレームヘッダはgRPCのフレーミングより小さくなる場面があるためです。

実効速度が効くのは、1件あたり数百バイト以下のメッセージを毎秒数千件流すような領域です。多くの業務システムはそこまで届かず、選定を左右するのは速度ではなく、次章以降の到達性・通過性・保守性の3つに寄ります。

型定義の有無を比較|契約を置く場所が長期の保守コストを左右する

2つ目の軸は、インタフェースを機械可読な形で持つかどうかです。ここは開発の初速ではなく、2年目以降の改修コストに効いてきます。

protoによる契約とコード生成|定義ファイルが単一の情報源になる理由

gRPCでは.protoファイルにサービスとメッセージを定義し、そこからサーバーとクライアント双方のコードを生成します。フィールドの追加や型の変更は定義ファイルの差分として現れ、生成し直せば呼び出し側のコンパイルが通らなくなる。破壊的変更が実行時ではなくビルド時に露見する、というのが最大の利点です。

service PriceFeed {
  // stream を両側に置くと双方向ストリーミングになる
  rpc Subscribe(stream SubscribeRequest) returns (stream Tick);
}

message Tick {
  string symbol = 1;
  int64  price  = 2;
  int64  ts_ms  = 3;
}

フィールド番号を持つ設計のため、番号を再利用しない限り、旧クライアントは知らないフィールドを読み飛ばして動き続けます。互換性の維持ルールが仕様として決まっている点は、複数チームや外部ベンダーが同じインタフェースを触る現場で効きます。

WebSocketのペイロード規約は自前|サブプロトコルの決め方

WebSocketには、これに相当する仕組みがありません。ハンドシェイク時にSec-WebSocket-Protocolでサブプロトコル名を交換できますが、名前の合意ができるだけで、中身の構造は定義されない。実務では自前でメッセージ規約を決めることになります。

最低限、次の3点は接続を開く前に決めておいてください。決めずに始めた実装は、機能追加のたびにif (msg.type === ...)の分岐が伸び、どの型がどのフィールドを持つのか誰も言えない状態になります。

  • メッセージ種別を示すフィールド名と、その値の一覧をどこで管理するか
  • スキーマの記述形式(JSON SchemaやProtocol Buffersなど)と、生成物を配る手段
  • 互換性のないメッセージを受け取ったときの扱い(無視するか、closeするか)

型を持たない方式を選ぶときに確認する組織数と仕様変更頻度の条件

とはいえ、型定義が常に得というわけではありません。メッセージの種類が数個で、送る相手が自社のフロントエンドだけで、仕様変更のたびに双方を同時にデプロイできるなら、protoを導入する手間のほうが上回ります。判断の線は「インタフェースを共有する組織の数」です。2つ以上のチームやベンダーがまたぐなら、機械可読な契約を持つ側に倒してください。

ブラウザからの到達性を比較|通信方式の選定を大きく分ける実装上の制約

3つ目の軸が、実務では決定打になります。呼び出し元がブラウザなら、gRPCはそのままでは使えません。

ブラウザから素のgRPCを呼べない理由|中継プロキシが必要になる構成

gRPCはHTTP/2のフレームを直接扱う必要がありますが、ブラウザのfetchやXHRはそのレイヤーを触らせません。そこでgRPC-Webという別の仕様が用意され、ブラウザ側はHTTP/1.1でも運べる形式で送り、経路上のプロキシがそれをgRPCへ変換してバックエンドへ渡します。既定の構成はEnvoyで、ほかにGoで書かれたプロキシやApache APISIX、Nginxのモジュールが選べます(2026年9月時点)。詳細な構成手順はgRPC-Webの仕組みとプロキシ構成で扱っています。

つまりブラウザ向けにgRPCを選ぶと、アプリケーションのほかに中継の運用が1つ増える。ここを許容できるかどうかが、最初の関門になります。

gRPC-Webで利用できる通信方式の範囲|双方向は現在も対象外

さらに踏み込むと、プロキシを立てても双方向にはなりません。gRPC-Webの公式リポジトリは、対応するのがunaryとサーバーストリーミングのみで、クライアント側ストリーミングと双方向ストリーミングは現時点で未対応だと明記しています。加えて、サーバーストリーミングが使えるのはgrpcwebtextモードのときだけという条件も付きます。

この事実の意味は小さくありません。ブラウザからサーバーへ継続的にメッセージを押し上げたい要件、たとえば共同編集の操作列やゲームの入力送信は、gRPC-Webでは素直に書けない。unaryを連打する形に崩すことになり、それならWebSocketで1本つないだほうが実装も遅延も有利です。

WebSocketはブラウザ標準API|追加部品なしで双方向通信が通る理由

一方のWebSocketは、ブラウザにWebSocketオブジェクトが標準で載っています。ライブラリもプロキシも足さずに双方向のチャネルが張れるうえ、フォールバックの検討も要りません。

const ws = new WebSocket("wss://example.com/feed");
ws.binaryType = "arraybuffer";
ws.onmessage = (e) => render(decode(e.data));
ws.onclose = (e) => scheduleReconnect(e.code);
// ブラウザのAPIからはpingフレームを送れない

ひとつ注意したいのが最後の行です。ping/pongはRFC 6455の仕様に含まれますが、ブラウザのJavaScript APIからはpingを送れません。死活監視の起点はサーバー側に置くか、アプリケーション層で独自のハートビートメッセージを流す形になります。この非対称は、切断検知の設計に直接効いてくる箇所です。

プロキシとロードバランサの通過性を比較|経路上の装置が通信の実質的な上限

ここが競合記事の空白地帯であり、本番で最も事故が起きる領域でもあります。どちらの方式も、経路にある装置が対応していなければ話が終わります。

WebSocketを通す条件|Upgradeの透過とアイドルタイムアウト

WebSocketが通るには、経路上のすべての装置がUpgradeとConnectionヘッダを落とさず後段へ渡す必要があります。リバースプロキシで明示的な設定を書き忘れると、ハンドシェイクが101にならず通常のHTTPレスポンスが返ってきて終わり、というのが典型的な失敗です。

通った後に待っているのがアイドルタイムアウトです。ロードバランサやNATは、一定時間データが流れない接続を黙って切ります。クラウドのL7ロードバランサでは既定が数十秒から数分の範囲にあることが多く、無通信のまま放置すればその時間で切断される。対策は装置のタイムアウトより短い間隔でハートビートを流すことで、値を確認せずに組むと「本番だけ数分おきに切れる」という再現しにくい症状になります。

gRPCを経路で通す条件|HTTP/2をどの区間まで維持できるか確認する

gRPCの場合、経路の装置がHTTP/2を終端して後段へHTTP/1.1で渡す構成だと通りません。プロトコルの前提が崩れるためです。クラウドのL7ロードバランサでgRPCを扱うときは、ターゲット側のプロトコルバージョンをHTTP/2かgRPCとして指定する設定が必要になり、多くのサービスでTLSの利用が条件に含まれます(2026年9月時点、詳細は各サービスの現行ドキュメントで確認してください)。

L4のロードバランサを使えばプロトコルの制約からは解放されますが、今度はTLSの終端やパスベースのルーティングを自前で持つことになる。どちらを選ぶかは、gRPC以外のトラフィックを同じ経路に載せるかどうかで決まります。

長寿命接続に共通する運用課題|負荷の偏りと再起動時の接続集中

方式にかかわらず、接続を張りっぱなしにする通信には共通の運用課題があります。1つは分散の偏りです。接続単位で振り分ける構成では、一度確立した接続は同じサーバーに留まり続けるため、スケールアウトしても既存の接続は移りません。新しいインスタンスを足しても負荷が下がらない、という現象はここから来ます。

もう1つがデプロイです。サーバーを入れ替えるたびに全接続が切れるため、再接続の集中(雪崩)が起きます。クライアント側に指数バックオフとジッタを入れ、サーバー側は接続の最大寿命を設けて計画的に切り直す。この2つを最初から入れておくと、後から慌てずに済みます。

実装方法を比較|サーバーから継続的に押し出す処理を両方式で書き比べる

同じ「サーバー発の継続配信」を、それぞれの流儀で書くとどう変わるかを見ます。

gRPCのサーバーストリーミング実装|メソッド内でデータを送り続ける

gRPC側は、protoでreturns (stream Tick)と書いたメソッドの実装内でループを回し、Sendを呼び続ける形になります。呼び出しの終わりはメソッドからの戻りで、そこでストリームが閉じます。

func (s *server) Watch(req *pb.WatchRequest, stream pb.Feed_WatchServer) error {
    for tick := range s.ticks(req.Symbol) {
        // 受信側が詰まると Send は戻らずに待つ(フロー制御)
        if err := stream.Send(tick); err != nil {
            return err
        }
        select {
        case <-stream.Context().Done(): // 切断・キャンセル・デッドライン
            return stream.Context().Err()
        default:
        }
    }
    return nil
}

受信メッセージ長の既定が4MB(4×1024×1024バイト)である点は覚えておいてください。大きな成果物を1メッセージで返す設計にすると、この上限に当たります。方式ごとの選び分けや切断時の後始末はgRPCストリーミングの4方式と切断対策で詳しく扱っています。

WebSocketのサーバー実装|接続を保持しながらデータを送る処理

WebSocket側は、確立した接続オブジェクトを保持し、送りたいタイミングで書き込みます。呼び出しという枠が無いぶん自由ですが、その自由さの代償として、接続の管理と規約の実装が自分の仕事になります。

wss.on("connection", (ws, req) => {
  const timer = setInterval(() => ws.ping(), 25_000); // LBのタイムアウトより短く
  const off = feed.subscribe((tick) => {
    // bufferedAmount を見て詰まりを検知する(背圧は自前)
    if (ws.bufferedAmount > 1_000_000) return;
    ws.send(encode(tick));
  });
  ws.on("close", () => { clearInterval(timer); off(); });
});

gRPCが標準で持っていたものが、ここでは手作業になっているのが分かります。フロー制御はbufferedAmountの監視で代替し、死活監視はタイマーでpingを送り、切断時の後始末はcloseハンドラに書く。どれも難しくはありませんが、書き漏らすと本番でメモリが伸び続けるといった形で表面化します。

再接続と通信再開の設計|切断後に復元する状態とデータ範囲を決める

どちらを選んでも、長時間つなぐなら再開の設計は避けられません。決めるべきは、再接続した後に「取りこぼした分をどう埋めるか」です。

  • 最後に受け取った位置を示すトークンやシーケンス番号をクライアントが保持する
  • 再接続時にそのトークンを送り、サーバーは続きから配信する
  • サーバー側が保持できる履歴の長さを決め、超えた場合は全体を取り直す経路を用意する
  • 重複配信を前提に、クライアント側は同じ番号のメッセージを冪等に扱う

この4点は方式を問わず同じ形になります。逆に言えば、再開設計の難しさは選定理由になりません。

使い分けの判断基準|通信相手と経路条件から採用方式を明確に決める

ここまでの軸を、実際の選定手順に落とします。迷ったときは上から順に当てはめてください。

WebSocketを選ぶべき3条件|ブラウザと双方向通信を優先する場合

次の3つがそろうならWebSocketです。チャット、実況・配信の視聴画面、共同編集、ダッシュボードの操作連動といった用途はここに入ります。

  • 通信の片側がブラウザで、クライアントからも継続的に送る必要がある
  • メッセージの種類が限られ、インタフェースを共有する相手が自社内に収まる
  • 経路の装置でUpgradeを通す設定が入れられる(または自社で管理している)

gRPCを選ぶべき3条件|型契約とサーバー間通信を優先する場合

反対に、次がそろうならgRPCに倒します。マイクロサービス間の内部通信、モバイルアプリとバックエンドの通信、社内基盤のAPIが該当します。

  • 呼び出し元がサーバーかネイティブアプリで、ブラウザから直接叩く要件が無い
  • インタフェースを複数チームや外部ベンダーと共有し、破壊的変更を検知したい
  • 経路でHTTP/2をエンドツーエンドに保てる(またはL4で通す構成にできる)

どちらも選ばない場面|要件に応じて検討する3つの代替通信方式

要件によっては、両方が過剰または不足です。サーバーからの一方向配信で足りるなら、Server-Sent Eventsのほうが実装も再接続も軽く済みます。この判断軸はSSEとWebSocketの違いと使い分けにまとめてあります。多対多の配信やIoT機器のように、送信元と受信先が動的に増減するならPub/Sub型のMQTTが向く。ブラウザから双方向かつ低遅延で、パケットロスに強い経路が欲しい場合はHTTP/3上のWebTransportが候補に入ります。

受託開発での取り決め|契約前に合意しておく双方向通信の3項目

外部に開発を委託する、あるいは受ける場合、双方向通信は見積もりのぶれが大きい領域です。理由は、切断が「誰の責任か」を決めないまま進むと、テストの合格条件が書けないからです。契約前に次の3項目を文書にしてください。

  • 切断時の責務の境界:再接続はクライアント側の責任か、サーバー側が状態を保持するか
  • 取りこぼしの許容範囲:欠落を許すのか、再開トークンで完全復元まで求めるのか
  • インタフェース変更の手順:定義ファイルの管理場所と、破壊的変更を入れるときの通知経路

この3点が曖昧なまま実装が進むと、結合テストの段階で仕様の解釈違いが表面化します。通信方式の選定からインタフェース設計まで含めて相談したい場合は、API開発・システム連携で扱っています。

よくある質問

gRPCのほうがWebSocketより速いというのは本当ですか?

条件付きです。Protocol Buffersのバイナリ符号化とHTTP/2のヘッダ圧縮が効くため、小さなメッセージを大量に往復させる用途ではgRPCが有利に出ます。ただしWebSocketもバイナリフレームで同じ符号化を使えるうえ、確立後のフレームヘッダは小さい。実測せずに速度だけで決めるのは避けてください。多くの業務システムでは、速度差より到達性と保守性のほうが選定に効きます。

ブラウザから双方向ストリーミングを使う方法はありますか?

gRPC-Webの範囲では現時点でできません。unaryとサーバーストリーミングのみが対応で、クライアント側と双方向は未対応と公式に明記されています。ブラウザから継続的に押し上げる要件があるなら、WebSocketを使うか、HTTP/3上のWebTransportを検討する形になります。上り方向がまれなイベント送信で足りるなら、下りをサーバーストリーミング、上りを個別のunary呼び出しに分ける構成も現実的です。

WebSocketの上にgRPCを載せることはできますか?

技術的には可能で、そうしたブリッジ実装も存在します。ただし、gRPCが前提とするHTTP/2の機能をWebSocketフレーム上で再現する形になるため、部品が1つ増え、トラブル時の切り分けも難しくなる。既存資産としてprotoの定義が大量にあり、それをブラウザから使い回したいという明確な理由が無い限り、素直にどちらか一方へ倒すほうが運用は楽です。

既存のWebSocket実装をgRPCへ移行すべきですか?

動いているなら、移行の理由は速度ではなくインタフェース管理に置いてください。移行が正当化されるのは、メッセージ種別が数十に増えて誰も全体像を把握できない、あるいは外部ベンダーとの結合で仕様の食い違いが頻発している場合です。逆に、ブラウザが主要クライアントで、メッセージ規約が安定しているなら、移行コストに見合いません。

社内のサービス間通信でWebSocketを使ってはいけませんか?

禁止する理由はありません。ただしサービス間ではブラウザ制約が無く、gRPCの利点である契約とコード生成がそのまま効くため、あえてWebSocketを選ぶ動機が薄くなります。既存のメッセージ基盤がWebSocketで統一されている、あるいは中継装置がHTTP/2を通せないといった事情があるなら、そのまま使い続ける判断で構いません。

関連記事

お気に入りに入れた記事の一覧

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.15 テックブログ リゾートトラスト不正アクセス:会員2.6万件・カハラ横浜3.6万件の対象確認と窓口
  2. 2026.10.16 テックブログ バーガーキング不正アクセスで約1,118万件の情報漏洩|対象確認・案内メールの真偽と運営側のログ点検
  3. 2026.10.16 テックブログ ソースネクスト不正アクセスで最大2,252万件流出|ログインできない理由・パスワード再設定と会員APIの点検
  4. 2026.10.15 テックブログ 銀のさら不正アクセス:最大650万件の対象確認と窓口、パスワード変更の手順
  5. 2026.10.15 テックブログ アエナ不正アクセス:最大81.7万人の対象確認と窓口、退会と不審メールの見分け方

RELATED POSTS 関連記事

目次