GraphQLとは
英語によるオリジナルはこちらでご覧いただけます。
アプリケーションの開発プロジェクトの経験があるなら、「GraphQL」という言葉を聞いたことがあると思います。このGraphQLとは、具体的に何を指しているのでしょうか。サーバーサイドやクライアントサイドで使う手法なのでしょうか。他の手法ではなくGraphQLを採用すべきなのは、どのような場合でしょうか。
この記事では、こうした疑問を掘り下げ、GraphQLのメリットを明らかにしていきます。
GraphQLは、オープンソースのAPIクエリ言語として主に知られています。急速な発展を経て、アプリケーションプログラミングインターフェース(API)設計にとって不可欠な技術となりました。GraphQLには、コーディングのパイプラインにおける柔軟性と効率性の向上をはじめ、多数のメリットがあります。クライアントのブラウザやデバイスとサーバーとの間の通信を効率化できることから、開発者はウェブ機能の高速処理を効果的に実現し、アプリケーションを迅速に開発できるほか、アプリケーションの機能を総合的に強化できます。この記事では、GraphQLの定義、動作の仕組み、サンプル、ユースケース、メリットについて説明し、GraphQLの全体像に迫っていきます。
GraphQLとは
GraphQLは、APIの種類(あるいはクエリ言語)の1つでもあり、その種類のクエリに応答するランタイムエンジンでもあります。GraphQLのAPIは効率的で、モバイルアプリや、複雑なスキーマを使ってデータのサブセットのみを扱う実装に最適です。
GraphQLでは、APIからフェッチしたいデータを開発者が指定できます。また、一括取得ではなくオンデマンドでフェッチしたり、変更を直ちに反映したりできるほか、サードパーティのデータソースをアプリケーションに統合するといったことも可能です。
アプリケーションは、GraphQLのクエリを使用してGraphQLのサービスを呼び出すことができます。GraphQLのクエリでは、クライアントが求めるデータ要素のみを過不足なく取得できるため、複数回のAPIコールを減らし、ネットワーク帯域幅や後処理を抑制できます。データを中心に扱うAPIや、携帯電話やタブレットなどのクライアントデバイスに近いエッジに位置するAPIにとっては、きわめて効率的なソリューションとなります。
GraphQLの歴史
GraphQLは、Facebookのモバイルアプリ向けとして2012年にMetaにより開発されました(その後2015年にオープンソース化)。GraphQLの狙いは、RESTのいくつかの欠点を解消することにありました。
GraphQLの導入は現在も増え続けています。分散データにAPI経由で簡単にアクセスしたいと考える企業にとって、GraphQLは堅実な選択肢です。GitHub、PayPal、Shopify、Netflix、Facebookといった大手サービスがGraphQLを利用しているのも納得できます。
RESTはGraphQLに取って代わられるか
RESTは現在もAPIアクセスの中心的な手法の座を維持しており、GraphQLに取って代わられることはありません。
なぜなら、RESTはAPIを構築するためのアーキテクチャフレームワークであるのに対し、GraphQLはランタイムエンジンとクエリ言語の両方の役割を担っているからです。基本的に、REST APIのやり取りには、HTTPリクエストが使われます。一方GraphQLでは、クライアントはサーバーサイドのランタイムエンジンが提供するAPIサービスにURLを通じてアクセスします。
GraphQL APIは、クエリを実行するときに、REST API、データベース、マイクロサービスなど、いくつかのデータソースを同時に利用します。サーバーは、これらのデータソースの違いを隠蔽し、要求されたデータを単一のAPIで提供します。複数のカテゴリのデータに1回の呼び出しでアクセスできることは、既存のクエリ言語との重要な違いの1つです。
GraphQLのユースケース
モバイルアプリ、ウェブアプリケーション
GraphQLを利用することで、モバイルアプリやウェブアプリケーションの処理効率や処理能力が向上します。(だからこそ、Metaはモバイルアプリの開発向けにGraphQLを考案しました)。GraphQLなら、サーバーに複数のリクエストを送信しなくても、単一のエンドポイントを通じてデータをクエリできます。読み込み時間を短縮し、ユーザー体験を向上させることが可能です。
リアルタイムのダッシュボードとデータ集約
データの変化を常に監視したい場合に、GraphQLを利用してリアルタイムのダッシュボードアプリケーションを構築すれば、刻々と変化するデータセットの状況を絶えず把握できます。またGraphQLなら、複数のデータソースを1つの画面に集約させることが容易であるため、全体の分析を改善できます。
APIの集約とバージョン管理
GraphQLでは複数のAPIをGraphQLの単一のエンドポイントに統合できます。これによって、APIの各バージョンの推移を把握しやすくなるとともに、データのバージョン管理の手段が得られます。
データのキャッシュ
GraphQLを使用し、データをクライアントサイドでキャッシュすることで、読み込み時間を短縮できます。
GraphQLの動作の仕組み
GraphQLは次の2つの要件を満たすように開発されました。
- データソースから得るデータは、クライアントの求める内容に過不足なく適合している必要がある。
- クライアントでのデータの利用方法が、APIやデータソースの設計に左右されないようにする。
この2つの要件を満たすために、GraphQLサービスはスキーマを定義します。
スキーマ、フィールド、型、リゾルバ
GraphQLのスキーマとは、クライアントがGraphQL APIにリクエストできるデータについて記述したものです。この中には、クライアントがクエリで取得する可能性があるデータをすべて指定します。スキーマ定義言語(SDL)の形式で記述して、スキーマの可読性を高めるのが理想的です。
スキーマは、クエリでアクセス可能なオブジェクトの種類を定義するオブジェクト型と、それぞれのオブジェクトがもつフィールドで構成されます。例えば、下記のコードはあるGraphQLクエリのスキーマです。
`type query {
teacher
students {
name
}
}
}`
このスキーマを見ると、teacherとstudentsという2つのフィールドがあることがわかります。
従来のREST APIの場合、生徒の名前と担任教師の名前を取得したいアプリケーションがAPIのURLに対してクエリを実行すると、APIからは例えば、教師の名前、クラスの生徒数、学科、生徒の名前、生徒の年齢といったデータが返ってきます。
つまり、クライアントは必要のないデータまで取得することになります。一方、GraphQLサービスで上記のスキーマが定義されている場合、クエリを実行したアプリケーションは、生徒の名前と教師の名前という必要最小限の情報のみを取得できます。例えば次のような出力です。
`{
"data": {
"teacher”: "Joe Bloggs",
"students": [
{
"name": "Jane Doe"
},
{
"name": "Joe Smith"
},
…
]
}
}`
オブジェクト型を構成する各フィールドも個別に型をもちます。フィールドの型は、別のオブジェクト型か、String、ID、Boolean、Int、Floatといったスカラー型のいずれかです。
例えば、classオブジェクトのスキーマは次のように定義できます。
`type class {
teacher: String
student: [StudentName]
}
type StudentName{
name: String
}`
そのうえで、スキーマの各フィールドをリゾルバに関連付けます。リゾルバとは、GraphQLクエリでそのフィールドのデータをフェッチする関数です。GraphQLのクエリエンジンは、実行時にすべてのクエリをスキーマと照合して、クエリを検証します。そして有効なクエリの場合には、クエリエンジンが各フィールドのリゾルバを実行して、そのフィールドのデータをフェッチします。
GraphQLで実行可能な操作
ここまで、GraphQLのクエリを使ったデータの読み取りについて説明してきましたが、クライアントが実行可能な操作は、実は読み取りだけではありません。GraphQLクライアントが要求できる操作には、クエリとミューテーションという2種類があります。
GraphQLのクエリ
GraphQLのクエリは、REST APIのGETメソッドに似ています。本記事ではここまで、この操作によるデータアクセスについて説明してきました。
GraphQLのミューテーション
ミューテーションとは、データの追加や変更を求めるリクエストです。REST APIのPOST、PUT、PATCH、DELETEの各メソッドに似ています。
GraphQLのサブスクリプション
GraphQLのサブスクリプションは、サーバーにリクエストを送信することなくリアルタイムのデータを受信できる強力な仕組みです。クライアントはこの機能を利用して、データベースに加わった変更や削除についての通知を受け取り、さらには、関連するクエリのステータスに関する更新のストリームを受信できるようになります。サブスクリプションを利用するクライアントは、目的のイベントを選択し、そのイベントが発生したときにデータをどのように受け取るかを指定できます。GraphQLのクエリやミューテーションの場合は、サーバーとの短時間のHTTP接続を使ってリクエストを送信するのに対し、GraphQLのサブスクリプションの場合は、クライアントはWebSocketを使って持続的な双方向の通信チャネルを確立する必要があります。
こうして確立する接続を使って、クライアントはサブスクリプションのクエリをサーバーに送信できます。
GraphQL vs REST
REST(Representational State Transfer) APIは広く使われています。しかし、あらゆる状況で最善の選択肢であるとは限りません。例えば、カスタマイズ性はGraphQLの方が優れています。さらに、ユースケースが適切であれば、効率性にも優れています。
RESTでは、サービス開発者とクライアントとの協調が必要で、画面ごとに異なるカスタムAPIを使用します。これに対しGraphQLでは、必要なデータとしてアプリケーション開発者が指定した内容と、提供可能なデータとしてサービス開発者が規定した内容を組み合わせます。
しかし、GraphQLやgRPCを検討する特段の理由がないアプリケーションでは、実績豊富なRESTが最善の場合もあります。
その他、RESTとGraphQLでは、俯瞰的に見ると次のような違いがあります。
- クエリの柔軟性は、RESTよりGraphQLの方がはるかに優れています。
- RESTはデータをフェッチする際にサーバーとクライアントの間で複数回のやり取りが必要になる場合がありますが、GraphQLは1回のやり取りで済みます。したがって、モバイルアプリの場合や、帯域幅について考慮が必要なユースケースの場合には、GraphQLの方が適しているかもしれません。
- RESTはキャッシュを強力にサポートしていますが、GraphQLはサポートしていません。ただし、サードパーティのGraphQLライブラリで補完できます。
- GraphQLは、RESTに比べて覚えることが多くあります(GraphQLのチュートリアルや、習熟のための時間をチームに与えることが必要な場合があります)。RESTはHTTPやクライアントサーバーアーキテクチャに慣れている人なら簡単に理解できます。
- GraphQLはスキーマを通じて自己文書化されていますが、RESTはそうではありません。
- GraphQLはバックエンドでRESTより多くの処理が必要になる場合があるものの、APIの使いやすさが高まる可能性があります。
- RESTはファイルのアップロードをサポートしていますが、GraphQLはサポートしていません。
GraphQLのメリット
GraphQLのメリットを大まかに言うと、柔軟性、一貫性、セキュリティの向上や、帯域幅と複雑さの抑制があります。理想的な活用法やメリットを見ていきましょう。
オーバーフェッチやアンダーフェッチがない
GraphQLの最も重要なメリットは、要求されたデータのみを返すことができ、オーバーフェッチ(過剰取得)がRESTクエリに比べて最小限で済むことです。RESTを使用して単一のエンドポイントへのクエリを行う場合、無関係な情報が大量に含まれている場合があります。一方GraphQLは、特定のデータのみを取得するのがより簡単です。またRESTでは、必要なデータを1つのデータソースで得られないときは、複数のAPIコールが必要になります。その場合、いずれの場所もアンダーフェッチ(過少取得)ということになります。
GraphQLの場合は、クエリで取得可能なデータ要素を限定するためのスキーマを明確に規定することによって、RESTのようなジレンマが解消されます。
ネットワークの通信量を抑制
GraphQLのクエリは、実行のたびに必要なデータセットのみを取得することから、オーバーフェッチの場合に比べてペイロードが格段に小さくなります。
また、GraphQLのクエリは複数のリソースに向けて複数のリクエストを送信する必要がないため、ネットワークトラフィックも抑えられます。地理的に離れたネットワーク間で互いに通信する分散アプリケーションにとってプラスになります。
HTTP/HTTPSプロトコルに対応
GraphQLのクエリでは、APIへのアクセスにHTTP/HTTPSプロトコルを使用できます。したがって、アプリケーションを設計するときに、新たな通信手段に対応する必要はありません。
APIの拡張
GraphQL APIは、クエリの動作を維持したままでスキーマを段階的に拡張できるようになっています。REST APIと同様にバージョン管理が可能ですが、スキーマを継続的にアップグレードする手段がある点がREST APIと違います。それぞれのクエリは、要求されたデータ要素以外は返さないため、オブジェクトやフィールドの数が増えても、既存のクライアントのリクエストが破綻をきたすことはありません。新たなクエリを作成することで、新たなオブジェクトやフィールドを取り入れられます。
強い型付けのスキーマ
GraphQLのスキーマやそのオブジェクト型は、階層型・宣言型で定義されています。そのため、開発者にとっては、データ要素間の関係(「グラフ」など)の理解や、クエリの構造の微調整がしやすくなっています。
また、スキーマやオブジェクトには強い型付けが適用されています。GraphQLのランタイムエンジンは、クエリの構文が正しいかどうかと、クエリで要求されたデータの型がスキーマのフィールドやオブジェクトの型に合致しているかどうかを確認します。
不一致が見つかった場合には、サービスはエラーメッセージを返します。強い型付けと、明確に定義されたスキーマによって、クエリが想定どおりに動作する可能性が高まり、エラーも簡単に検出できます。
ツールが充実
GraphQLは、開発ツールやテストツールのエコシステムが活発であることも特長としてあげられます。なかには、開発がかなり容易なオープンソースのツールもあります。広く利用されているGraphQL用のツールには、Apollo、Graphback、GraphiQL、GraphQL Playground、GraphQL Explorerがあります。
まとめ
GraphQLは、RESTの代わりとなる手法です。開発者はサーバーからフェッチするデータを宣言型で定義できます。従来のREST APIと比べたときのGraphQLのメリットには、パフォーマンスと効率性が向上する点や、クライアントが必要なデータのみを要求できる点があります。