GraphQLを使っているエンジニアの人と話していて、自分がGraphQLをよくわかってないことに気づいたので、基本的な情報を調べてみた。
GraphQL
Metaが開発したOSS。APIを効率よく呼び出すために作られたクエリ言語。
SQLがRDBを使うように、GraphQLはGraphQL用の特殊なDBを使うのかと思いがちだが、そういうわけでは無い。GraphQLもRDBなどを使う。なので、DB内の計算などを効率化するわけでは無い。backend側のコードを見通し良く効率的に書ける、というモチベーションが強い印象。
GraphQLの特徴
必要なデータを過不足なく、一度で取得できる(アンダーフェッチ、オーバーフェッチが無い)。そのため、データフェッチの効率性が高い。
基本的に、1つのデータを取得する際1つのエンドポイントを呼ぶだけで完結するので、APIの設計をシンプルにすることができる。クエリ言語を柔軟に記載することができる。
色々なサポート機能がある。例えば、Subscriptionsという機能を使って、リアルタイムデータを効率的に扱うことができる。
向いているサービス
ソシャゲ、eコマースなどの複雑なデータ構造を持つサービス、リアルタイムデータを扱うアプリケーションなどで真価を発揮する。
一方で、データ構造がシンプルなサービス、キャッシュが重要なサービスなどには向いていない。
データベース
特定のデータベースに依存していない。RDBでも、NoSqlでもOK。必ずしも、GraphQLを使うとREST APIよりもデータベースからfetchする回数が減るとは限らない。実装次第。
Resolver
スキーマとデータソースを結びつける役割を持つ。スキーマはあくまで定義のみで、Resolverが実際の操作を行なってくれる。
Subscriptions
GraphQLサーバーにデータ変化などの特定のイベントが生じるたびに、クライアントにデータ送信するPubSubのような仕組み。クライアントがサーバーにGraphQLのクエリ、クエリ変数を送信する。サーバーは、イベントがトリガーされたらクエリを実行する。
DataLoader
データ取得に使用される汎用的なツール。データ取得をbatch処理する機能と、結果をcacheする2つの機能がある。
batchは、データ取得のリクエストを一定時間待って、その間に行われたリクエストを統合してbatch処理してくれる。
cacheは、batchに登録されるkeyと、それに対応するvalueの組をメモ化する。
これらの機能を使うと、データアクセスの回数が減少する。
DataLoader導入前
SELECT item_id, amount FROM orders WHERE customer_id = "foobar"; SELECT name, description, price FROM items WHERE id = "hoge"; SELECT name, description, price FROM items WHERE id = "fuga"; SELECT name, description, price FROM items WHERE id = "piyo";
DataLoader導入後
SELECT name, description, price FROM items WHERE id IN ("hoge", "fuga", "piyo");
N+1問題
N件のデータレコードを取得した時、関連レコードの取得にN回のfetchを行なって、N+1回のfetchをしてしまうこと。DataLoaderで解決できる。
Relay
Metaが開発しているGraphQLクライアント。
- 全てのObjectに対して、一意のGlobal IDを要求するので、データの再利用性が高い
- リスト、ページネーションなどの際、Connectionという仕様を使うことで効果的に処理できる
- Mutationを行いやすい
- Fragment colocationによって、データフェッチが最適化される
Fragment colocation
コンポーネントとGraphQLフラグメントを密接に配置するデザインパターン。
以下のような利点がある。
- 明確な依存関係を示すことができる
- 再利用性の向上
- 効率的なデータフェッチ
- 保守性の向上
GraphQLのメリット
クライアントはスキーマをもとに、欲しいフィールドだけをリクエストできる。
リレーションがある値は、一度のリクエストで取得できる。例えば、twitterのフォロー数、フォロワー数を取得する際、REST APIだと2回のリクエストが必要だが、GraphQLであれば一度で取得できる。
スキーマをもとに開発するので型の不一致が起きない。強い型付けが採用されている。
GraphQLのデメリット
クエリが複雑になる可能性・学習の難しさが挙げられる。
また、GraphQLのメリットを享受するのが難しい。GraphQLはMetaがReact・Relayと組み合わせて使い始めた。「RelayスタイルでないGraphQLに価値はない」と言うGraphQL有識者もいる。Relayを使わないにせよ、Fragment Colocationがわかってないとメリットを享受しづらい。
RESTでやっていたことが直感的にやり辛くなる側面もある。
gqlgen
GraphQLサーバーを構築するGoライブラリ。GraphQLスキーマ定義言語を使用してAPIを自動生成してくれる。
参考文献
https://sizu.me/adwd/posts/34mkeimfb06x
https://lyohe.github.io/blog/2021/12/16/reading-dataloader/#:~:text=graphql%2Fdataloader