GraphQLはWeb APIを構築するためのとても強力なアプリケーション(仕様)ですが、多面的な特徴を持つためにすぐに理解しづらいところがあるのかなと思ってます。そのためこれまでにいくつか記事を書いてきました。
今回もGraphQLの解説になりますが、今回は特徴を整理し、手短に見ていきたいと思います。GraphQLの理解につながれば幸いです。
GraphQLの特徴を3つに分ける
GraphQLの特徴を分けると大きく3つに分かれると考えます。(プラスでエコシステム)
- APIインターフェスとして
- Universal BFFとして
- API Gatewayとして
- (エコシステム)
それぞれ見ていきます。
APIインターフェースとしてのGraphQL
GraphQLの最も目立つ部分で、これまでに多くの情報で言及されている部分はこのAPI インターフェースとしての部分でしょう。GraphQLの特徴的な部分ではありますが、すでに言及されていることなので今回は割愛します。
フロントエンドから見るGraphQLはこの部分の理解だけで十分な気がします。
APIインターフェースとしてのGraphQLの特徴
- グラフ理論
- Tree
- Node
- AST
- Query Language
- Query
- 読込系 - Mutation
- 書込系 - Subscription
- Websocket
- Query
- Schema
- Scalar, Type, List, Enum, Union, Interface, Fragment, Input, Directive
- 宣言的データフェッチ
- クライアントが取得するデータを自由に宣言出来る
- Overfetching対策
- Underfetching対策
- 1度のレスポンスに載せられる有効な情報量が多い
- 複数のクエリを1回のリクエストに含めることが出来る
- リクエスト数削減
- 単一のエンドポイント
- クライアントからするとエンドポイント毎の仕様の違いを知る必要がなくなる
- Self-Documenting
- Introspection
- Schemeがそのままドキュメントになる
- 別途ドキュメントを作る工数が0
- RESTなどで発生する、API仕様の統一化のコストがなくなる
- 型がある
- TypeScriptと相性が良い
- React エコシステムとの相性が良い
- 進化するAPI
- インクリメンタルな実装
Universal BFFとしてのGraphQL
サーバーサイドのアーキテクチャの観点からはこの特徴を理解しておく必要があります。
その前にBFFの特徴を見ていきます。
BFF
出典: Pattern: Backends For Frontends - samnewman.io
2010年代中盤に出来てたアーキテクチャパターンで、モバイルの台頭によるマルチクライアント化、Docker・Kurbernetesなどのコンテナ技術の台頭によるマルチアプリケーション化による課題に対するパターンです。クライアントとサーバーアプリケーションが多対多になることで双方のコミュニケーションコスト(通信も人も)が多重化し増大していきます。BFFは主にクライアントの負担を減らすためにクライアント毎にそれぞれ導入されます。またクライアントにとって利用しやすいAPIをリソースサーバーに変わって実現することでクライアントファーストなAPIデザインを行うことができます。
BFFの特徴
- クライアントのためのAPIデザイン
- リソースサーバーからUseCaseを分離する
- リソースサーバーの実装負担が減る
- あらゆるリソースとつながる
- Microservices, Serverless
- 最適な言語、最適なデータソースを選択出来る
- サービス毎のコンピューティングリソースの最適化
- 変更容易性が高い
- レガシーアプリケーションのモダン化
- Microservices, Serverless
- HTTPSオフローディング
- gRPCなどの軽量プロトコルに載せ替え
- ステートレスな実装
- スケールアウト可能
個別のBFFの課題
個別のBFFを実装していく中で課題もあります。
- BFF間で似たような重複実装になってしまう
- リソースサーバーへのアクセスの多重化は解決されていない
- クライアントごとに作るのでクライアントがある程度大きくなるまでは導入されずらい
- それまではクライアントはバックエンド都合で作られたPIでやりくりする必要がある
Universal BFFとしてのGraphQL
出典: https://www.apollographql.com/docs/apollo-server/
GraphQLは全てのクライアント向けのBFFとして振る舞います。BFFとしての特徴を引き継ぎながら、個別のBFFで起きていた課題を解決しています。
Universal BFFとしてのGraphQLの特徴
BFFパターンの特徴
- クライアントのためのAPIデザイン
- リソースサーバーからUseCaseを分離する
- リソースサーバーの実装負担が減る
- あらゆるリソースとつながる
- Microservices, Serverless
- 最適な言語、最適なデータソースを選択出来る
- サービス毎のコンピューティングリソースの最適化
- 変更容易性が高い
- レガシーアプリケーションのモダン化
- Microservices, Serverless
- HTTPSオフローディング
- gRPCなどの軽量プロトコルに載せ替え
- ステートレスな実装
- スケールアウト可能
に加えて
- 全てのクライアント向けのBFF
- 複数BFFでの問題を解決
- 重複実装を防ぐ
- リソースサーバーへのアクセスの多重化を解決
- 開発のどの段階でも導入可能(初期、中期、終盤)
API GatewayとしてのGraphQL
Universal BFFとして全てのクライアント・全てのリソースサーバーの中心につながる事になったのでAPI Gatewayとして振る舞う事が出来ます。
URLベースAPI GatewayのOSS実装としてKong GatewayやKrakenDがあります。Kurbernetes界隈ではIstio Ingressが使われるみたいです。クラウドではAzureにはAzure Application GatewayやAzure API Management, AWSにはAmazon API Gatewayがあります。
GraphQLではそれと同等の機能を盛り込む事が出来ます。
APIGatewayの特徴としてわかりやすいのでKrakenDの特徴の画像を参考として引用します。
API Gatewayの特徴
- Gateway オフローディング
- リソースサーバーから共通処理をオフローディングする(認証, ログ, セキュリティ, etc)
- 複数エンドポイントに比べて、HTTP/1.1のハンドシェイクのオーバーヘッドを軽減出来る
- 認証サーバーは別途必要(OAuth2.0, OpenID Connect等)
GraphQLのエコシステム
- Apollo Server: メジャーなGraphQLサーバーサイド実装(Node.js)
- Apollo Client: メジャーなGraphQL クライアント実装
- Apollo Federation: 複数のGraphQLをまとめる。大規模GraphQLを実装する際にサービスを分離できる
- Apollo Studio: 監視, メトリクス, 通知を行うサービス
- GraphQL Playground: GraphQLをGUIで操作するためのツール
- graphql-code-generator: SchemaからTypeScriptなどの型情報としてコード生成するツール
- Hasura: CMS as GraphQL + PostgreSQL
- AWS AppSync: AWSサービスに接続するためのGraphQL PaaS
まとめ
GraphQLの特徴を3つに分けて分類してみました、トップの図を見るとわかりやすいと思います。日本の現状ではフロントエンド界隈で若干の盛り上がりを見せていますが、主にAPIインターフェースの部分だけが語られているような気がしています。サーバーサイドのアーキテクチャパターンとしてはBFF, API GatewayのベストプラクティスとしてのGraphQLがあると思っていて、サーバーサイドの人たちにはこのあたりが伝わっていくといいのかなと思ってます。GraphQLは特徴としてクライアントとサーバーサイドの橋渡し役なので、フロントエンドとサーバーサイドの双方の了解を経て初めて採用される性質があります。そのためサーバーサイド側の理解が更に進んでくことを期待しています。
さいごに
GraphQLはいいぞ
よかったらフォローおねがいします。 @saboyutaka
[追記 2021/07/16] [PR] Software Design 2021年8月号にGraphQLの特集を寄稿しました
Software Design 2021年8月号にて、GraphQLの特徴や解決している問題、そしてGraphQLの基本動作原理(クエリ言語、型システム、実行エンジン)について29ページに渡って特集を寄稿しました。 GraphQLを理解するための手がかりになればと思って書いたので興味ある方はぜひ読んでみてください!