はじめに
APIと一口に言っても、その通信スタイルは一つではない。
リクエストに応答する同期的なものから、サーバーから一方的に通知するもの、複数のシステムが非同期にメッセージを交換するものまで、目的に応じた選択肢がある。
本記事では、代表的な6つのAPIスタイルを横断的に比較する。
- REST
- GraphQL
- gRPC
- Webhook
- WebSocket
- メッセージング(メッセージ交換)
それぞれの概要・設計観点・pros/consを整理し、最後に使い分けの指針を示す。個別の深掘りは、関連記事へのリンクをたどってほしい。
分類軸
比較の前に、APIスタイルを整理する分類軸を示す。
- 通信モデル: リクエスト/レスポンス、またはイベント・ストリーミング
- 駆動方向: クライアント主導(pull)、またはサーバー主導(push)
- 同期性: 同期、または非同期
- 接続数: 1対1、または1対多
この軸で6スタイルを俯瞰すると、次のように整理できる。
| スタイル | 通信モデル | 主な方向 | 同期性 |
|---|---|---|---|
| REST | リクエスト/レスポンス | クライアント主導 | 同期 |
| GraphQL | リクエスト/レスポンス | クライアント主導 | 同期 |
| gRPC | リクエスト/レスポンス(+ストリーム) | クライアント主導 | 同期 |
| Webhook | イベント通知 | サーバー主導 | 非同期 |
| WebSocket | 双方向ストリーム | 双方向 | 非同期 |
| メッセージング | メッセージ交換 | 仲介経由 | 非同期 |
REST
HTTPのメソッド(GET/POST/PUT/DELETE)とURLでリソースを操作する、最も普及したスタイルである。
設計観点
リソースを中心に設計し、ステートレスな通信を基本とする。HTTPのキャッシュやステータスコードをそのまま活かせる。
pros / cons
- 利点: 普及度が高くツールやノウハウが豊富。HTTPの仕組みに乗れる。学習コストが低い
- 欠点: 関連するリソースの取得でリクエストが增えがち(オーバーフェッチやアンダーフェッチ)。スキーマが標準化されていない(OpenAPIで補う)
深掘りはWeb APIの設計を参照してほしい。
GraphQL
クライアントが必要なデータの形をクエリで指定し、1回のリクエストで過不足なく取得するスタイルである。
設計観点
スキーマを型で定義し、1つのエンドポイントに集約する。オーバーフェッチやアンダーフェッチを抑えられる。
pros / cons
- 利点: 必要なデータだけを取得できる。型付きスキーマ。フロントエンド主導で柔軟
- 欠点: キャッシュがRESTより難しい。クエリの複雑さやN+1問題への対策が要る。サーバー実装の負担
深掘りはGraphQLの採用判断を参照してほしい。
gRPC
Protocol BuffersとHTTP/2を使う、高速なRPCスタイルである。
設計観点
スキーマ(.proto)からコードを生成し、型安全に通信する。単方向だけでなく双方向ストリーミングも扱える。
pros / cons
- 利点: 高速・低オーバーヘッド。型安全。ストリーミング対応。多言語のコード生成
- 欠点: ブラウザから直接は使いにくい(gRPC-Webが要る)。人間が読めないバイナリ。エコシステムがRESTより限定的
深掘りはgRPCの採用判断を参照してほしい。
Webhook
イベントが起きたとき、サーバーが登録済みのURLへHTTPで通知するスタイルである。
設計観点
受信側がエンドポイントを用意し、送信側がイベント発生時にPOSTする。ポーリングを不要にする「逆向きのAPI」である。
pros / cons
- 利点: ポーリング不要でリアルタイム性が高い。HTTPベースで実装が容易
- 欠点: 受信側が公開エンドポイントを持つ必要がある。配信保証・リトライ・署名検証を自前で設計する必要がある。順序保証が弱い
WebSocket
1つのコネクション上で、クライアントとサーバーが双方向にメッセージを送り合うスタイルである。
設計観点
HTTPからアップグレードして常時接続を張る。チャットや通知など、低遅延の双方向通信に向く。
pros / cons
- 利点: 双方向・低遅延。常時接続でサーバープッシュが容易
- 欠点: 接続を維持するためサーバーの状態管理やスケールが難しい。再接続やハートビートの設計が要る。HTTPのキャッシュは効かない
メッセージング
送信側と受信側の間にブローカー(メッセージキューやイベントストリーム)を挟み、非同期にメッセージを交換するスタイルである。
設計観点
RabbitMQのようなキューや、Kafkaのようなログ型ストリームを仲介に使う。送信側と受信側を時間的・空間的に疎結合にする。
pros / cons
- 利点: 疎結合・非同期で、負荷の平準化や耐障害性が高い。1対多の配信やイベント駆動に向く
- 欠点: ブローカーの運用が必要。結果整合性になりやすい。デバッグや順序・重複の扱いが難しい
横断比較表
| 観点 | REST | GraphQL | gRPC | Webhook | WebSocket | メッセージング |
|---|---|---|---|---|---|---|
| 結合度 | 疎 | 疎 | やや密(スキーマ共有) | 疎 | 密(接続維持) | 最も疎 |
| スキーマ | OpenAPIで補完 | 型必須 | .proto必須 |
緩い | 緩い | 任意(CloudEvents等) |
| リアルタイム性 | 低 | 低 | 中(ストリーム) | 中 | 高 | 中(非同期) |
| 双方向 | × | × | ○(ストリーム) | △(逆方向) | ○ | △(pub/sub) |
| スケール | 容易 | 中 | 中 | 容易 | 難 | 容易(水平) |
| 代表用途 | 一般的なCRUD | 柔軟なデータ取得 | 内部マイクロサービス | 外部連携通知 | チャット・実時間 | イベント駆動・非同期処理 |
使い分けの指針
要件からスタイルを選ぶときの目安を示す。
- 公開APIや一般的なCRUD: REST(必要に応じてGraphQL)
- クライアントが取得データを細かく制御したい: GraphQL
- 内部のマイクロサービス間で高速・型安全に通信したい: gRPC
- 外部サービスにイベントを通知したい: Webhook
- 双方向・低遅延の実時間通信が必要: WebSocket
- システムを疎結合にし非同期で処理したい: メッセージング
実際には、1つのシステムで複数を組み合わせることが多い。たとえば、外部公開はREST、内部はgRPC、通知はWebhook、非同期処理はメッセージング、という具合である。
まとめ
APIスタイルは、通信モデル(リクエスト/レスポンスか、イベント・ストリームか)と同期性で整理できる。
- 同期・リクエスト/レスポンス: REST・GraphQL・gRPC
- 非同期・イベント/ストリーム: Webhook・WebSocket・メッセージング
どれが優れているかではなく、要件に合うスタイルを選び、組み合わせることが重要である。
参考
- Roy T. Fielding, "Architectural Styles and the Design of Network-based Software Architectures", 2000. https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm
- GraphQL Specification. https://spec.graphql.org/
- gRPC Documentation. https://grpc.io/docs/
- RFC 9113: HTTP/2. https://www.rfc-editor.org/rfc/rfc9113
- RFC 6455: The WebSocket Protocol. https://www.rfc-editor.org/rfc/rfc6455
- RFC 9110: HTTP Semantics. https://www.rfc-editor.org/rfc/rfc9110
- CloudEvents Specification. https://cloudevents.io/