Apollo+Expressで始めるGraphQL超入門 ~ GraphQLをざっくり理解する

# はじめに

GraphQL超"ど初心者"である私は、

「`GraphQL` とはSQLのAPI版である」

と、小並感あふれる解釈しか持ち合わせていませんでした。

そんな私が実際に `GraphQL` に触れてみて

**「GraphQL 完全に理解した」**

となるまでの流れを共有できればと思います。

*※ 筆者はまだまだ初心者です。間違った解釈などがあればご指摘お願いします。*

# 環境を構築する

## インストール

以下のパッケージをインストールします。
詳細は各リンクで確認してください。

- [express](https://expressjs.com/ja/)
- [apollo-server-express](https://github.com/apollographql/apollo-server/tree/master/packages/apollo-server-express)
- [graphql](https://graphql.org/learn/)

```console
$ npm i --save express apollo-server-express graphql
```

## コードを書く

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

// Construct a schema, using GraphQL schema language
const typeDefs = gql`
  type Query {
    hello: String
  }
`;

// Provide resolver functions for your schema fields
const resolvers = {
  Query: {
    hello: () => 'Hello world!',
  },
};

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

const app = express();
server.applyMiddleware({ app });

app.listen({ port: 4000 }, () =>
  console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
);
```

## 実行

```console
$ node app.js
```

正しく実行できたら以下のテキストがでます

```console
🚀 Server ready at http://localhost:4000/graphql
```

`http://localhost:4000/graphql` にアクセスしてみましょう。

<img width="1150" alt="スクリーンショット 2019-04-11 15.24.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/211318/44a01694-2f55-2fd9-7ee1-51c39f1fda32.png">

この画面になればOKです。

# GraphQLを書く

## Hello World

`http://localhost:4000/graphql` の画面左部分に以下のコードを書いてみましょう。

```graphql
{
  hello
}
```

<img width="1150" alt="スクリーンショット 2019-04-11 15.27.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/211318/034eac4b-f968-d6bd-12fc-3be6fd8074a4.png">

初めてGraphQLを動かすことができました！

## データを自分で作る

GraphQLで扱うためのデータを用意しましょう。
オブジェクトで大丈夫なので適当に作ってみましょう。

オブジェクトが持つキーは
`id` `name` `age` `created_date` です。

```js:users.js
exports.users = [
  {
    id: 1,
    name: 'Zonomaa',
    age: 25,
    created_date: '2019-04-05 01:35:25.000'
  },
  {
    id: 2,
    name: 'Masa',
    age: 28,
    created_date: '2019-04-10 08:23:51.000'
  },
  {
    id: 3,
    name: 'Ms',
    age: 30,
    created_date: '2019-04-10 08:32:09.000'
  }
  // ... 適当にいくつか作ってみましょう
];
```

`users.js` という別ファイルに記述して保存します。
app.jsのあたまに読み込んでおきましょう。

```diff:app.js
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
+ const { users } = require('./users');
```

## スキーマを定義する

GraphQLでは扱うデータがどういう構造なのか、細かく記述していきます。
詳しい詳細は省きますが、参照する際は[こちら](https://employment.en-japan.com/engineerhub/entry/2018/12/26/103000#%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%9E%E8%A8%80%E8%AA%9E---GraphQL%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88-%E3%81%9D%E3%81%AE1) などを参照されるといいかもしれません。

先程 `Users` を作成したので、その型を宣言していきましょう。

```js
type User {
  id: Int
  name: String
  age: Int
  created_date: String
}
```

`app.js` の `typeDefs` に追記しましょう。

```diff:app.js
// Construct a schema, using GraphQL schema language
const typeDefs = gql`
+ type User {
+   id: Int
+   name: String
+   age: Int
+   created_date: String
+ }
  type Query {
    hello: String
  }
`;
```

この段階では型の定義をしただけなので、取得することはできません。
取得できるようにするために`Query`も定義しましょう。

helloはもう不要なので、削除します。

```diff:app.js
const typeDefs = gql`
  type User {
    id: Int
    name: String
    age: Int
    created_date: String
  }
  type Query {
-   hello: String
+   users: [User]
  }
`;
```

`Query` を定義できました。
やっとこれでUsersを取得でき………ません！

## 取得するためのロジックを書く

GraphQLを学ぶ上で一番ビックリしたことなんですが、 **取得ロジックは自分で書きます。**

`app.js` の中層にある `resolvers`
ここに `Query` で定義したキーで関数を作ります。

```diff:app.js
const resolvers = {
  Query: {
-   hello: () => 'Hello world!',
+   users: () => users
  },
};
```

`Users` を返却するロジックを書きました。

ここまで書いて初めて `Users` を **GraphQLから取得することができます。**

※ コードの書き足しを行ったらnodeタスクを再起動してください

```console
$ node app.js
```

## Usersを取得する

クエリを書いて実行してみましょう。

```
{
  users {
    id
    name
  }
}
```

`Users` から `id` と `name` を取得するという意味になります。

<img width="1147" alt="スクリーンショット 2019-04-11 16.05.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/211318/3265abf0-1d25-de97-4f90-f84810427a05.png">

**取得できました！！！！**

## GraphQLのざっくり解釈がわかった

実際に触ってみるまで私は、GraphQLは検索エンジンを搭載していて型を定義してあげればいい感じに検索してくれるものだと思っていました。
しかし、動かしてみると全くの勘違いであるとわかりました。
お恥ずかしい限りです…

私の中のGraphQLの解釈が

`GraphQLとは、検索エンジンを積んだいい感じにデータ取得できるやつ`

から

`GraphQLとは、APIの新しいフレームワークであり、取得ロジックは頑張らないといけないやつ`

という解釈に変わりました。

GraphQL... 思ったより泥臭いんですね…

## さまざまなデータストアを選択できる

MySQLやFireStoreなど、データストアとしてGraphQLと連携して取得することができます。
今回はjsのオブジェクトをデータストアとしましたが、
取得ロジックさえ書いてしまえばどんなデータでも取得できるようになります。

GraphQLについて調べているときに
`GraphQLは様々なデータストアとリンクさせることができます。`
的な紹介文をいくつか見ましたが、そういうことだったのかと…

# まとめ

GraphQLの凄さを理解しました。
REST APIとは全く異なるもので汎用性も理解できた気がします。

しかし、GraphQLのスキーマ言語は数多くの種類があり、その理解にはかなり勉強しないといけないと言う感じ…
次回は実践的なデータ取得操作などの実装を進めていこうと思います。

GraphQLマスターへの道程は長い。

Next → [Apollo+Expressで始めるGraphQL超入門 ~ データ取得Lv1](https://qiita.com/zonomaa/items/69bedaae8208d8abc437)