みんなFirebaseを使うけど、私がAmplifyを選ぶ理由

サーバーレスアーキテクチャを選ぶとき、候補には「AWS の Amplify」と「GCP の Firebase」という 2 つの選択肢があると思います。

しかし、私のまわりでは `Firebase` を使っていらっしゃる方が多いように感じます。
**なぜ`Amplify`ではないのでしょうか？**

たしかに学習コストが高い上に、着実に課金されます（笑） ※
ですが、かなり**柔軟性の高いアーキテクチャを組むことができる**のです！

Amplify に偏った立場で、推しポイントをお話しさせてください。
(導入記事にもきっとなるはずです)

…もしかして食わず嫌いをしているだけではないですか？
そんな方が、今日を境に Amplify にチャレンジくださると幸いです。

> ※課金はされますが、例の通り AWS は使った分だけにかかる方式なので
> 料金周りを調べて気を付けつつ使えば（Lambda 一回いくらか、Dynamo の更新がいくらか…など）そうそう高額にはならないと思っています。
>
> 私は Amplify で複数のサービスを開発してますが、月額 200 円にも満たない金額で開発できています。
> → 自己責任でお願いします 🤤

## 一般的なおすすめポイント

### 複数の環境（開発、本番）を手軽に作成できる

`Amplify` では、環境を分けて管理することが出来ます。
（フロントのホスティングサービスは、環境で分ける必要がないため別です…）

最初に`amplify init`というコマンドで、環境を作る時に環境名を設定します。
仮にここで`DEV`という名前で作ったとしましょう。

それ以降に追加されたリソース（例えば DB や Function など）は、**全て自動的にインフラ情報がテキストベースで管理**されます。
※インフラ情報とは … 例えば Function（Lambda）だと、メモリやアクセス権限などのこと

続いて本番環境を同様のアーキテクチャで作りたいと思ったときには、同様に`amplify init`を実行して
対話形式の中で「新たに環境を作成する」を選択すると、**`DEV`と全く同じインフラ情報の、新たなリソースが作成される**のです。

このリソースは、完全に別のもので
認証 DB や DB や Function など、全て開発環境と分けて使用することができるのです！

#### amplify init コマンド

コマンドの概要については後述しますが、この魔法のコマンドについてフォーカスして説明していきたいと思います。

`amplify init`を実行する目的は大きく 2 つあると思っています。

1. 新たに環境を作成して、接続しにいく
2. 既にある環境に、接続しに行く

先ほど説明した内容は 1 の半分で、環境を作成するところまででしたが
重要な点は、**「フロントからアクセスする環境を指定できる（接続する）」**ことなのです。

フロントのコードから Amplify で作成した環境内の**サービスにアクセスする際には、環境を意識することなくアクセス**することが出来ます。
ではアクセスする対象の環境情報はどこで持っているのでしょうか？

それが`amplify init`時に生成される、`aws-exports.js`というファイルなのです。
ここには例えば以下のような、環境に依存する情報が記載されます。

- 環境名を含んだリソースの ID
- リソースのリージョン
- API リソースのエンドポイント
- ...etc.

![amplifyInit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1156985/151344b2-096c-5845-a23d-a3a208e6f0a7.png)

`amplify init`を使用すれば、AWS アカウントを越えた移行もできそうです。
それぐらい強力なコマンドなのです！

### `Amplify CLI` でサクサク開発

この点はほぼほぼ `Firebase` と一緒です。
AWS のコンソールをいじらなくても、コマンドライン上からほとんどの操作をすることができます。

（先ほどの`amplify init`も `Amplify CLI` の一つです）

しかも他の様々なサービスとの連携も手軽に出来ます！

#### 『頻繁に使うコマンド一覧』

| コマンド                     | 説明                                                                                                               | 備考                              |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------ | --------------------------------- |
| **amplify init**             | 環境を作成する。フロントからアクセスする環境を選択する                                                             |
| **amplify {service} add**    | 使用する AWS サービスを新たに追加する                                                                              | 対話形式で多様な設定が可能        |
| **amplify {service} update** | 既に作成したリソースの設定を変更する                                                                               |
| **amplify push**             | ローカルでいじった設定、ファイルをリソースに反映させる                                                             | これをしないと一切反映されない    |
| **amplify publish**          | `amplify push`の実行 + フロントコードの build + ホスティングに反映                                                 | Git と CI/CD 連携してる場合は不要 |
| **amplify pull**             | 共同開発者などがリソースを更新して、ローカルのリソース管理ファイルと差分が出たときに、その差分をローカルに取り込む |
| **amplify status**           | ローカルのリソース管理ファイルと、リソースでど差分がある場所を確認                                                 |                                   |

※ 上記{service}には、auth / api / function...などが入ります。

ほぼほぼ git コマンドと似た感じなので、分かりやすいですね。

1. `amplify status`を実行して差分が無いか確認
2. 差分があれば...`amplify pull`でローカルに反映
3. もろもろ開発
4. → 1 → 2
5. `amplify push`でリソースに反映
6. → 1 に戻る

で進めると良さそうです。

#### 『連携できるサービス』

連携できるサービスは多岐に渡り、
よく使うモノとしては、以下のようなものがあります。

- API(GraphQL or REST)
- DB(DynamoDB or AuroraDB)
- Auth(Cognito) ※Google 認証など多様な認証方法があります
- Storage(S3)

連携した場合、フロントからアクセスする方法が非常に手軽なライブラリ(`aws-amplify`)も提供されています。
例えば、Storage を追加してフロントからファイルをアップロードする場合…以下のように書けば出来ます。

```js
import { Storage } from "aws-amplify";

const uploadFile = async (fileName, contents, contentType) => {
  try {
    const result = await Storage.put(fileName, contents, {
      contentType,
    });
    return result;
  } catch (err) {
    console.log(err);
  }
};
```

参考：[Amplify Docs](https://docs.amplify.aws/lib/storage/upload/q/platform/js/)

他にも、様々なサービスを手軽に利用することが出来ますので、是非試してみてくださいね！
（以下の例も一部です）

- [AI まわり](https://docs.amplify.aws/lib/predictions/intro/q/platform/js/)
  - 音声系：翻訳、テキスト ⇔ 音声
  - 画像系：オブジェクト検出、顔認識
  - テキスト：感情分析、構文解析
- [マップ](https://docs.amplify.aws/lib/geo/getting-started/q/platform/js/)
- [チャットボット](https://docs.amplify.aws/lib/interactions/getting-started/q/platform/js/)
- [既存の XR リソースの使用](https://docs.amplify.aws/lib/xr/getting-started/q/platform/js/)

## 私的おすすめポイント

私は GraphQL で開発するのが好みなのでその観点でおすすめしたいポイントをまとめます。

### GraphQL で開発しやすい

GraphQL の名前に圧倒されてブラウザバックする前に、メリットだけでも読んでいってほしいです！

スキーマと呼ばれるたった一つのファイル(schema.graphql)を書いていくだけで、
**「型定義」「データベース（DynamoDB）」「認証体系」**が整います。

実際に私が書いたコードから抜粋してご紹介します。

```graphql
type Folder @model @key(fields: ["id"]) @auth(rules: [{ allow: owner }]) {
  id: ID!
  name: String!
  description: String!
  type: String!
  childIds: [String]
  deleted: Boolean!
}
```

これを書いた後、`amplify push`コマンドを打つだけで…

- Dynamo で`[id, name, description, type, childIds, deleted, createdAt, updatedAt]`のテーブルが生成される
- このテーブルデータについての CRUD 操作が JS 上からできる
- ユーザーは自分が作成したデータのみに CRUD 操作ができる、という制限がかかっている

が出来上がります。

他にも、ユーザーグループ単位での制約をかけるなど、`@~~`による設定は非常に便利です！

### モック開発できる

この点は後述します。
(デメリット リソースを反映するのに時間がかかる)

### ローコードでサクサク開発できる（新機能 ✨）

この辺りは私もまだ検証中のため、今後使い勝手が良さそうであればどんどん記事で共有していこうと思います！

**『Amplify Studio』**

とうとう出ました！拡張性の高いローコードです。

AWS のノーコードと言えば`Honey Code`もありますが、これよりはエンジニアが拡張開発する余地が大きいのがメリットのようです。

- フロントエンド ... Figma で作成したデザインを元に、React のコードが生成されます。
- バックエンド ... ブラウザ上からユーザーフレンドリーな UI で DB 定義すると、GraphQL 周りのコードが生成されます。

※バックエンドは厳密には`Amplify Studio`に統合された`Amplify Admin UI`の機能です。

ただ、どの程度拡張開発できるのかは今後検証が必要です。
（ご存じの方がいれば、教えてください！）

参考：[Amplify Studio ドキュメント](https://docs.amplify.aws/console/)

## デメリット

### 時には、AWS のサービスの知識が必要

Amplify を使えば、様々なことができると分かったでしょう。

しかし、時には AWS のサービスの知識が求められる事もあります。
（以下は例のほんの一部です）

#### 例１）バッチ処理を作りたい

バッチで Lambda から DynamoDB を更新したいときには、「IAM ロール」と「AWS SDK を使った Dynamo の更新処理の書き方」を知っている必要があります。
※勿論この話は、Dynamo に限らず…です。

「IAM ロール」… あるサービス(Lambda)が別のサービス(Dynamo)にアクセスする権限を設定します
「AWS SDK」… AWS SDK は、ソースからリソースにアクセスする手段の一つで、多くの言語がサポートされています

[Dynamo に限って言えば、SDK 経由でなくてもこれでもいけます](https://zenn.dev/y_uuu/articles/ee18d2ff3404d9)

#### 例２）コンソール上から Lambda のソースを更新したい

Lambda は一定以上のソースサイズだと、コンソール上からソースをいじることが出来なくなります。
そのため、テストするには一々`amplify push`でリソースに反映させる必要があります。

ですが、Lambda レイヤーを知っていれば、Lambda 本体とは別にモジュールなどを管理できるので
本体のソースサイズを圧迫せずに済むのです。

→ これはサービスの知識が必要…というよりも、あるとスムーズという程度ですね。

#### 例３）Amplify の想定からはみ出る構成には CloudFormation のカスタムが必要

CloudFormation とは、サービスの構成情報を余すことなくテキストで書いたもので
AWS を良く知らない方がいじるのは、とても心労です。はい。（少なくとも私はあまり触りたくありません…）

例１で IAM ロールを変更する際などにも、これは非常に軽微ですが CloudFormation をいじることになります。

### リソースを反映するのに時間がかかる

ローカルのソース上で、Lambda の実行ファイルを書き換えたとき…どうやって動作確認するのでしょうか？

愚直にするならば、`amplify push`コマンドでリソースに反映させて実際に動かしてみる、ですかね。
ですが、Amplify の反映は少々…いえ、多少の時間（数分）が掛かってしまいます。

そこで便利なのが、amplify mock という機能で
一時的に『実際のリソース』ではなく、**『ローカルのソース』を元に諸々のサービスの動作をモック化**して、アプリの動作を確認できます。

※**aws-exports.js を通じてフロントから接続先のリソースを、ローカルリソースに置き換えてくれる**のです。

使ってみるなら、こちらの記事がステキです ✨
https://qiita.com/nagym/items/638974a3a5aaa63841c8
（ドキュメントは[こちら](https://docs.amplify.aws/cli/usage/mock/)）

ですが、mock 化を利用できるのは限られたサービスのみです…
API(GraphQL のみ...) / Lambda / Storage

---

今回は `Firebase` との比較も特にないまま、ひたすら Amplify について語ってきました。

デメリットを見て、少し自分には Amplify は早いかもな…と思われたかもしれませんが
まずは使って手軽さを実感してみてください！

小難しいことを知らなくても、**小さめのサービスから慣れていけば**
AWS の知識も少しずつ身について、今後のカスタマイズ性向上にも大いに活かせます！

`Amplify CLI` を使って構築していくのが、手軽かつカスタムしやすいですが
ハードルが高ければ`amplify studio`で Figma から変換するところからでも良いかもしれません。

本記事を通じて、少しでも Amplify に興味を持っていただければ幸いです！

それでは皆さんもよき Amplify ライフを～ 🐕