フロントエンドエンジニアが GraphQL をキャッチアップするのに Hasura がいい感じだった件

# はじめに
自分はフロントエンドエンジニア2年目の者です。GraphQL を実務で使うことになったのでキャッチアップを行いました。その際 Hasura を使えば GraphQL サーバーを簡単に構築することができ、フロントエンドエンジニアが GraphQL をサクッとキャッチアップできるのかなと思ったのでこの度記事にまとめてみました。

## この記事で取り扱う内容 🙆‍♂️
- GraphQL の概要
- Hasura の概要
- Hasura を用いた GraphQL サーバーの構築手順と、クライアント側からデータの取得までの**ざっくりした**流れ
## この記事で触れないこと 🙅‍♂️
- Typescript や React の基本的な内容
- GraphQL クライアントライブラリの使い方

## 注意点🚨
- Applo Server とか Prisma などでも GraphQL サーバーを作れるのですが、自分は試してないので比較はしてません
- 実は GraphQL を実務で用いた経験は現時点（2022年10月22日）ではありません。。ですので実務で使用した際に 「もっとこういう方法でキャッチアップしておけばよかった」「Hasuraより ◯◯ の方がよかった」 などあれば随時加筆修正を行いますのでご了承ください。
# GraphQLついて
そもそも　GraphQL とは何なのでしょうか。以下は公式サイトを Deepl 翻訳したものになります。

> GraphQL は、API のためのクエリ言語であり、既存のデータを使ってクエリを実行するためのランタイムです。GraphQL は、API 内のデータについて完全で理解しやすい記述を提供し、クライアントに必要なものだけを要求する力を与え、時間の経過とともに API を進化させることを容易にし、強力な開発者ツールを可能にします。

参考: https://graphql.org/

わかるようなわからんようなといった感じだと思うので重要な概念をもう少し噛み砕いて説明してみます。

## APIのためのクエリ言語とは
クエリとは「問い合わせ」、「訪ねる」などの意味を持つ英単語のことです。SQLなどを使用されたことがある方はイメージしやすいと思います。下記の図をご覧いただければイメージしやすいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1741616/fd0c38f9-27ae-ba04-1933-be1a6987e5ac.png)
参考: https://www.netlify.com/blog/2020/01/21/advice-from-a-graphql-expert/

**データソースに対して問い合わせをするための言語**程度の認識があれば一旦大丈夫です。

## API 内のデータについて理解しやすい記述を提供

GraphQL では GraphQL スキーマというものを用いて APIのデータ仕様を記述することができます。

```graphql
type Book {
    id: ID!
    name: String
    pageCount: Int
    author: Author
}
```
上記の graphql ファイルでは スキーマ定義にてクライアントが操作できるクエリや様々な型を定義しています

実際のデータ操作を行うのが**リゾルバ**というものになります。リゾルバを使うことで、「**そのクエリが呼ばれた時にどのデータを返すか**」という紐付け情報を付与することができます。GraphQLサーバー開発者が提供します。以下は先ほどのファイルにリゾルバを追記したものです。

```graphql
type Book {
    id: ID
    name: String
    pageCount: Int
    author: Author
}

type Query {
    bookById(id: ID): Book
}
```

bookById というメソッドは id を引数にとり、Bookを返す関数になります。GraphQLスキーマとリゾルバーに関しては以下記事を読んでいただくとより詳細に理解できると思います。

https://graphql.org/learn/schema/

https://qiita.com/NagaokaKenichi/items/d341dc092012e05d6606

https://qiita.com/NagaokaKenichi/items/86272f2f654070b06488

https://zenn.dev/waddy/books/graphql-nestjs-nextjs-bootcamp/viewer/overview_from_backend#%E3%83%AA%E3%82%BE%E3%83%AB%E3%83%90%E3%82%92%E7%94%A8%E6%84%8F

## クライアントに必要なものだけを要求する力を与える
「データソースとやりとりをするだけなら REST でよくない？」と言いたくなりますが、GraphQLには「**必要なものだけを要求する**」という大きなメリットがあります。例えば、「苗字と名前だけを表示させるカード」を作るとします。（わかりやすくするために簡単な例にしています）

![スクリーンショット 2022-10-23 14.52.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1741616/4c1b1db4-d90c-603e-40c7-2e2b4cb0fbe6.png)

REST APIのエンドポイントとそのレスポンスを見てみましょう。名前を表示するために必要なデータは "firstName"と "lastName"だけですが、"hobby"や"birthday"など表示に必要でない値まで取得しています。このことを**オーバーフェッチ**と言います。

![スクリーンショット 2022-10-23 15.06.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1741616/cca72983-0055-08cc-ed61-d5f415f8a80e.png)


GraphQLを使えばREST API で問題とされていたオーバーフェッチを防ぐことができます。

![スクリーンショット 2022-10-23 15.14.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1741616/74eb213e-bb18-ec42-5298-9c1a5c8bdcb3.png)


## GraphQL でできることまとめ
- データソースとのやりとりができる
- APIのデータ仕様（実際にやり取りする値やメソッド）を記述することができる
- フロントエンド側でクエリを実行することでオーバーフェッチを抑えることができる

# サーバー構築するの面倒くさくない？
さあ、ここまでは GraphQL の概要について説明してきました。フロントエンドがGraphQLサーバーからデータを取得、表示するには 

- **クエリ**を投げる
- そのクエリを叩いた時に、どんなデータを返すかを**リゾルバ**を用いてデータ操作を行う

ということがわかりました。リゾルバを構築するには当然バックエンドの知識も必要になってきますが、「バックエンドの知識はあまりないから、もう少し簡単に GraphQL サーバーを構築できるものがないか」と考えていました。そこで見つけたのが Hasura です。

# Hasura とは
Hasura は PostgreSQL サーバーから**自動的に GraphQL サーバーを建てられるツール**のことです。以下の図を見てもらえるとわかりやすいですが、Hasura サーバーがクライアントと PostgreSQL サーバーの間に入り、GraphQL API で PostgreSQL を操作しているといえばイメージしやすいでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1741616/8f1f2890-0b7b-e2c9-dad1-45e9b29cfe94.png)
参考:https://hasura.io/

## GraphQLサーバーの構築まで
Hasura がどれくらい便利なのか、実際に見てもらった方が早いので GraphQLサーバーを構築までの流れを見てみましょう。詳細な使い方やコンソールのセットアップ手順は [公式チュートリアル](https://hasura.io/learn/ja/graphql/hasura/introduction/)がわかりやすいので、ここでは「こんな感じなんだな〜」と雰囲気だけ把握してもらえれば大丈夫です🙏

### テーブルの作成
Hasura のコンソールからテーブルを作成することができます。コンソール画面はこんな感じです。
![スクリーンショット 2022-10-23 10.28.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1741616/f14bd0bd-bfc5-ca0d-4cdf-df250e973014.png)

必要なプロパティやデフォルト値、Primary Key などを埋めていきます。

### 自動生成されたGraphQL API の確認
テーブルを作成するとあら不思議。GraphQL のAPI が作成されているではありませんか。

![スクリーンショット 2022-10-23 10.36.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1741616/6e38b24b-a7ca-8048-ebcd-4f8ce8cddb8b.png)

データベースのテーブルを定義するだけで、基本的なCRUDのGraphQLリゾルバを作成してくれました。複雑な処理が特になければリゾルバの実装工数はほぼゼロで開発することができます。

左のサイドバーにある Explorer をいじるとクエリを勝手に生成してくれて、[GraphiQL](https://qiita.com/NagaokaKenichi/items/f83148f4903b17d1d2f0#graphiql) 上で動作確認もできるので適当にいじって動作確認してみましょう。

![スクリーンショット 2022-10-23 10.49.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1741616/52cdb4f7-0458-ef6d-dc73-2a44bb2cdc92.png)

## クライアント側でデータを取得してみる

### データの手動生成
今度は GraphQL のAPIを用いてデータを取得してみます。事前にデータを作成しておきましょう。（本当は GraphQL で[Mutation](https://zenn.dev/offers/articles/20220609-graphql-onboarding#mutation) というものを用いてデータの作成が行えるのですが、説明が長くなりそうなので説明は割愛します）データの手動生成はコンソールの Insert Row から行えます。
![スクリーンショット 2022-10-23 10.58.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1741616/2f1f5c7f-aa53-e5a3-67bd-15c4435c52fe.png)

### Graph QL クライアントライブラリのインストール
Graph QL クライアントライブラリは Appolo Server、urql、Relay など色々ありますが、今回は urql を使用します。各々お好きなものをインストールしてお使いください。

```
npm install urql graphql
```

どのライブラリにも BaseURL と header を指定するオプションがあるので、Hasuraのコンソールに表示されていた GraphQL Endpoint と x-hasura-admin-secret を設定してください。

```tsx
const gqlClient = createClient({
  url: エンドポイント,
  fetchOptions: {
    headers: {
      'content-type': 'application/json',
      'x-hasura-admin-secret': シークレットキー,
    },
  },
});

root.render(
  <React.StrictMode>
    <Provider value={gqlClient}>
      <App />
    </Provider>
  </React.StrictMode>
);
```

Clientを利用するためには、Context APIを介してClientを提供しています。詳しくは[公式サイト](https://formidable.com/open-source/urql/docs/basics/react-preact/#providing-the-client)をご覧ください。

### データをフェッチしてみる
先ほど作成された全件取得のクエリを叩いてコンソールで表示してみましょう。

```tsx
const query = gql`
  query {
    posts {
      id
      title
      created_at
      content
    }
  }
`;

function App() {
  const [result] = useQuery({
    query: query,
  });
  const { data, fetching, error } = result;

  if (fetching) return <div>Loading...</div>;
  if (error) return <div>{error.message}</div>;

  console.log(data.posts);
  // 以下略
```
実際にブラウザで確認すると表示が確認できてると思います。もし無理だった場合は設定した URL や API key が正しいか確認してみてください。
 ![スクリーンショット 2022-10-23 14.23.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1741616/559f600b-843b-277e-4e04-80dc92890e58.png)

# 最後に
今回はフロントエンドエンジニアが GraphQL をキャッチアップするのに Hasura がいい感じだったので記事にまとめてみました。書き終えてから気づきましたが単にデータを取得して表示するだけなら[こういうの](https://www.apollographql.com/blog/community/backend/8-free-to-use-graphql-apis-for-your-projects-and-demos/)でも十分かもしれませんね。ただ HasuraだとCRDUなAPIも作れるので時間のある方は個人開発などで使用しながら GraphQLに慣れていくのもいいかもしれません。自分はサーバーサイドの開発経験が無く GraphQL サーバーやリゾルバを構築することへのハードルが高く感じてしまいました。Hasura はリゾルバを自動生成してくれサーバー実装の手間が省けるので、**フロントエンドエンジニアが GraphQL をサクッとキャッチアップする選択肢の1つ**としてオススメします。もっと「この方法使った方がキャッチアップ簡単だったよ！！」「ここの内容違うよ！！」などあればご指摘、ご意見いただけると幸いです🙇‍♂️