GraphQL は、クライアントが欲しい項目を指定してデータを取得する API の仕組みです。公式には「API のためのクエリ言語」と説明されています。窓口は1つにまとめ、何を返すかは要求する側が書きます。
query {
user(id: 123) {
name
orders(last: 3) { id total }
}
}
この1回の要求で、利用者の名前と直近3件の注文がまとめて返ります。REST API なら2回に分かれるところです。
REST との本当の違い
「必要な項目だけ取れる」はよく挙げられますが、運用で効いてくる違いは別のところにあります。
| REST API | GraphQL | |
|---|---|---|
| 窓口 | 対象ごとに分かれる | 1つにまとまる |
| 返す内容を決めるのは | サーバー側 | 要求する側 |
| 必要な往復 | 画面によっては複数回 | 1回にまとめやすい |
| HTTPのキャッシュ | そのまま効く | 効きにくい |
| 重い要求の防ぎ方 | URLごとに見れば足りる | 要求の中身を見る必要がある |
下2行が、導入後に必ず向き合うことになる部分です。
運用で必ず出てくる3つ
1つ目は、要求の重さを制御できないこと。 返す内容を要求側が決められるということは、深くたどる要求も書けるということです。関連をたどる階層の上限や、要求全体の複雑さの上限を決めておかないと、1回の要求でデータベースを埋め尽くせてしまいます。外部に公開する場合は必須の対策です。
2つ目は、N+1 の起きやすさ。 一覧を取り、その1件ごとに関連を引く形になると、件数に比例して問い合わせが増えます。100件の一覧で関連を引けば101回です。関連するIDをまとめて1回で引く仕組み(一般にデータローダーと呼ばれます)を最初から入れておくのが定石です。同じ問題はORMでも起きます。
3つ目は、キャッシュの置き場所が変わること。 REST なら URL ごとに経路上でキャッシュできますが、GraphQL は窓口が1つで中身が毎回違うため、その仕組みが使えません。キャッシュはアプリケーション側で持つことになります。
向いている場面、向かない場面
- 向いている:画面ごとに必要なデータが大きく違う。Webとモバイルが同じ基盤を共有する。複数のデータ源を1つの窓口にまとめたい
- 向きにくい:取得の形がほぼ固定されている。公開APIとして不特定多数に開ける。経路上のキャッシュに強く依存している
「新しいから GraphQL」ではなく、要求の多様さが実際にあるかで決めると外しません。詳しい比較はGraphQLとREST APIの違いにまとめています。