5 ポイント 投稿者 GN⁺ 2025-12-15 | 2件のコメント | WhatsAppで共有
  • GraphQL はデータの過剰取得問題を解決しようとするが、ほとんどのエンタープライズ環境ではすでに別の方法で解決済みの問題である
  • BFF(Backend for Frontend) アーキテクチャが一般化した企業システムでは、GraphQL の主な利点は大きく薄れる
  • 実装の複雑さ、可観測性の低下、キャッシュの問題、ID 制約、ファイル処理の不便さ などにより、実運用ではコストが大きくなる
  • REST はシンプルで速く、エラー処理やオンボーディングが容易なため、大規模チーム環境でより効率的である
  • 結論として GraphQL は 特定の状況では有用だが、ほとんどのエンタープライズには過剰な選択だと評価される

GraphQL が解決しようとする問題

  • GraphQL の中核的な目的は overfetching(不要なデータの過剰取得) の防止
    • クライアントが必要なフィールドだけを要求し、不要なデータ転送を減らす構造
    • 新しい UI 要件が出るたびにバックエンドを修正する必要がないという利点
  • しかし実際の環境では、この理想的な構造は 複雑な現実と合致しない

BFF で既に解決されている overfetching

  • ほとんどのエンタープライズのフロントエンドは BFF(Backend for Frontend) レイヤーを使用している
    • UI に合わせてデータを組み合わせ、複数のダウンストリーム呼び出しを統合し、バックエンドの複雑さを隠す
  • REST ベースの BFF はすでに必要なデータだけを返せるため、GraphQL の利点が重複する
  • GraphQL レイヤーが REST API からデータを取得する場合、overfetching は単に一段下へ移動するだけ
  • 複数ページが同じエンドポイントを共有するときは GraphQL が有用な場合もあるが、
    • その利点は 数キロバイト節約するために、より多くの設定と保守負担を受け入れる程度にとどまる

実装の複雑さと生産性の低下

  • GraphQL は REST より 実装にずっと時間がかかり、複雑
    • スキーマ、型、リゾルバ、データソース定義など追加作業が必要
    • スキーマとクライアントの同期を維持する負担もある
  • GraphQL は 利用(クライアントの利便性) を最適化する一方で、生産(サーバー開発速度) を犠牲にする
  • エンタープライズ環境では 開発速度とシンプルさ のほうが重要である

可観測性とモニタリングの問題

  • GraphQL の HTTP ステータスコード体系は一貫していない
    • 200 レスポンスにもエラーが含まれうるため、モニタリング時に成功/失敗の区別が難しい
  • REST は 2XX/4XX/5XX で明確に区分され、ダッシュボードのフィルタリングが直感的
  • Apollo などでカスタマイズは可能だが、これは 追加設定と認知負荷 を招く
  • 運用中の障害対応では、REST より 問題の把握が難しく複雑になる

キャッシュの現実的な限界

  • Apollo の 正規化キャッシュ(normalized caching) は理論上は強力だが、実際には 脆く複雑
    • フィールドが 1 つ違うだけのクエリも別物として扱われ、手動での関連付けが必要
    • キャッシュのデバッグが独立した問題に発展する
  • 一方 REST はレスポンス全体を単純にキャッシュでき、安定していて保守しやすい

ID フィールド制約の問題

  • Apollo はすべてのオブジェクトに id または _id フィールド が必要だと仮定する
    • 多くのエンタープライズ API には一意 ID が存在しないか、グローバル識別子ではない
  • これに合わせるため、BFF が ローカル ID 生成ロジックを追加しなければならない
    • 結果として 不要なフィールドとロジックが増え、overfetching 削減効果を相殺する

ファイルのアップロードとダウンロードの非効率

  • GraphQL は バイナリデータ処理に不向き
    • 実際にはダウンロード URL を返し、ファイル自体は REST で転送する
    • PDF などの大容量データを GraphQL レスポンスに含めると 性能が低下する
  • その結果、GraphQL の理想である「単一 API」は崩れる

オンボーディングと学習曲線

  • ほとんどの開発者は REST の経験が豊富だが、GraphQL は学習が必要
    • スキーマ、リゾルバ、クエリ構成、キャッシュ規則、エラー処理など新しい概念を学ぶ必要がある
  • そのため チームのオンボーディング速度が低下する
  • REST は「退屈だがスケーラブルな」アプローチとして、大規模チームに適している

エラー処理の複雑さ

  • GraphQL のエラーレスポンスは nullable フィールド、partial data、errors 配列、拡張ステータスコード などで複雑
    • どのリゾルバが失敗したのか追跡する必要がある
  • REST は単純に 400/500 で区別され、理解とデバッグが容易

結論: GraphQL はニッチ技術

  • GraphQL は 特定の状況では有効なツール
    • しかし大半のエンタープライズ環境では、すでに BFF と REST で問題を解決している
    • 主要な課題は overfetching ではなく、可観測性、信頼性、速度 である
  • 結果として GraphQL は 狭い問題を解決する一方で、より広い複雑性を招く
  • 結論は「GraphQL は悪くないが、ほとんどの場合は必要ない」というもの

2件のコメント

 
colus001 2025-12-16

長所と短所はあると思いますが、スキーマレベルでデータとアクセス制御を設計して、何かを1つ追加するたびに REST API に追加し、あとで全部返すようにするよりはよく見えます。欠点は明確ですが、長所も明確なので(笑)

 
GN⁺ 2025-12-15
Hacker Newsの意見
  • GraphQLの主な問題をoverfetchingだと規定する記事には同意しない
    私が見るに本当の利点は、(a) 厳格な型ベースの契約を強制できること、(b) スキーマ進化がはるかに容易なこと
    型システムのおかげで入力と出力は常に定義された形に従い、カスタムスカラー型(例: 電話番号、メールアドレスなど)を使えばバグやセキュリティ問題を大幅に減らせる
    また、新しいフィールドの追加や既存フィールドの廃止が標準化されているため、サーバー・クライアントの両方で認知負荷が小さい

    • 私もoverfetchingが核心的な問題だとは思わない
      私がGraphQLを使う理由はAPIの組み合わせと進化にある。特にM:N構造の大規模システムでは、「クライアントが必要なものを記述 → サーバーが組み合わせる → ドメインサービスが解決する」という流れのほうが、長期的にはるかに管理しやすい
      優れたobservabilityと組み合わせれば、データアクセスの強力な基盤になる
    • OpenAPI仕様からTypeScript型を生成すれば双方向の契約が生まれるので、その点はGraphQLが解決する問題ではない
    • 私もGraphQLの強い契約性が最大の理由だと思う
      もう一つはresolverの再利用とfederationが容易なこと。RESTではこれはかなり面倒だ
    • リクエストとレスポンスをzodでpruningするのは簡単だ。その理由だけでGQLを導入しようとは思わない
      スキーマ進化はProtobufでもうまく扱える
    • GraphQLがprotobuf通信と何が違うのかわからない。どちらも定義に従ってパースされるのだから
  • GraphQLの本当の利点は、UIデータを小さな断片として組み合わせられることだ
    この動画のようにfragment colocationを活用すれば、下位コンポーネントを修正しても他の部分に影響しない
    クエリがfragmentベースで自動生成されるので、フィールド削除時に他のコンポーネントが壊れるリスクも減る
    規模が小さい、あるいは高速な開発が重要でないなら、GraphQLは過剰投資に見えるかもしれない

    • Apolloが人々を間違った方向へ導いたせいで、GraphQLの本当の利点を感じにくくしたのだと思う
      Colocationは本当に革新的な概念なのに、Apolloはこれをほとんど語らなかった
    • 問題はGraphQLではなくApollo Client
      Relayのドキュメントは依然として不十分だが、Entrypointという概念は素晴らしい
    • fragment maskingには同意する
      ただしgraphql-codegenの実装はプラグイン互換性が低く、私たちは自前でプラグインを作らなければならなかった
      エコシステム全体の一貫性が不足している
  • overfetchingがGraphQLの核心的な問題だというのは誇張だ
    GraphQLは、ORMが解決するインピーダンスミスマッチをクライアントレベルで扱うための道具だと考えている
    Relayのようなコンパイラベースのツール群なしで使うのはアンチパターンだ
    最近はAIがデータレイヤーを自動生成してくれるので、GraphQLの必要性は下がっているように見える

    • 「コンパイラなしでGraphQLを使うべきではない」という意見には共感するが、それがBFFで数行のコードを書くより簡単なのかは疑問だ
    • 優れたGraphQLツーリングの例として、Isograph VSCode拡張を勧めたい
      存在しないフィールドを選択すると自動生成してくれるなど、開発体験(DevEx) が優れている
    • URQLgql.tadaは素晴らしいクライアントサイドツーリングだ
    • GraphQLツーリングに何を使っているのか気になる。IntelliJPostmanもサポートが良い
    • overfetchingが大した問題ではないという意見には同意できない
      現代のWebが遅くなっている主因はほとんどがデータの過剰転送だ。実際、多くのアプリは0.5%未満の効率で動いている
  • 私は2016年からGraphQLを使ってきた
    本質的にGraphQLはRPC仕様だ。サーバーの「Action(Args) → ResultType」マップとして実装される形になる
    RESTの複数エンドポイントの代わりに、GraphQLは単一の/queryエンドポイントでresolverマップを通じて動作する
    結局はOpenAPIやgRPCのように入出力が型で定義された構造だ

    • 2015年からGraphQLを使ってきたが、RelayなしでGraphQLを使うなら本当の強みを感じられない可能性が高い
      Apolloがfragment maskingを追加して多少は良くなったが、それでもRelay中心の考え方が重要だ
    • この説明は単純化しすぎだ。クエリ解釈プロセスを完全に省略している
    • クライアントが要求フィールドを指定できる点が抜けている
    • 元記事との関連性が薄く見える
    • GraphQLは、Reactページ全体が下位コンポーネントの要件を集めて1つの巨大なクエリを作り、
      バックエンドがこれを単一のSQLクエリに変換して処理する時に最も効率的だ
      resolverはDBから直接取得できないデータに対してのみ例外的に使うべきだ
  • 以前チームを率いていた時、FEがGraphQLを望んだので導入した
    結果として各ページごとに1つの巨大なクエリで全データを取得し、修正時にはJSON blob全体を送り返していた
    アプリは動いていたが、結局会社がピボットしたことでそのコードは消えた
    実際、多くのGraphQLプロジェクトはこうした形式だけ整った実装で終わるように思う

  • GraphQLの認証(auth)フローは最大の難題の一つだ
    resolverがさまざまなコンテキストで呼ばれるため、あらゆるケースを考慮しなければならない
    複雑さと認知コストが大きすぎて、結局フィールドをロックすることになる
    自分でgraphql-autharooを作ったが十分ではなかった
    たいていの機能はGraphQLなしでももっとシンプルに実装できる

    • GitHubでも権限管理(authz) が大きな問題だ
      GraphQLリソースごとに細かな権限を追加しなければならず、リソース全体が更新されるまでクエリが動作しない
      RESTで作り直したほうがよい」という声が出るほど負担が大きい
    • デコレータベースの認証を使ったことがあるか聞きたい
      自前で組み合わせるより、完成度の高いサーバーフレームワークを使うほうがよいと思う
  • GraphQLは見た目は良さそうだが、実際には時間が経つほど保守が難しくなる技術
    多くの技術がそうであるように、結局車輪はただの車輪にすぎないという教訓を与えてくれる

  • GraphQLの利点は、スキーマにフィールドを追加するだけで全クライアントがすぐにクエリできることだ
    「このフィールドも追加してほしい」というFEからの要望がなくなり、協業がシンプルになる
    また、スキーマスナップショットを作って統合テストで変更検知するのも容易だ
    RESTより一貫性が高いと感じたが、これは個人的な経験だ

    • ただしその利点は諸刃の剣でもある
      AからEまで連鎖的に要求できるので、性能低下やフロントエンドとデータ構造の結合が深刻になる
    • 最近はたいていフルスタックTypeScript環境なので、こうした協業上の問題は減っている
      Reactも今ではフレームワークベースのSSRとサーバーコンポーネントが前提になっている
      結局、TypeScriptがクライアントとサーバーを統合する方向に進んでいる
  • GraphQLがDB負荷や非効率なクエリの問題をどう防ぐのか気になる
    悪意あるクエリが内部状態を爆発させることもあるのではないか?

    • ほとんどのサーバーはクエリ複雑度(コスト)制限を設けており、基準を超えればリクエストを拒否する
  • RESTがあまりに退屈なのでGraphQLを試している
    サーバーとクライアントがリクエスト・レスポンスについてコンパイル時に合意できる点が気に入っている
    ブログには「これはよくない」と言うだけでなく、代替技術も一緒に示してほしい

    • もしisomorphic TypeScriptが好きなら、tRPCがGraphQLよりもすっきりした代替案だ
      どちらの技術もクライアント・サーバー契約の問題をうまく解決する