仕組みから学ぶ Web
発展読了目安 15#GraphQL#REST#API設計#技術選定

REST と GraphQL — 何を楽にして、何を難しくするか

過不足のない取得という利点の裏で、キャッシュ・認可・負荷制御がクライアント任せから自分の責任に移る。

この記事の進み方

What — 同じ画面を作るときの違い

Compare記事詳細画面(記事 + 著者 + コメント10件)を表示する

リソースごとに URL が分かれる。過不足は出るが、HTTP の仕組みがそのまま使える。

GET /articles/123
GET /articles/123/author
GET /articles/123/comments?limit=10

→ 3往復(HTTP/2 なら並列で流せる)
→ それぞれ独立に CDN キャッシュできる
→ 使わないフィールドも返る(オーバーフェッチ)
→ 足りなければもう1回呼ぶ(アンダーフェッチ)
往復回数
リソースの数だけ
転送量
不要な分も含む
CDN キャッシュ
そのまま効く
認可の実装
エンドポイント単位
負荷の上限
設計時に決まる
  • HTTP のエコシステム(キャッシュ・監視・レート制限)がそのまま使える。
  • 画面ごとに専用エンドポイント(BFF)を作れば、往復を1回にできる。

GraphQL は取得を1往復に畳む。REST は URL ごとに分かれる。この違いが、キャッシュ・認可・負荷制御のすべてに波及する。

GraphQL が持ち込む3つの責任

FigureGraphQL サーバーが自前で用意する必要があるもの
  1. 1① N+1 対策(DataLoader)階層ごとにリゾルバが呼ばれる構造的な問題重い
  2. 2② クエリの複雑度制限深いネストや大量取得を拒否する重い
  3. 3③ フィールド単位の認可誰がどのフィールドを見てよいか重い
  4. 4④ キャッシュ戦略HTTP キャッシュが使えない分の代替
  5. 5⑤ 監視とレート制限1リクエストの重さが一定でない

これらを用意せずに公開すると、冒頭の事故(キャッシュ消失・DB 飽和)が起きる。導入コストの本体は、スキーマ定義ではなくここ。

1/5
① N+1 対策(DataLoader)記事10件それぞれの著者を解決すると、著者の取得が10回走る。DataLoader で同一階層の問い合わせを収集し、1回の IN 句にまとめる。GraphQL では実質必須。

REST なら HTTP やフレームワークが提供していた機能を、GraphQL では自分で組み立てることになる。「導入して終わり」ではない。

確認 — ここまで読めたか

GraphQL で CDN キャッシュが効きにくいのはなぜですか?

まず選ぶ(解答例は a〜d の記号で説明します)

Why — どちらが優れているかではない

GraphQL は2012年に Facebook が作りました。動機は明確で、モバイルアプリの画面ごとに必要なデータが違いすぎたことです。

  • 画面が増えるたびに専用エンドポイントを作ると、API が増え続ける
  • 汎用エンドポイントにすると、どの画面でも使わないデータまで返る
  • モバイルの回線は遅く、往復も転送量も削りたい
  • アプリのバージョンによって必要なフィールドが違う

**「クライアントが必要なものを宣言する」**という発想は、この状況への合理的な回答でした。

しかし、その柔軟性はサーバーが持っていた制御権をクライアントに渡すことで得られています。渡した分だけ、制御の責任がサーバー側に残ります。

「REST は往復が多い」への反論

REST の欠点として挙げられる往復回数は、BFF(Backend For Frontend)でかなり解消できます

GET /screens/article-detail?id=123
  → 記事 + 著者 + コメント10件を1回で返す

画面ごとに専用のエンドポイントを作る形です。往復は1回、転送量も過不足なし。GraphQL の利点の多くがここで得られます。

代償は「画面が増えるたびにエンドポイントが増える」こと。画面の種類が少なく、変更頻度も低いなら、BFF のほうが単純で安全です。

画面が数十種類あり、クライアントが複数(Web / iOS / Android / 提携先)ある場合に、GraphQL の価値が出てきます。

エラーとステータスコード

GraphQL は原則として HTTP 200 を返し、エラーは errors 配列で表現します。

HTTP 200 OK
{
  "data": { "article": null },
  "errors": [{ "message": "Not found", "path": ["article"] }]
}

これはエラー設計の章で見た「すべて 200 で返す」問題そのものです。監視・ロードバランサ・CDN が異常を検知できません。 GraphQL を採用するなら、エラー率の監視を errors 配列を見る形で作り直す必要があります。

確認 — ここまで読めたか

転送量が40%減ったのにサーバー負荷が10倍になりました。何が起きていますか?

まず選ぶ(解答例は a〜d の記号で説明します)

演習 — まず自分で判断する

解説を読む前に、まず自分で判断してみてください。ここで一度詰まっておくと、 次の節の判断軸が「なるほど」ではなく「そう来たか」に変わります。

演習 — 設計判断を問う

この2つのサービスに、それぞれどちらを選びますか?

与えられた条件
  • 【サービスA】料理レシピの閲覧サイト。月間 3000 万 PV
  • ・クライアントは Web(レスポンシブ)のみ
  • ・8割が未ログインの閲覧で、コンテンツは誰が見ても同じ
  • ・テレビ紹介時に特定ページへ数万 PV/分が集中する
  • ・画面の種類は10程度で、変更頻度も低い
  • 【サービスB】社内の統合ダッシュボード
  • ・クライアントは Web / iOS / Android / 提携先の外部システム
  • ・画面が 60 種類以上あり、毎月新しい画面が追加される
  • ・画面ごとに必要なデータの組み合わせがまったく違う
  • ・すべてログイン必須で、社内ネットワークからのみアクセス
  • ・同時利用者は最大 500 人程度
この軸で考える
  • · キャッシュが可用性にどれだけ寄与しているか
  • · クライアントの数と、画面の変更頻度
  • · 利用者を信頼できるか(負荷制御の必要性)
まず選ぶ(解答例は a〜d の記号で説明します)

演習 — 説明できるか

「GraphQL にすれば過不足なく取れて速くなる」という提案に、一緒に決めるべきことを説明してください

与えられた条件
  • 相手は転送量の削減を根拠にしている
  • 現在は CDN でレスポンスをキャッシュしている
  • 採用を否定せず、必要な準備を洗い出したい

読み終わりましたか?

読了にすると、これを前提とする記事がロードマップで開放されます。