FIG-099

gRPC と Protocol Buffers — 辞書を共有すれば、名前は送らなくていい

Web 2026.09.24 公開 読了 約12分

サーバー同士がデータをやり取りするとき、よく使われるのは JSON です。人間が読めて便利ですが、毎回「id」「name」「price」と項目名まで書いて送るので、同じ形のデータを何万回も送ると無駄がかさみます。

Protocol Buffers(Protobuf)は、送る側と受ける側が同じ辞書(スキーマ)を持っておくことで、項目名を番号1つに置き換えてしまう方式です。翻訳こんにゃくを両方が食べていれば、長い説明は要らない。図1で1項目ずつ変換して、何バイトまで縮むかを見てください。

Protocol Buffers — 項目名を送らず、番号で済ませる
item.proto(両者が持つ辞書)
message Item {
  int32 id = 1;
  string name = 2;
  int32 price = 3;
  bool in_stock = 4;
}
JSON で送ると(57 バイト)
{"id":150,"name":"メロン","price":3000,"inStock":true}
Protobuf で送ると
0896011209e383a1e383ade383b318b8172001
タグ(番号+型) 長さ 値
JSON 57B
Protobuf 0B
受け取った側の読み方
id: 150 1: 150
name: "メロン" 2: (9バイトの何か) e3 83 a1 …
price: 3000 3: 3000
in_stock: true 4: 1
図1 — 57バイトが19バイトに。縮んだぶんの正体は、送らなくてよくなった項目名と区切り記号

名前の代わりに番号、文字の代わりにバイト

Protobuf の変換規則は単純です。各項目は「タグ」+「値」の組で、タグは項目の番号と型を1バイトに詰めたものです。id = 1 で整数なら 08、name = 2 で文字列なら 12。受け取った側は辞書を引いて、「1番は id だな」と名前を復元します。

数値も文字にしません。JSON では 3000 が4文字=4バイトですが、Protobuf は7ビットずつに切って詰める(varint)ので2バイト。小さい数ほど短くなります。読みやすさを捨てて、機械にとっての短さと速さを取った形式なのです。

図1の最後で「辞書を持っていない」に切り替えると、受け取った側には番号と値しか分かりません。両者が同じ .proto を持っていることが、この会話の前提です。番号を変えずに項目を足していけば、古い辞書の相手とも話し続けられます。

gRPC — 遠くの関数を、手元の関数のように呼ぶ

gRPC は、この Protobuf を使って別のサーバーにある関数を呼び出す仕組みです。.proto に「GetItem という関数は、こういう引数を受け取り、こういう答えを返す」と書いておくと、各言語用の呼び出しコード(スタブ)が自動で生成されます。

呼ぶ側は URL を組み立てたり JSON を解析したりせず、ふつうの関数のように呼ぶだけ。変換と通信はスタブが引き受けます。図2の「呼び出す」を押して、1回の呼び出しがどこを通るかを追ってください。

gRPC — 関数呼び出しの裏で、変換と通信をスタブが代行する
クライアントのコード
client.GetItem({ id: 150 })
スタブが変換
Protobuf のバイト列へ
HTTP/2 で運ぶ
1本の接続で並行に
サーバーのスタブ
バイト列から元の型へ
サーバーの関数
GetItem(req) を実行
クライアント側 サーバー側
READY
書くのは、関数を呼ぶ1行だけ
アプリのコードが書くのは client.GetItem({ id: 150 }) だけです。「呼び出す」を押すと、その1行の裏で何が起きるかを順に光らせます。
図2 — 真ん中の3つはスタブとHTTP/2の仕事。アプリのコードからは見えない

通信には HTTP/2 を使うので、1本の接続で何本もの呼び出しを並行して流せます。データが軽く、接続を使い回せるぶん、サーバー同士が大量にやり取りするマイクロサービスで特に好まれます。逆に、ブラウザから直接呼ぶのは苦手で、人間がのぞいて確かめるのも JSON より手間です。外向きの API は JSON、内側の配管は gRPC、という使い分けがよく見られます。

用語ミニ辞書
Protocol Buffers
スキーマで項目に番号を振り、バイト列として詰めて送るデータ形式。
.proto
メッセージの形と番号、呼び出せる関数を書いた定義ファイル。両者で共有する。
シリアライズ
データを送れる形(バイト列など)に変換すること。戻すのはデシリアライズ。
varint
数値を7ビットずつに区切り、小さい数ほど短く表す書き方。
gRPC
Protobuf と HTTP/2 を使い、別のサーバーの関数を呼び出す仕組み。
スタブ
.proto から自動生成される呼び出しコード。変換と通信を代行する。

まとめ

JSON は毎回、項目名まで書いて送る手紙。Protobuf は辞書を共有しておき、番号とバイトだけ送る電報です。図1では 57 バイトが 19 バイトになりました。gRPC はその電報を HTTP/2 で運び、遠くの関数を手元の関数のように呼べるようにします。代わりに失うのは、人間がそのまま読める気軽さです。