概要
GraphQL は API (Application Programming Interface) のクエリ言語であり、既存のデータに対してクエリを実行するためのランタイムです。REST API との違いとして、エンドポイントが 1 つのみであり、クライアントが取得したい情報をクエリで指示するような形となります。これにより、REST API が抱えるような以下の課題を解決することができます。
- 必要のない情報までレスポンスに含まれてしまい、クライアント側で情報を取捨選択する必要がある (Overfetching)
- クライアントは 1 つの API 呼び出しで必要な情報を全て取得することができず、複数回異なる API エンドポイントに対して通信をする必要がある (Underfetching)
- データに型が存在しないので、どのようなデータを送信すればよいか、どのようにレスポンスを処理するべきか、クライアント/サーバー側の型チェックができない
- 特定のユースケースに対応するために専用のエンドポイントを作成する必要が出てくる (例えば https://hoge.com/dogWithOwner 等)
上記の通り、GraphQL では必要な情報を 1 つのエンドポイントから少ない回数の HTTP リクエストで取得できる ようになり、またクエリを実行する際に細かく条件を指定することで 必要以上に大きなデータがレスポンスとして返却されることを防ぐ ことができます。
GraphQL の構成
GraphQL は大きく分て クエリ言語 (フロント側、リクエスト) と スキーマ言語 (サーバー側、レスポンス) の 2 つにより構成されます。
クエリ言語
クエリ言語とは GraphQL サーバーに対してリクエストをするための言語であり、データ取得系の query 、データ更新系の mutation 、サーバー再度からのイベント通知である subscription の 3 種類があります。
クエリの種類 | 役割 |
---|---|
query | データ取得 (GET) |
mutation | データ更新 (POS, PUT, DELETE …) |
subscription | イベント通知 |
スキーマ言語
スキーマ言語 (SDL) は、GraphQL API の仕様を記述するための言語であり、クエリ言語からのリクエストはスキーマ言語で記述したスキーマに従って GraphQL 処理系により実行され、データグラフ構造のレスポンスを生成する。フレームワークや言語に依存せずに定義が可能です。
なお、スキーマ言語はあくまで GraphQL API の仕様定義のみを行い、実際のデータ操作は行わない。実際のデータ操作を行うのはリゾルバという、特定のフィールドのデータを返す関数 (メソッド) となります。
GraphQL ではさまざまなプロトコル (TCP/UDP/WebSocket) が使用でき、NoSQL や RDBMS 、ローカルのデータや REST API 等、データソースの種類に依存せず利用することが可能となります。
GraphQL サーバー
GraphQL はクエリ言語であるため、使用の際は GraphQL サーバーの構築が必要となる。また GraphQL サーバーはデータソースと通信を行い、必要に応じてデータを取得及び変更する役割を担います。
主な GraphQL サーバーのライブラリは以下の通りとなります。
- GraphQL-JS: node.js のフレームワークである Express で利用可能な GraphQL オリジナルのリファレンス実装
- GraphQL Yoga: Express サーバーと Apollo サーバー上に構築された Prisma のサーバー実装
- Apollo Server: Apollo コミュニティが管理する GraphQL サーバー
GraphQL クライアント
フロントエンド側から GraphQL API に直接クエリを実行することもできるが、専用のクライアントライブラリを使用するとより簡単に実施できます。
主な GraphQL クライアントライブラリは以下の通りとなります。
- Relay: GraphQL を利用して React アプリケーションを構築するための Facebook による JavaScript ライブラリ
- Apollo Client: 陸絵うとをキャッシュし、データを正規化しトラフィックを節約する。React だけではなく、Vue や Angular 、また iOS との連携も可能。
Hello World をやってみる
早速 GraphQL を使って Hello World をやってみましょう。まずは環境構築から。
$ mkdir hello-world
$ cd hello-world
$ touch server.js
$ npm init
$ npm install express@4.17.1 express-graphql@0.12.0 graphql@15.4.0 --save
次に、server.js
を以下の通り編集します。
const express = require("express")
const { graphqlHTTP } = require("express-graphql");
const { buildSchema } = require("graphql");
// Defining GraphQL Schema
const schema = buildSchema(`
type Query {
hello: String
}
`);
// Resolver function
const root = {
hello: () => {
return "Hello World!";
},
}
// Launch Express server. Set graphiql: true to use GraphiQL
const app = express();
app.use("/graphql", graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}));
app.listen(4000);
console.log("Running a GraphQL API server at http://localhost:4000/graphql");
上記完了後、server.js
を実行することで、ブラウザから http://localhost:4000/graphql で GraphQL の IDE (GraphiQL) にアクセスできると思います。
$ node server.js
Running a GraphQL API server at http://localhost:4000/graphql
左側がクエリを書くエディタ部分で、実行結果はその横に表示されます。< Docs の部分をクリックすることで Documentation Explorer が開き、実行可能なクエリ一覧を確認することができます。
続いて、実際にクエリを書いてそのレスポンスを確認します。GraphQL のクエリはルート型で始まります。ルート型とは Query や Mutation 、Subscription などデータソースに対する操作を表現する型です。それでは以下のようにクエリを書いてみます。
query {hello}
すると、以下のレスポンスを得られるかと思います。
{
"data": {
"hello": "Hello World!"
}
}
このように GraphQL では:
- スキーマ定義でクライアント側から操作できるクエリを事前に定義し、
- リゾルバ関数にてデータを返す操作を行い、
- クライアント側からルート型から始まるクエリを発行する
ことによってデータソースへのアクセスが可能となります。