RESTの課題とGraphQL 〜GraphQLを簡単に使ってみる〜

## RESTとは
以下の記事等でもまとめていますが、REpresentational State Transferの略で、分散型システムにおける複数のソフトウェアを連携させるのに適した設計原則の集合、考え方のことです。
※詳細は以下記事を参照ください。

* [RESTful APIとは何なのか](https://qiita.com/NagaokaKenichi/items/0647c30ef596cedf4bf2)
* [リソース指向アーキテクチャ(ROA)とは何なのか](https://qiita.com/NagaokaKenichi/items/0f3a55e422d5cc9f1b9c)
* [Web APIとは何なのか](https://qiita.com/NagaokaKenichi/items/df4c8455ab527aeacf02)

Web APIのインターフェースとしては割と一般的になりつつありますが、本記事ではそんなRESTの課題と（それに取って代わるわけではないですが）GraphQLについて書きたいと思います。

## GraphQLとは
GraphQLとはFacebookが2015年に公開したAPIの規格です（APIのための問い合わせ言語とも言われることがあります）。RESTはAPIの設計原則の集合、考え方なのに対して、GraphQLは言語（クエリ言語、スキーマ言語）や型（スカラー型等）が標準化された規格になります。
※つまり、RESTに比べて多くの決まりごとが定められています。
RESTと異なり、その名が示す通り情報のグラフ構造に着目してクエリ言語を用いて情報を操作しようという考え方をしています。標準化された規格なので、開発言語は問いません。公式ページによると[これだけの言語がサポートされています](https://graphql.org/code/)。より実情に即した表現をするのであれば、Webの発達につれてRESTが適合しない状況が生まれ始めてきており、そういった状況に適合する形式のAPIとしてGraphQLが誕生しました。

## RESTの課題
RESTには以下の課題があると言われています。

#### 過剰な取得（オーバーフェッチ）

※一般公開されているThe Star Wars APIを（SWAPI）使って説明します。
例えば、SWAPIでダース・ベイダーの情報を取得する場合、URI（エンドポイント）は以下になります。
　https://swapi.co/api/people/4/
これにより取得できるリソースは以下の通りです。

```response.json
{
    "name": "Darth Vader", 
    "height": "202", 
    "mass": "136", 
    "hair_color": "none", 
    "skin_color": "white", 
    "eye_color": "yellow", 
    "birth_year": "41.9BBY", 
    "gender": "male", 
    "homeworld": "https://swapi.co/api/planets/1/", 
    "films": [
        "https://swapi.co/api/films/2/", 
        "https://swapi.co/api/films/6/", 
        "https://swapi.co/api/films/3/", 
        "https://swapi.co/api/films/1/"
    ], 
    "species": [
        "https://swapi.co/api/species/1/"
    ], 
    "vehicles": [], 
    "starships": [
        "https://swapi.co/api/starships/13/"
    ], 
    "created": "2014-12-10T15:18:20.704000Z", 
    "edited": "2014-12-20T21:17:50.313000Z", 
    "url": "https://swapi.co/api/people/4/"
}
```

多くの情報が返ってきますが、仮にアプリケーションで必要となるデータが名前（name）のみだった場合、それ以外のデータは不要なデータとなります。こういったデータはメモリに積まれるため、APIの使い方次第ではメモリリークにも繋がります。つまり、本当に必要なデータのみだけでなく不要なデータもレスポンスとして返されることがあります。

#### 過少な取得（アンダーフェッチ）
名前だけでなく、ダース・ベイダーが出演する映画のタイトルの一覧も必要となった場合、 以下のAPIを叩く必要がでてきます。
※上記JSONでは、映画リソースはfilmsフィールドにある4つのURIになります
　https://swapi.co/api/films/2/ 
　https://swapi.co/api/films/6/ 
　https://swapi.co/api/films/3/ 
　https://swapi.co/api/films/1/
つまり、名前と映画のタイトルの一覧を取得するだけなのにも関わらず合計5回もAPIを叩く必要があります。

#### 自由度の低さ
要件追加や仕様変更等により、APIを使うクライアントに変更が入ると、新しくエンドポイントを追加する必要がでてくることもあり、エンドポイントの数が膨れ上がります。これはエンドポイントの管理をより煩雑なものにし、また、フロントエンドとバックエンドでIFを擦り合わせる必要もでてくるため、開発速度の低下にも繋がります。

## GraphQLでどう解決されたか
GraphQLでは必要なデータだけを指定してリクエストを投げます。Star WarsのGraphQL API（SWAPI GraphQL API）を使って試してみます。SWAPI GraphQL APIのURLは以下です。
　https://graphql.org/swapi-graphql

RESTの課題で挙げた、ダース・ベイダーの名前と出演する映画のタイトル一覧を取得するクエリは以下の通りです。必要となるデータだけを指定します。

```
query {
  person(personID:4) {
    name
    filmConnection {
      films {
         title
      }
    }
  }
}
```

上記クエリを投げることで、以下のレスポンスが返ってきます。

```response.json
{
  "data": {
    "person": {
      "name": "Darth Vader",
      "filmConnection": {
        "films": [
          {
            "title": "A New Hope"
          },
          {
            "title": "The Empire Strikes Back"
          },
          {
            "title": "Return of the Jedi"
          },
          {
            "title": "Revenge of the Sith"
          }
        ]
      }
    }
  }
}
```

上記の実行イメージは以下のような感じです。左がクエリ、右が実行結果です。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23101/1199134e-5739-c30c-bd5e-04996b3d35bb.png)
GraphQLを使えば1回のリクエストで指定したデータのみを取得することが可能なことがわかります。RESTのように、レスポンスデータを使って更に何回もAPIを叩いてデータを取得する必要はありません。また、GraphQLは基本的にエンドポイントは1つです。単一のエンドポイントに送られるクエリに基づいて様々なデータを統合します。

## GraphQLの実情
日本ではまだまだ採用事例は多くありませんが、開発元のFacebookはもちろんのこと、GithubのAPI V4ではRESTからGraphQLに切り替わっています。また、ニューヨーク・タイムズ、IBM、Twitter、Yelpといった企業でもGraphQLは採用されています。

## 最後に
本記事では、RESTの課題とGraphQLについて簡潔に紹介しました。以降の記事ではもう少しGraphQLについて踏み込んでみたいと思います。

以上です。

## 参考
* https://graphql.org/
* https://www.amazon.co.jp/%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AEGraphQL-%E2%80%95Web%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E5%AD%A6%E3%81%B6%E6%96%B0%E4%B8%96%E4%BB%A3API-Eve-Porcello/dp/487311893X