GraphQL vs REST API - 設計思想と選択基準

10分 で読める | 2025.12.02

公式ドキュメント

GraphQLとRESTは、単純な機能一覧だけでは比較できません。 大切なのは、画面や利用者によって必要なデータがどれほど変わるか、HTTPキャッシュをどこまで使いたいか、運用チームが複雑なクエリを管理できるかです。

この記事では実装方法ではなく、選択基準に集中します。

最初に用語を分ける

RESTはアーキテクチャスタイル

RESTは、Roy Fielding氏が示した次のような制約から成るアーキテクチャスタイルです。

  • クライアントとサーバーを分離する
  • リクエストをステートレスにする
  • 応答がキャッシュ可能か示す
  • 統一されたインターフェースを使う
  • 階層化されたシステムを許容する
  • 必要に応じてコードを配布する(任意)

実務で「REST API」と呼ばれるものには、リソースをURLで表し、HTTPメソッドとJSONを使うAPIも広く含まれます。 ただし、その呼び名だけでRESTの制約をすべて満たすとは限りません。

この記事では混同を避けるため、一般的なものを「リソース指向のHTTP API」と呼びます。

GraphQLは型付きの問い合わせ方式

GraphQLは、型付きスキーマに対してクライアントが必要なフィールドを指定する問い合わせ言語と実行方式です。 HTTPでは1つのエンドポイントを使う構成が一般的ですが、エンドポイント数だけが本質ではありません。

query Profile($id: ID!) {
  user(id: $id) {
    name
    avatarUrl
  }
}

クライアントはスキーマで許可された範囲から、今回必要なデータの形を宣言します。

同じ画面でも取得形状が違う

同じProfile画面のdataをRESTではresource endpointから取得し、GraphQLではtyped schemaへ必要fieldをqueryする取得shapeの比較図

プロフィール画面にユーザー、投稿、フォロワー数を表示するとします。

リソース指向のHTTP APIでは、次のどれも設計可能です。

  • /users/123など複数のリソースを取得する
  • 画面向けの集約エンドポイントを用意する
  • fieldsincludeで返す範囲を指定できるようにする

GraphQLでは、クライアントが1つのクエリで関連フィールドを選べます。

したがって「HTTP APIは必ず複数リクエスト」「GraphQLは必ず1リクエストで高速」とは限りません。 ブラウザーからサーバーへの往復が1回でも、サーバー内部で多数のDB問い合わせが発生する場合があります。

比較するときの6つの軸

観点リソース指向のHTTP APIGraphQL
応答の形サーバーがエンドポイントごとに決めるクライアントがスキーマ内から選ぶ
契約OpenAPIなどを導入できる型付きスキーマが中心になる
HTTPキャッシュGETとURLを使う設計では活用しやすいGET、persisted document、CDNなどの設計が必要
部分的な失敗HTTP statusと独自のエラー形式で表すdataerrorsが同時に返る場合がある
クエリの自由度公開した操作に限定しやすい高いが、深さや量の制御が必要
運用HTTP基盤を利用しやすいスキーマ変更、クエリ分析、resolver監視が重要

1. オーバーフェッチとアンダーフェッチ

GraphQLでは必要なフィールドを選べるため、画面ごとに必要な形が大きく異なる場合に有効です。

一方、リソース指向のHTTP APIでも、用途別エンドポイントやフィールド選択を設計できます。 GraphQLを導入しただけで転送量が必ず減るわけではなく、クライアントが大きなクエリを送れば応答も大きくなります。

2. スキーマと変更管理

GraphQLでは、型、フィールド、引数がスキーマに集約されます。 非推奨化を使い、利用状況を確認しながら段階的に移行しやすい点が強みです。

リソース指向のHTTP APIでも、OpenAPIなどで契約を定義できます。 ただし、仕様書と実装を同期する仕組みは別途必要です。

どちらでも、互換性を壊す変更を自動的に防げるわけではありません。

3. キャッシュ

安全なGETリクエストと安定したURLを使うHTTP APIは、Cache-Control、ETag、共有キャッシュを利用しやすい構成です。

GraphQLでも、GETによる問い合わせ、persisted document、CDN、クライアントの正規化キャッシュを利用できます。 ただし、任意のクエリ文字列や認可されたデータをどう識別するかまで設計する必要があります。

HTTPキャッシュの利用可否は、方式名だけでは決まりません。 キャッシュ可能性、キー、利用者ごとの分離、無効化方法を確認します。

4. エラー

HTTP APIでは、通信や認証、リソース状態をHTTP statusで表し、本文に詳細を入れる設計が一般的です。 エラー本文にはProblem Detailsなどの共通形式も選べます。

GraphQLでは、実行できたフィールドのdataと、失敗したフィールドのerrorsが同時に返る場合があります。 HTTP transportの失敗と、GraphQLの要求・実行エラーは分けて扱います。

部分データを表示するのか、画面全体を失敗にするのかは、クライアント側の方針が必要です。

5. N+1

N+1は、一覧を1回取得した後、各項目の関連データを1件ずつ追加取得する問題です。 これはGraphQL固有ではなく、HTTP APIの集約処理やORMでも起こります。

GraphQLはフィールドごとにresolverを分ける実装が多いため、N+1が生まれやすく、観測しやすい傾向があります。 対策には、次の選択肢があります。

  • DBのJOINや事前読み込み
  • 同一リクエスト内のbatching
  • DataLoaderなどによる重複排除
  • query plannerやデータソース側での集約

DataLoaderを追加すればすべて解決するわけではありません。 発行されたDBクエリ数と実行計画を計測して判断します。

6. セキュリティと負荷制御

どちらの方式でも、認証だけでなく、対象データごとの認可が必要です。 入力検証、rate limit、応答サイズ、監査ログも共通の課題です。

GraphQLでは、利用状況に応じて次も検討します。

  • クエリの深さ、alias数、一覧件数を制限する
  • query complexityや実行時間を計測する
  • persisted documentや許可済み操作を使う
  • resolverごとではなく一貫した認可層を持つ

introspectionを無効にするだけでは、認可や負荷制御の代わりになりません。 開発ツールとの兼ね合いも含めて判断します。

選択基準

GraphQLが候補になりやすい

  • Web、モバイルなど複数のクライアントで必要な形が大きく違う
  • 画面の変更が多く、クライアントが取得フィールドを調整したい
  • 複数のバックエンドを型付きスキーマの背後にまとめたい
  • スキーマ所有者と変更手順を決められる
  • クエリコストやresolverを観測する基盤を運用できる

リソース指向のHTTP APIが候補になりやすい

  • 操作と応答の形が安定している
  • 公開GET APIやCDNキャッシュを素直に活用したい
  • ファイル配信、stream、webhookなどHTTPの仕組みが中心
  • 許可する操作を少数のエンドポイントに限定したい
  • チームがHTTPの運用基盤とOpenAPIに習熟している

併用もできる

外部公開APIはリソース指向のHTTP API、画面向け集約はGraphQLという構成もあります。 ただし、認可、監視、データモデルを2方式で維持する費用が増えます。

流行ではなく、主要な画面を1つ選び、転送量、DB問い合わせ数、キャッシュ率、実装と運用の複雑さを小さく検証して決めましょう。

実装を試す

GraphQLのスキーマ、Query、Mutation、認証を手元で試す場合は、GraphQL API実装のPracticeへ進んでください。 この記事では選定と設計判断に集中し、フレームワーク固有の実装はPracticeへ分けています。

参考リソース

← 一覧に戻る
PR
PR
PR
PR