GraphQL (Flutter Roadmap GraphQL)

## はじめに
Flutterを網羅的に学習するにあたって[Roadmap](https://roadmap.sh/flutter)を使って学習を進めることにしました。

この記事では、Flutter初学者やこれからFlutterを学習し始める方に向けて、**GraphQL**についてまとめています。

RoadmapはFlutterだけでなく、他の言語やスキルのロードマップも提供されており、何から学習して良いか分からないと悩んでいる方にとって有用なサイトになっています。
ぜひ[Roadmap](https://roadmap.sh/)を利用して学習してみてください。

## Roadmapとは

簡潔に言えば、Roadmap.shは学習者にとっての**ガイドブック**であり、**学習の方向性を提供する学習ロードマップサイト**です。

初心者から上級者まで、ステップバイステップでスキルを習得するための情報が提供されています。

学習の進め方が分かりやすく示されているだけでなく、個々の項目に参考資料やリソースへのリンクも提供されているので、学習者は目標を設定し、自分自身のペースで学習を進めることができます。

## GraphQL
FlutterロードマップGraphQLでは以下の２つのサイトが紹介されています。興味のある方はぜひお読みください。

- GraphQL official website: https://graphql.org/: 
- How to GraphQL : https://www.howtographql.com/

## GraphQLとは
**GraphQL**（Graph Query Language）とは、データ操作をするためのクエリ[^1]言語で、サーバーサイドのAPIを操作するために使用されます。GraphQLはFacebook社(現 Meta社)によって開発されました。さまざまなOSに対応しており、クロスプラットフォーム開発が可能です。

GraphQLの特徴として、呼び出すエンドポイントが1つであること、1回のリクエストで複数のリソースにアクセスが可能であること、セキュアな開発ができることなどが挙げられます。

### REST SQL GraphQLの処理表
||Rest|SQL|GraphQL|
|---|---|---|---|
|データ取得|GET|Select|Query|
|データ作成|	POST|	Create|	Mutation|
|データ更新|	PATCH|	Update|	Mutation|
|データ削除|	DELETE|	Delete|	Mutation|
|イベント監視|	-|-|Subscription|

## GraphQLの基本

### １. クエリ（Query）
クライアントがデータを取得するために使用するもので、要求するデータを記述します。クエリはRESTのエンドポイントとは異なり、必要なデータのフィールドを指定できます。

#### クエリの特徴
- フィールド: クエリはフィールドを使用してデータを指定します。各フィールドは取得したいデータを指定します。

- 引数: クエリ内のフィールドに引数を渡すことができます。引数はフィールドの取得条件を指定するのに使用します。

- ネスト: クエリはネストでき、関連するデータをまとめて取得できます。

```graphql: GraphQLクエリの例
query {
  getUser(id: "123") {
    username
    email
  }
}
```

- `query`: クエリの種類を指定します。上記の場合、データを取得するためのクエリです。

- `getUser(id: "123")`: `getUser`というフィールド指定しています。このフィールドは引数`id`を持っており、値が`"123"`であるユーザーの情報を取得します。

- `username`, `email`: `getUser`フィールドの中にネストされているフィールドです。これらのフィールドは、ユーザの名前とメールアドレスを取得するために使用されます。

上記のクエリを実行すると、サーバーは指定したユーザーの名前と電子メールアドレスを返します。GraqhQLの最大の機能の一つは、クライアントが必要なデータを指定できることです。このため、不要なデータが取得されることはありません。

### 2. ミューテーション（Mutation）
データを変更するために使用されます。ミューテーションはデータの作成、更新、削除などの操作を実行するためのクエリタイプです。

#### ミューテーションの特徴
- ミューテーション名: ミューテーションは名前を持つことができ、クライアントが実行したい具体的な操作を指定します。

- 引数: ミューテーションには、実行に必要な引数を指定することができます。指定した引数は実行する処理内で使用することができます。

```graphql: GraphQLミューテーションの例
mutation {
  createUser(username: "newuser", email: "newuser@example.com") {
    id
    username
    email
  }
}
```

- `mutation`: クエリの種類を指定します。上記の場合、ミューテーションを実行するためのクエリです。

- `createUser(username: "newuser", email: "newuser@example.com")`: `createUser`というミューテーションを指定しています。このミューテーションは`username`と`email`の引数を使用して、新しいユーザーを作成します。

- `id`, `username`, `email`: ミューテーションの結果として、作成されたユーザーの情報を取得するために使用されるフィールドです。

上記のミューテーションを実行すると、サーバーは新しいユーザーを作成し、そのユーザーの情報を返します。

### 3. フラグメント（Fragment）
フラグメントは、クエリ内で再利用可能なフィールドセットを定義するための機能です。フラグメントを使用すると、同じフィールドセットを複数のクエリで簡潔に指定でき、クエリの再利用性と可読性が向上します

#### フラグメントの特徴
- フラグメント名: フラグメントは名前を持つことができ、再利用するフィールドセットに識別名を付けることで使用します。

- ターゲットタイプ: ターゲットタイプは、フラグメントがどのデータ型のフィールドセットとして利用できるかを指定します。

```graphql: GraphQLフラグメントの例
# ユーザー情報を再利用するためのフラグメント
fragment UserInfoFragment on User {
  id
  username
  email
}

# フラグメントを使用してユーザー情報を取得
query GetUserProfile {
  getUser(id: "123") {
    ...UserInfoFragment
  }
}

# 別のクエリで同じフラグメントを再利用
query GetAnotherUserProfile {
  getUser(id: "456") {
    ...UserInfoFragment
  }
}

```

- `UserInfoFragment`: フラグメントの名前であり、`User`タイプに関連付けられています。このフラグメントは `id`、`username`、`email`のフィールドを指定しています。

- `GetUserProfile`クエリ: フラグメント`UserInfoFragment`を使用して、`getUser`フィールド内でユーザー情報を取得します。

- `GetAnotherUserProfile`クエリ: 同じフラグメント`UserInfoFragment`を再利用して、別のユーザーの情報を取得します。

フラグメントを使用することで、同じフィールドセットを繰り返し記述する必要がなくなり、クエリの可読性が向上します。また、変更が必要な場合、フラグメントの定義を変更するだけで複数のクエリに変更が反映されるため、保守性も高めることができます。

### 4. スキーマ（Schema）
GraphQL APIはスキーマで定義されます。スキーマは、データの型やクエリ、ミューテーションなどの要素を定義することができるため、クライアントがどのようなデータを要求できるかを決定させるGraphQLの中心的な要素になります。

以下のスキーマは、ユーザーに関するデータ型(Type)、データの取得に使用するクエリ、新しいユーザーを作成するためのミューテーションを定義しています。

GraphQLスキーマは、クライアントとサーバー間でデータの要求と提供を行う際に使用されます。クライアントはスキーマを参照して、どのデータを要求できるかを理解し、サーバーはスキーマを使用してクエリの解析と処理を行います。これによって、クライアントとサーバー間のデータ取引が実現されるのです。

```graphql: GraphQLスキーマの例
type User {
  id: ID!
  username: String!
  email: String!
}

type Query {
  getUser(id: ID!): User
  getAllUsers: [User]
}

type Mutation {
  createUser(username: String!, email: String!): User
}

```


## GraphQLの利点

GraphQLは、特に複雑なデータ要求が必要な場合や、モバイルアプリケーションのAPI設計において非常に便利です。以下はGraphQLの利点です。

- ネットワーク効率性: クライアントは必要なデータのみを要求できるため、過剰なデータ取得を減らすことができます。

- クライアントの柔軟性: クライアントは必要なデータを指定できるため、開発者の実装が容易になります。

- 一度のリクエスト: 複数のデータ要求を一つのクエリで結合できるため、多くのデータを一度に取得できます。

## まとめ
GraphQLは、データ操作を行うためのクエリ言語で、サーバーサイドのAPIを操作するために使用されます。

- クエリ: クライアントがデータを取得するために使用するもので、必要なデータを指定します。RESTと異なり、必要なデータのフィールドのみを指定できます。

- ミューテーション: データを変更するために使用され、データの作成、更新、削除などの操作を実行します。

- フラグメント: クエリ内で再利用可能なフィールドセットを定義し、同じフィールドセットを複数のクエリで簡潔に指定できます。

- スキーマ: GraphQL APIの設計や定義を示し、データ型、クエリ、ミューテーションなどを定義します。

上記の特徴からもわかるように、GraphQLは特に複雑なデータ要求が必要な場合やモバイルアプリケーションのAPI設計に適しています。今回はGraphQLの基礎的な書き方についてまとめてみましたが、今回説明した以外にもたくさんの機能があるので、興味のある方はより実践的な内容を学習してみてください。

## 参考資料

https://udemy.benesse.co.jp/development/system/graphql.html

https://www.profuture.co.jp/mk/column/27360

https://zenn.dev/overflow_offers/articles/20220609-graphql-onboarding


[^1]: **クエリ**
データベースに対してデータの検索などの処理を求める命令文のことです。
[こちら](https://wa3.i-3-i.info/word136.html)にわかりやすい記事があったので、是非読んでみてください。