引越し業界初の新サービスを支えるフロントエンドの技術


この記事はエイチーム引越し侍 / エイチームコネクトの社員による、[Ateam Hikkoshi samurai Inc.× Ateam Connect Inc. Advent Calendar 2021](https://qiita.com/advent-calendar/2021/hikkoshizamurai-connect) 2日目の記事です。

**「引越し侍 ネット見積もりサービス」**

https://hikkoshizamurai.jp/moving

のβ版をリリースしました :tada:

昨日、 @sho-hata が
「引越し業界初の新サービスを支えるバックエンド技術」というのを投稿してくれたので、
であれば、フロントエンドも、、ということで @anneauがフロントについてお話させていただきます。

結構、チャレンジングな技術構成してるので、皆さんの参考になる部分もあるかと思い、
イケてるところとイケてないと思ってるところを書こうと思います。

## 技術構成

まず、全体の技術構成は図を見ていただければと思います。

![structure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136353/1039a7ff-ada7-bbf6-6ca2-8aa307e61977.png)

画像作成: @sho-hata 

フロントエンドに関係のある部分のみ解説します

### [Next.js](https://nextjs.org/)

フロントエンドの構築には[Next.js](https://nextjs.org/)を採用しました。
Next.jsの詳細は不要かと思いますので、内部構成のみお伝えします。

- SSRで実行
- データの取得はGraphQL
    - GraphQLクライアントには[React Relay](https://relay.dev/)を採用
- ユーザー認証にはFirebase Authentication
- リアルタイム性が問われるチャットにはFirestore

### [Hasura](https://hasura.io/)

あまり聞き慣れないかと思いますが、HasuraはGraphQL エンジンという役割を担っております。

![スクリーンショット 2021-11-30 18.34.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136353/738064bb-e0ef-aef4-2ecb-5f6e27024cec.png)

図のように、クライアントでGraphQLのクエリを定義し、Hasuraにリクエストを飛ばせば、自動的にSQLを作成し、データベースにクエリを走らせてくれます。

### [Firebase](https://firebase.google.com/)

ユーザー認証やチャットなどリアルタイム性が問われるところには、Firebaseを用いています。
Hasuraとも相性がよく、jwtでFirebase側のユーザー認証情報をHasura側で解釈することができます

## イケてるところ

### Next.js 採用による色々

普段開発してるとその恩恵が当たり前になりがちですが、

- DX向上
    - Fast Refresh
    - TypeScript Support
- UX向上
    - Image Optimization
- その他
    - SSR Support
    - API Routes

等々、Vercel teamの皆さん、本当にお世話になっています :bow:

### Hasura採用によるバックエンド工数削減

Next.js → Hasuraの通信にはGraphQLを用いています。
GraphQLでは、クライアントが望むデータをクライアント側に定義していくようになります。

```graphql
query {
  profile {
    id
    name
    avatar
  }
}
```

本来であれば、GraphQLサーバーの方で、このクエリを解釈し、SQLを発行する必要がありますが、
上で述べたとおり、これらは全てHasuraが担ってくれます。

![スクリーンショット 2021-11-30 18.34.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136353/738064bb-e0ef-aef4-2ecb-5f6e27024cec.png)

認証やパフォーマンスチューニングもHasuraがやってくれるため、基本的にバックエンドが不要となります。

:::note
GraphQLでは解決できないような複雑な処理は
HasuraからRest APIを呼び出せるようになっています。
僕たちのサービスでは、暗号化を必要とする部分や複雑なビジネスロジックはGolangに任せています
:::

### React Relay × Hasura 採用による型の安全性

API側のスキーマとTypeScriptの型定義をあわせるのは労力のいることかと思いますが、
現状、ほぼ0工数で実現することができています。

GraphQLのクライアントには、[React Relay](https://relay.dev/)を用いており、
Hasuraが出力してくれるGraphQLスキーマを[Relay Compiler](https://relay.dev/docs/guides/compiler/)にかませることで、
バックエンドとフロントエンドの型に一貫性をもたせることができています。

### Nx採用によるモノレポ化

Nxというのはフロントエンド特化のモノレポ管理ツールです。

:::note
モノレポとは?
複数のプロジェクトを一つのリポジトリで管理しようという概念で
GoogleやFacebook、Uberなど多くの企業が採用しているアーキテクチャです。
:::

- リソースの共通化
    - linterやbuilderの共通化
    - コンポーネントや処理の共通化
- ビルドスピード向上
    - 変更を加えていない部分はキャッシュすることでビルドスピードを上げる
- 依存関係の見える化

などメリットが多くあります。

#### 例) ユーザー、提携企業、社内を一つのリポジトリで管理

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136353/cee0448f-07ac-2f20-6e0e-3b13cb16df99.png)

このように一つのリポジトリで構成することでリソースの共通化がしやすくなります。

## イケてないと思ってるところ

### GraphQLによるフロントエンドのコード肥大化

GraphQLはクライアントから自由にデータを取り出せるというメリットがある一方、
パース処理などをクライアント側でする必要があります。

#### 例) TODOコンポーネント

```tsx
const STATUS = {
  1: '未着手',
  2: '着手中',
  3: '完了',
};

const query = graphql`
  query todoQuery on Todo {
    title
    status
    deadline
  }
`

const Todo: VFC = () => {
  const data = useQuery(query);
  return (
    <>
      <p>{data.title}</p>
      <p>{STATUS[data.status]}</p>
      <p>{dayjs(data.deadline).format('YYYY-MM-DD')}</p>
    </>
  );
}
```

バックエンドを介していれば、

- ステータスはバックエンド側で変換して、表示用に日本語をもらう
- 日付はフォーマットされたものを返してもらう

ということができますが、現状、これらがフロントの責務となってしまっています。

### Firebaseの処理をクライアントが担っていること

構成図を見てもらえればわかるかと思いますが、
現状、フロントから発生する通信がHasuraに一本化できておらず、Firebaseとも通信をしております
できる限り保守しやすい状態は保とうとしておりますが、フロントエンドが担っている責務が大きすぎるような気がしています。

![structure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136353/1039a7ff-ada7-bbf6-6ca2-8aa307e61977.png)

## 今後の展望

やりたいことは色々ありますが、まずはイケてないと思っているところで取り上げた、
「フロントエンドの肥大化」というところは解消していきたいと思っています。

世の中的にはBFFによる解決策が多いかと思いますが、
僕たちの場合、HasuraがBFFに近い動きをしてくれていますし、Nextjsのapi routesも一部使用しているため、少し冗長な気もしています。

引き続き議論は進めていきますが、少なくともFirebaseの処理はサーバーサイドに寄せていきたいと思っています。

## 明日

[Ateam Hikkoshi samurai Inc.× Ateam Connect Inc. Advent Calendar 2021](https://qiita.com/advent-calendar/2021/hikkoshizamurai-connect) 2日目の記事は、いかがでしたでしょうか。
明日は @ex_SOUL の投稿になります！お楽しみに！