GraphQL と REST の本当の違い
GraphQL と REST の比較
GraphQL と REST:同じデータを両方の方法で取得 | We.Inc
同じデータを両方の方法で取得して GraphQL と REST を比較します。リクエスト数、過剰取得、キャッシュ、エラーの返り方、そしてどちらを選ぶかの判断表を紹介します。
RESTはリソースごとに1つ、多数のURLを公開し、各レスポンスの中身はサーバーが決めます。GraphQLは通常 /graphql という1つのエンドポイントを公開し、クライアントは欲しいフィールドを正確に指定したクエリを送ります。RESTはURLによるHTTPキャッシュを無料で得られ、GraphQLはサーバーの処理が増える代わりに往復回数を減らし、使わないフィールドを省けます。
ひと目でわかる比較
- エンドポイント
- リソースごとに1つのURL
- 1つのエンドポイント、多くは /graphql
- フィールドを選ぶのは
- サーバー
- クライアント(クエリ内で指定)
- 関連データ
- 複数のリクエストが必要なことが多い
- 1つのクエリに入れ子で記述
- HTTPキャッシュ
- URLごとのGETに標準で対応
- GETクエリ、永続化クエリ、またはクライアントキャッシュが必要
- エラー
- 主にHTTPステータスコード
- errors 配列。部分的なデータと一緒に返ることも多い
下の比較では、同じ画面分のデータを両方の方法で取得します。シナリオを選ぶと、クライアントが行うRESTの呼び出しと、それを置き換える1つのGraphQLクエリが並んで表示され、それぞれのレスポンスで何が省かれ、何が加わるかがわかります。
- 最近の投稿付きのプロフィールページなど、シナリオを選びます。
- 左側のRESTリクエストと右側のGraphQLクエリを読みます。
- ペインの下に表示されるリクエスト数を比べます。
- メモを読んで、それぞれの方式が画面に必要な量より多くのデータを送る箇所を確認します。
- 流行だけを理由に、正常に動いているREST APIをGraphQLに切り替えないでください。効果が出るのは、多くの異なる画面がそれぞれ関連データの異なる部分を必要とするときです。
- すべてのGraphQLの型に安定した id フィールドを公開しましょう。クライアントライブラリがそれをもとにキャッシュを正規化できます。
- ステータスが 200 でデータが含まれていても、すべてのGraphQLレスポンスで errors 配列を確認しましょう。
- 1つの入れ子クエリで膨大な処理を要求できてしまうため、公開GraphQLエンドポイントには深さとコストの制限を設けましょう。
よくある質問
GraphQL は REST より速いですか?
それ自体では速くなりません。関連データが必要な画面では往復回数とペイロードのサイズを減らせますが、各クエリの解決にはサーバー側でより多くのコストがかかることがあります。1つの画面向けにうまく設計されたRESTエンドポイントも同じくらい速くなりえます。
GraphQL のエラーがステータス 200 で返るのはなぜですか?
あるフィールドが失敗しても他は成功することがあるため、サーバーは取得できたデータと errors 配列を一緒に返します。GraphQL over HTTP の指針では部分的な成功に 2xx を使い、application/graphql-response+json で応答するサーバーはリクエストが検証に失敗すると 400 を使います。
GraphQL のレスポンスは CDN でキャッシュできますか?
はい。クエリをGETで送れば可能で、サーバーはクエリに限りGETを許可できます。長いクエリはURLの長さ制限を超えることがあるため、ドキュメント全体の代わりに短いハッシュを送る永続化クエリが使われます。
1つのプロダクトで両方を使えますか?
多くのチームがそうしています。ファイルアップロード、Webhook、単純な公開リソースはRESTのルートのままにし、アプリの画面はGraphQLの層を通して読み取ります。その層の裏で同じサービスを呼び出すこともあります。
GraphQL には専用のデータベースが必要ですか?
いいえ。GraphQLサーバーはリゾルバーの層です。リゾルバーは、データベース、RESTサービス、ファイルなど、データがある場所から各フィールドを取得する小さな関数です。スキーマが記述するのは形であって、保存方法ではありません。
過剰取得と過少取得
- RESTのエンドポイントは決まった形を返します。名前だけを表示する一覧画面でも全ユーザーの全フィールドをダウンロードすることになり、これが過剰取得(オーバーフェッチ)です。ユーザー、その投稿、各投稿のコメント数が必要な詳細画面では何度も呼び出しが必要になることがあり、これが過少取得(アンダーフェッチ)です。
- GraphQLはこの選択をクライアントに移します。クエリがフィールドを列挙し、サーバーはその形だけを返します。その代わり、クライアントが要求しうるあらゆるフィールドの組み合わせにサーバーが対応しなければなりません。
キャッシュの仕組みが異なる
- RESTではURLがキャッシュキーになります。GETとHEADはキャッシュ可能なメソッドなので、ブラウザーやCDNはGETのレスポンスを保存して再利用できます。GraphQLの通信の大半は1つのURLへのPOSTで、そうしたキャッシュには保存されません。
- GraphQLのクライアントはアプリ内でこれを補います。レスポンスをオブジェクトに分割して id ごとに保存するので、同じユーザーに触れる2つのクエリが1つのキャッシュレコードを共有します。graphql.org がグローバルに一意な id フィールドを推奨しているのは、まさにこのためです。
エラーとステータスコード
- RESTはステータス行に頼ります。レコードがなければ 404、サインインしていなければ 401、入力が不正なら 422 です。クライアントはコードだけで処理を分岐できます。
- GraphQLのレスポンスには data キー、errors キー、またはその両方があります。構文や検証の問題では errors だけが返り、data はありません。1つのフィールド内での失敗では、そのフィールドが null の部分的なデータと、path でそのフィールドを指すエラー項目が返ります。
どちらを選ぶべきか
判断表
- 多くの画面がそれぞれ異なる関連データを必要とする
- GraphQL
- 読み取りトラフィックをCDNで積極的にキャッシュしたい
- REST、または永続化GETクエリを使うGraphQL
- 低速なネットワーク上のモバイルクライアント
- GraphQL(往復回数が少ない)
- 1つの入り口の背後に複数のバックエンドサービス
- ゲートウェイ層としてのGraphQL
実際に送受信される内容
fetch を使ったGraphQLリクエスト
すべての操作は、query と variables のキーを持つJSONを1つのエンドポイントへPOSTするものです。Accept ヘッダーで新しいGraphQLレスポンス形式を要求し、プレーンなJSONを予備にしています。
部分的なGraphQLレスポンス
1つのフィールドが失敗したので null になり、errors の項目が path でそのフィールドを示しています。残りのデータは届いています。
投稿付きのプロフィール
RESTでは投稿のために2回目の呼び出しが必要で、どちらのレスポンスにもサーバーが含めるすべてのフィールドが入ります。GraphQLのクエリは、名前、アバター、3件の投稿タイトルだけを返します。
名前のみ
単純な一覧ではどちらもリクエストは1回ですが、RESTはユーザーのレコード全体を送ります。GraphQLは要求された2つのフィールドだけを送ります。
コメントと投稿者付きの投稿
専用のエンドポイントがなければ、RESTはツリーを1リクエストにつき1階層ずつたどり、各コメントの投稿者を取得するにはコメントごとにもう1回の呼び出しが必要になることもあります。GraphQLはツリー全体を1つのクエリに入れ子で記述します。
投稿を作成
書き込みは似ていて、どちらも1回のリクエストです。RESTはコレクションのURLにPOSTメソッドを使い、GraphQLはミューテーションを送ります。これもHTTPのPOSTで、新しい投稿のどのフィールドを返すかを選べます。
同じデータを両方の方法で
シナリオを選択
RESTリクエスト
GraphQLクエリ
RESTリクエストをコピー
GraphQLクエリをコピー
REST:{n} 回のリクエスト。GraphQL:{v} 回のリクエスト。
無料で始める · クレジットカード不要
関連: ガイド|Webマーケティングと集客を学ぶ
製品
ご利用いただける方
機能
リソース
会社情報
サイトマップを見る