GraphQLを初めて触ってみた

## はじめに
こんにちは。開発歴4ヶ月のエンジニアです。主にバックエンドをメインに開発しています。
今回はGraphQLについて学習したことを書いていきます。
## GraphQLって？
> GraphQLは、APIのクエリ言語であり、既存のデータでこれらのクエリを実行するためのランタイムです。
[GraphQL公式サイトから](https://graphql.org/)

クエリ言語？ランタイム？よくわからないので調べます。

###### クエリ言語
クエリ言語はGraphQLサーバーに対してリクエストするための言語です。
データを取得するための**query**、データを更新するための**mutation**、サーバーサイドからのイベント通知である**subcription**の３種類があります。

| クエリの種類 | 意味 | 効果 |
|:-:|:-:|:-:|
| query  | データの取得  | GET  |
| mutation  | データの更新  | POST/PUT/DELETE  |
| subcription  | イベントの通知  | Websocket  |

**※GraphQLサーバー**：クエリ言語を使うために必要なサーバー。データソースと通信して必要に応じてデータを取得、変更する役割を担う。
**※サーバーサイド**：サーバの中で動くプログラム
**※ランタイム**：プログラムとかを動かすとき（実行時）のこと。

結局のところGraphQLは、クエリ言語を使うために必要な部品といったところでしょうか。

## GraphQLの特徴
GraphQLの特徴は**エンドポイントが1つだけ**な点です。
エンドポイントとはAPIにアクセスするために必要なURIのことです。
REST　APIでは各リソースごとにリクエストをしないといけず、リクエストの回数とリソースの数が比例します。
例えば、「ユーザー情報」、「フォロワー一覧」、「投稿一覧」を取得するには合計3回のリクエストが必要になります。
一方GraphQLは後述したように、必要な情報全てを1つのエンドポイントから一回のリクエストで取得することが出来ます。

つまり1回のリクエストにしてHTTPリクエストの回数を減らすことができるし、クエリを実行する時に条件を細かく設定できるので必要なデータだけ取得することが出来ます。

## 実際にGraphQLを動かしてみる
調べているだけでは中々イメージが掴みづらいので実際に動かしてみます。

## Apolloを使ってGraphQL Serverを構築
Apolloは簡単にGraphQLServerを構築できるライブラリです。ApolloServerの[Get started]
(https://www.apollographql.com/docs/apollo-server/getting-started/)を参考にSetupしていきます。

- 新しいプロジェクト用フォルダ作成

```
mkdir graphql-server-example
cd graphql-server-example
```

- 新しいNode.jsプロジェクトをnpmで初期化

```
npm init --yes
```
- 実行結果

```
Wrote to /Users/i.kohei.noguchi/graphql-server-example/package.json:

{
  "name": "graphql-server-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

```

### 必要なライブラリをインストール
Apollo Serverを実行するアプリケーションには、```apollo-server```と```graphql```の2つをインストールする必要があります。

```
npm install apollo-server graphql
```
- 実行結果
 
```
added 113 packages, and audited 114 packages in 10s

3 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```
実行すると```node_modules```ディレクトリに内容が保存されます。
続いてプロジェクトのルートディレクトリに```index.js```を作成して以下を記述します。

``` index.js
const { ApolloServer, gql } = require('apollo-server');

const typeDefs = gql`
  type User {
    name: String
    age: String
    gender: String
  }

  type Query {
    users: [User]
  }
`;

const users = [
  {
    name: 'noguko',
    age: '28',
    gender: 'female'
  },
  {
    name: 'noguo',
    age: '30',
    gender: 'male'
  },
];

const resolvers = {
  Query: {
    users: () => users,
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});

```

### サーバーを起動
以下のコマンドでserverを起動します。

```
node index.js
```
すると以下が表示されるので```http://localhost:4000/```にアクセスします。

```
🚀 Server ready at http://localhost:4000/
```
![スクリーンショット 2022-01-16 16.47.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337961/7afe0cd4-07d7-0409-1d84-09a4ed0845be.png)
サーバーの起動成功です！
### クエリを実行する
ApolloSandboxを使ってクエリを実行していきます。
```Query your server```をクリックすると以下のページが表示されます。
![スクリーンショット 2022-01-17 13.48.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337961/24daadaf-44d2-f2fd-6f2d-1c4188008c85.png)

ページの左側がスキーマを検索できたり実行できるクエリの一覧を確認することができます。
中央がクエリを書くエディター部分で実行結果はその横の右側に表示されます。

続いて先程```index.js```に書いた部分のテストをします。
正常に動作するかクエリを書いて、レスポンスがあるか確認します。
GraphQLのクエリはルート型で決まります。
ルート型はQueryやMutation、Subscriptionなどデータソースに対する操作を表現する型です。
青色部分の```ExampleQuery```をクリックしてクエリを実行すると右側にレスポンスが返ってきます。

![スクリーンショット 2022-01-17 13.51.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2337961/0f8c34d7-02b6-abd7-f241-81b0f9686b8d.png)


今回の例ではUserというスキーマを定義してその下にデータソースを定義しています。
スキーマとはGraphQL APIの仕様を表現するもので、クライアントがクエリできるデータの構造を定義するためのものです。

```index.js
// スキーマの定義
const typeDefs = gql`
  type User {
    name: String
    age: String
    gender: String
  }

  type Query {
    users: [User]
  }
`;

// データソース
const users = [
  {
    name: 'noguko',
    age: '28',
    gender: 'female'
  },
  {
    name: 'noguo',
    age: '30',
    gender: 'male'
  },
];
```
上記ではスキーマとデータソースを定義しているだけで実際のデータ操作をするにはリゾルバーを作成する必要があります。↓

```index.js
// リゾルバ関数を定義してクエリ実行時のデータ操作を行う
const resolvers = {
  Query: {
    users: () => users,
  },
};
```
最後にクライアント側からクエリを実行することによってデータソースへのアクセスが可能になります。
GraphQLは必要なデータだけ取得することが可能です。
もし```name```の情報のみ欲しい場合は```age```と```gender```をクエリ部分から削除すれば```name```のデータのみ表示されます。

### おわりに
実際にGraphQLを動かしてみて今まで理解が曖昧だったクエリ言語やスキーマ言語、リゾルバーの意味と基本的な文法を理解できて少し前進できました。
また必要なデータだけをリクエストできるのは凄い便利だと感じました。GraphQLの技術を使いこなせるように今後もインプットとアウトプットを繰り返して行こうと思います。