はじめに
GraphQLを用いたフロントエンド開発は多くなってきているように思います。
フロントエンドから柔軟にデータを取ってくることができるということは、今までバックエンドが担保してきていた部分をフロントエンドが担わないといけなくなった
ということを意味します。
保守性をちゃんと考えないといけない。
ということですね。
今回はその中でも結構重要な、スキーマ定義についての話。
採用する、しないはどちらを選んでも大きな判断になるかと思いますが、知っておく必要はある知識かなと思います。
スキーマとは?
スキーマというのはQuery(データの取得)やMutation(データの更新や削除)といったものを定義したものです。
この定義にそってフロントエンドから以下のようにクエリを書き、データの取得や更新を行っていく訳ですね。
query {
albums(limit:20) {
title
tracks (limit:2) {
name
}
}
}
この定義ですが、適当に作り始める前に知っておいた方が良いことがあります。
Global Object Identification
という概念です。
Global Object Identification
とは?
全テーブルにおいてグローバルなID(NodeID)を発行し、キャッシュするようにしましょう。
と言う話です。
意味がわかりませんね。一つ一つ解説します。
GraphQLのキャッシュとは?
RESTfulなAPIの場合、https://smaple.com/api/items/5
のようにURLベースでデータに問い合わせにいったりしますね。
なので、このGETリクエストをURLベースでキャッシュをすることができたりします。
CDNにGETリクエストごとキャッシュしたりすることで、ユーザーに高速にレスポンスを返すんですね。
しかし、GraphQLはエンドポイントを一つしか持たないため、キャッシュを行うことができません。
なので、なんとかして別の方法でキャッシュしたい
という話です。
どうやってやるのか?
URLベースでのキャッシュができないのであればどうするのか?
一度、アクセスしてくれたデータを何かをキーにしてオンメモリキャッシュに突っ込むことができればいい気がしますね。
その「何かのキー」というのに全テーブルにおいてグローバルユニークなIDを使おうということです。
DBのレコードIDでいいじゃないか。と思われるかもしれませんが、usersテーブルとpostsテーブル、両方にid: 1は存在すると思います。
なので、全テーブルにおいてユニークなIDが必要なんです。
これをGlobal Object Identification
ではNodeIDと表現しています。
全てのテーブル型定義において、Node
というインターフェースを継承します。
interface Node {
# The ID of the object.
id: ID!
}
type User implements Node {
id: ID!
# Full name
name: String!
}
こうしておくことで、フロントエンドからすると、Userデータをフェッチした時にidが全テーブルにおいてユニークなIDが返ってくるので、データをリフェッチするときは以下のようにnodeIDでとって来ればキャッシュから返ってくる。
といった仕組みですね。
query {
node(id: nodeID) {
users (limit:2) {
name
}
}
}
どう作るのか?
簡単に考えるとテーブル名:ID
みたいな形にすればいけそうですね。
ちゃんとやるのであれば、全テーブルでユニークなUUIDを振るみたいな方法もあります。
実はこれは結構大変。
だって、データを作成する時に全テーブルにおいてユニークな何かを保存しておかないといけないのだから、、
micro serviceみたいな構成にしていてデータベースが分かれている。
みたいな人たちはより大変ですね。
GraphQL Serverのレイヤーでうまく処理できるようにしていく必要があるかなと思います。
まとめ
最初にもいった通り、Global Object Identificationの概念を取り入れるとリフェッチが効率化できたりします。
でも、作るのめちゃくちゃ大変だと思います。
チームで話し合ってやるのがいいかなと思います。