handatのdatファイル

日頃の出来事を格納するdatファイル

「初めてのGraphQL」でGraphQLに再入門した

ここ数ヶ月の間GraphQLのサーバサイドの開発をする機会があったのだが、その中で一番難しかったのがスキーマ定義をすることだった。 DBのカラムと1対1になるようなフィールドであれば簡単だが、実際にはそうではないフィールドが必要になり、その定義をどうやって決めれば良いかの判断が難しかったからである。

そこで、初めてのGraphQLを読むことにした。

この本は大まかに言うと以下のような構成になっている。

  • 1,2章: GraphQLの導入
  • 3,4章: 仕様や型定義の説明
  • 5,6章: サーバーサイド/クライアントサイド実装のハンズオン
  • 7章: セキュリティや発展的な使い方
  • 付録: Relayの仕様解説

この記事ではGraphQLの理解を深め、スキーマを定義に役立てられそうな1,2章を中心に要点や感想を書いている。

GraphQLとは

  • APIのためのクエリ言語
  • どのような形でデータを渡すかのみを重要視していて、どのようにデータを生成するかに関心はない

GraphQLの仕様として決まっているのはクライアント/サーバ間の通信を行うための言語仕様のみなので、実装する言語やデータソースに依存しないということが書かれていた。
実際にサーバサイドの実装はメジャーな言語ではすべての言語にGraphQLのライブラリが存在している。

実装面に関する定義がなくRESTのようにAPIの仕様だけになっているということが多くのアプリケーションでGraphQLを採用する一つの要因になっていると感じた。

GraphQLの設計原則

GraphQLの設計原則として以下の5つがが公開されている。

  • 階層構造 (Hierarchical)
    • クエリは階層構造になっていて、フィールドを入れ子にすることができる
    • レスポンスはクエリと同じ階層構造になる
  • プロダクト中心 (Product‐centric)
    • フロントエンジニアを主体として、彼らの考え方や要件に従って実装される
  • 強い型付け (Strong‐typing)
    • アプリケーションごとに定義されている型に基づいている必要がある
  • クライアントごとのクエリ (Client-specified response)
    • GraphQLアプリケーションはクライアントが利用できる機能を公開する
    • GraphQLで提供される機能をどのように利用するかはクライアントが責務をもつ
  • 自己参照 (Introspective)
    • GraphQLサーバは自身の型定義に基づいてGraphQLクエリで問い合わせできる

サーバサイドとして設計原則を読むとGraphQLの型定義に基づいたクエリを定義に基づいて同じ階層構造を返すことだけが求められているように感じた。 一方で「フロントエンジニア主体」や「どのように利用するかはクライアントが責務を持つ」などの表現からGraphQLがクライアントサイドに重きを置いていることがよく分かる。

一つ気になったこととしては、この本の発行(2019年4月)時点のリリース(June 2018)と最新のリリース(October 2021)で5つの原則の順番が異なっている。

June2018版では最初の2つが Hierarchical, Product‐centricの順番になっているが、October2021版ではProduct-centric, Hierarchicalと順番が入れ替わっていた。
GraphQLがプロダクト志向であることをより強く主張したいという意図があるのかもしれないが、それを決定付けるような記事は見つけられなかった。

GraphQLが解決するRESTの課題

  • 過不足あるデータ
    • クライアントで使わない余分なデータもレスポンスに含めることによるパフォーマンス悪化
    • クライアントに必要なデータをすべて取得するために複数回のリクエストが発生することによるパフォーマンス悪化
  • エンドポイント管理の難しさ
    • 過不足あるデータをクライアントごとに最適化しようとするとAPIエンドポイントの数が膨大になる
    • クライアントで必要なデータが変更になると、APIの仕様自体を変更する必要がある

エンドポイント管理の観点に関しては、実際にGraphQLを使ってみるとエンドポイントが1つしかないため、キャッシュの仕組みを考える必要があったり、どんなクエリがを調べるためにアクセスログが使えないなどRESTと比べてデメリットあるようにも思える。
しかし、1つめの必要なデータを1クエリで取得するという要件も含めてクエリごとにRESTのエンドポイントを用意するコストと比較するとGraphQLを使うメリットの方が圧倒的に大きいように感じる。

グラフ理論

上記を踏まえて、2章で説明されているグラフ理論についても少し触れたい。 下記はWikipediaから引用したものである。

例えば、鉄道や路線バス等の路線図を考える際には、駅(節点)がどのように路線(辺)で結ばれているかが問題となる一方、線路が具体的にどのような曲線を描いているかは本質的な問題とならないことが多い。

したがって、路線図では駅間の距離や微妙な配置、路線の形状などがしばしば地理上の実際とは異なって描かれている。つまり、路線図の利用者にとっては、駅と駅の「つながり方」が主に重要な情報なのである。

ー「グラフ理論」(2023/09/02 14:00の版)『ウィキペディア日本語版』。

個人的には路線図の例えがすごくしっくりきた。

路線図を利用者が見る時、下記のような関心ごとがあると思う。

  • 今いる駅はどんな路線が通っているか
  • それぞれの路線に乗るとどこに行けるのか
  • 目的の駅に行くためにはどこで乗り換える必要があるのか

逆に、上記以外の物理的な位置や正確な距離は関心ごとではないため路線図を作る上で重要視されていないことになる。

このグラフ理論をベースとしているからこそ、GraphQLがプロダクト中心でありクライアントが関心を持つことだけを取得できるという原則を重要視しているという考えをより理解することができた。

どう生かすか

初めてのGraphQLを読んでGraphQLはクライアントサイドのためにあるものだということが再認識でき、グラフ理論や路線図の例えによってクライアント主体として考えることでどのようなメリットがあるのかも理解できた。

今後、GraphQLのサーバーサイド開発の求められるのは以下の3つを心がけたい。

  • 関心ごとに着目する(型やフィールドが何のために必要なものなのかを理解する)
  • その上でクライアントサイドが求めている機能を開発する
  • クライアントサイドから見えにくい非機能要件に関しては責任をもつ