GraphQLの設定方法(Nest.jsで解説)

# GraphQLとは
***WebAPIのクエリ言語***です。

# GraphQLの公式ドキュメント

https://graphql.org/

### APIとは
以下の動画を見てみてください。

[APIとは？仕組みや種類などを初心者向けに解説【APIプログラミング入門】](https://www.youtube.com/watch?v=4inw0dmOHXs&t=53s)

# どういう現場で使われているか？
有名な企業で言うと***メルカリさん***などです。

[GraphQL | メルカリエンジニアリングブログ](https://engineering.mercari.com/blog/tag/graphql/)

あとはGo、Next.js、GraphQL、MicroService、k8sを使っているような***モダンな最先端の技術を使っている会社***でもよく使われています。


### クエリとは
***問い合わせをするための言語***です。つまり***APIへの問い合わせ言語***です。
APIにこういうふうに動けーというように指示するよう言語のイメージです。

# RESTAPIとGraphQLの違い


# RESTAPIの問題点
1.***システムが大きくなってくるとエンドポイントが大量に作成されてしまう***。

Swaggerとかを用意したりしないとAPIの仕様がわからなくなりなってしまったりします。💦

https://qiita.com/Hashimoto-Noriaki/items/8695e6c290519f3d7670

2.***特定のデータを取ってくることができない(不要なデータの取得)***

# GraphQLのメリット
1.***GraphQL***
```/graphql```という***エンドポイント1つだけでいろんな情報を取ってくることができる***

2.***余計なデータを取ってくる必要がない***

3.***型指定でデータがわかりやすくなる***

# GraphQLの課題(デメリット)
1.***まだメジャーではないので、情報が少ないので学習コストが高く、採用コストも高い***

2.***サーバー側の不可予測が難しい***

3.***キャッシュが複雑になる***

# GraphQLスキーマ
***GraphQLのAPIの仕様書***です。***GraphQL Schema Languageという独自言語を使用***します。
データを使うには```リゾルバーを実装```する必要があります。


### オブジェクト型
メインの型です。

```graphql
type User {
  id: ID!
  name: String!
  age: Int
  email: String
}
```


他にも```スカラー型```、```リスト型```、```Query型```、```Mutation型```列挙型、ユニオン型などもあります。それぞれ調べてみてください。

# Nest.jsでGraphQLを扱うには
以下の2点があります。

- ```スキーマファースト```
***GraphQLスキーマファイルを先に定義し、スキーマからコードを書いて開発***していきます。大規模なバック、フロントを分けて開発する時に向いています。あとGraphQL Schema Languageはキャッチアップが難しくデメリットがあります。

https://docs.nestjs.com/graphql/quick-start#schema-first

- ```コードファースト```
***GraphQLスキーマファイルを先に定義しない***です。フロント側は、バックエンドによって作られたスキーマを参考に開発していきます。コードとスキーマをいつも一致させる必要ないです。
小規模なスピード感がある開発向きです。GraphQL初学者はこっちが良さそうです。

# GraphQLの導入(Nest.js)
まずはNest.jsの新規作成からです。
```
nest new graphql-sample
cd graphql-sample
```

### インストール
公式ドキュメントからnest.jsのディレクトリでインストールしてください。

https://docs.nestjs.com/graphql/quick-start#installation

公式ドキュメントとは少し違いますが、以下のコマンドを今回は使用します。
```
npm install @nestjs/graphql @nestjs/apollo apollo-server-express graphql
```
まずは以下を実装します。
```src/app.module.ts
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { join } from 'path';
import { UserModule } from './user/user.module'; // UserModuleをインポート

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      autoSchemaFile: join(process.cwd(), 'src/schema.gql'), // スキーマファイルを自動生成
      playground: true, // GraphQL Playgroundを有効にする
    }),
    UserModule, // UserModuleをインポート
  ],
})
export class AppModule {}
```
⚫︎補足
```autoSchemaFile```は***trueにすると自動生成されたスキーマがメモリに保存***されます。

### リゾルバーとデータモデルを作成
```GraphQLの型定義(DTO)```を作成します。

``` src/user/user.model.ts
import { Field, ObjectType, Int } from '@nestjs/graphql';

@ObjectType()
export class User {
  @Field(() => Int)
  id: number;

  @Field()
  name: string;

  @Field()
  email: string;
}
```
GraphQLの***クエリやミューテーションを処理***するための```リゾルバーを定義```します。
```src/user/user.resolver.ts
import { Resolver, Query } from '@nestjs/graphql';
import { User } from './user.model';

@Resolver(() => User)
export class UserResolver {
  @Query(() => [User])
  getUsers(): User[] {
    return [
      { id: 1, name: 'Messi', email: 'Messi@example.com' },
      { id: 2, name: '大谷', email: 'Ohtai@example.com' },
    ];
  }
}
```
### モジュールに登録
***リゾルバーとデータモデル***を***モジュールに登録***します。
```src/user/user.module.ts
import { Module } from '@nestjs/common';
import { UserResolver } from './user.resolver';

@Module({
  providers: [UserResolver],
})
export class UserModule {}
```

### AppModuleにモジュールをインポート
```src/app.module.ts
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { join } from 'path';
import { UserModule } from './user/user.module';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
    }),
    UserModule,
  ],
})
export class AppModule {}
```

### サーバーを起動してplaygroundを確認する
以下のコマンドでサーバーを起動します。
```
npm run start:dev
```
- http://localhost:3000/graphql
でplaygroundを使えるようになります。(もうすでに自分は他のデータを取得したりしているのでごちゃごちゃして申し訳ないです🙇‍♂️)

![スクリーンショット 2024-11-17 6.22.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748789/d78573c2-0d21-d56f-4a43-0e3e4c8d9f83.png)

### playgroundの使用方法
playgroundを開いたら下のクエリを実行します。
```
query {
  getUsers {
    id
    name
    email
  }
}
```
すると以下のデータが取得できます。
```
{
  "data": {
    "getUsers": [
      {
        "id": 1,
        "name": "Messi",
        "email": "Messi@example.com"
      },
      {
        "id": 2,
        "name": "大谷",
        "email": "Ohtai@example.com"
      }
    ]
  }
}
```
![スクリーンショット 2024-11-17 6.26.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748789/aa5f1095-6449-659a-69f5-5e5ce276ef75.png)


# Diniiが使っている構成
どういう現場で使われているか以下の動画で確認してください。

https://qiita.com/Hashimoto-Noriaki/items/791de3398c8f1346f1c7

# 参考資料

[誰でも理解できるGraphQL入門！REST APIとの違いを分かりやすく解説【ハンズオン形式】](https://www.youtube.com/watch?v=u8vD2NESjC0)

https://www.udemy.com/course/nestjs-react-graphql/?srsltid=AfmBOorpM_sZefIqTdMnY3G8PxhiLYpUpG3f0I2qv_fw4I_3w2YRUO0h&couponCode=KEEPLEARNING

https://qiita.com/kim_t0814/items/c6ef7e3c668007f920a6