Amplifyと約一年半向き合ってみて

この記事はAmplifyアドベントカレンダー21日目の記事です。

こんにちは！オンライン劇場ZAのUXエンジニアをしています、とうようです。

オンライン劇場ZAというのは昨年11月末に開設した、**オンライン演劇のためのプラットフォーム**です。自分はこのオンライン劇場ZAの立ち上げに学生エンジニアとして関わり、現在はそのまま副業として関わらせてもらっています。

そんなつい先日設立一周年を迎えたオンライン劇場ZAは、設立当初から**Amplify + Next.js**という技術スタックで作られています。今回の記事は、UXエンジニアという肩書きのもとフロントとバックエンド、どちらの実装にも関わってきた自分が開発開始からの約一年半を振り返ってAmplifyの良かったところ・いまいちだったところを書いていきたいと思います。
なお構成上、**技術の深いところまでは立ち入らず、ここまでのを経緯を振り返りながらそれぞれのトピックのさわりだけ触れる形**になっています。個別の詳細はもし機会があったら別途記事にしようと思うのでよろしくお願いします。また、似たような内容で今年の9月にAWSDevDayでも登壇しています。プレゼンと文章だとまとめ方も違ってきているので、こちらも参考にしていただければと思います。


<iframe width="560" height="315" src="https://www.youtube.com/embed/4wC7tlLHyYw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


## 最初の技術選定

2020年9月ごろから集められたメンバー。揃った後は早速技術選定から始まりました。基本的には先行して参加することになっていた現テクニカルディレクターが大枠を検討しており、AmplifyとNext.jsを使うことはかなり序盤に決定しました。フロントに関してはシニアレベルの方が参加していたため、自分が最初に関わったのはデータベース周りに関する検討です。
この時に、集まったメンバーが**テクニカルディレクター以外全員フロント**という特殊事情があったこと、フロントとして**TypeScriptでの開発**が決まっていたこと、あとは単純に自分の興味的なところもあってGraphQLをAppSyncで使おうという提案しました。
実際、遡ってみたらこんな形で提案していたみたいです。

> Amplifyからデフォルトで生成されるから参考資料が多いし、バックエンドはER図から型に落とし込めばあとはちょっとごにょごにょするだけで済むっぽいし新しい概念とはいってもどの型の何を取りたいのかさえわかってればすぐ書けるようになりそうだしAppSync使うとCognitoとの連携でアカウントの種別によって取れる情報の制限も簡単にできるみたいだから実装コスト結構下がりそう

ここでも少し触れているのですが、認証はAmplifyを使う関係上Cognitoになるため、その認証情報をいかに活用するかというところが肝になります。AppSync+GraphQLで**スキーマの設定ファイルにCognito認証によるアクセス制限の条件が書ける**ため、データベースのアクセスコントロールが技術選定で解決することができたのはかなり大きかったと思います。

## 自分が最初に立ち向かった認証の壁

最初に自分が担当したのは、ログイン・新規登録周りと全画面に共通するコンポーネントの作成でした。ログイン・新規登録はこの頃の資料だと少し厄介で、というのも、まだAmplifyが出始めの頃だったのであまり実プロダクトでの活用例が出ておらず、参考にできる記事は大抵デザインなどが作り込まれていないチュートリアルレベルのものが多かったからです。そのため、Amplifyが用意してくれているログイン・新規登録UIを使った認証はたくさん出てきたのですが、肝心の**見た目を公式コンポーネントを使わずに、処理だけAmplify+Cognitoを借りるといった使い方**の参考になるドキュメントがなかなか見つかりませんでした。

この理由から実装については苦戦する部分も多かったのですが、その中でも特に**登録認証メールのハンドリングが難しかった**です。登録が終わった後に即ログインさせたい、また想定ユーザー層的にリンクを踏むだけで認証が終わる形にしたいという要件だったのですが、そのような機能は用意されておらず、結果的に仕様・デザインを調整して、以下のような流れで落とし所を見出しました。

1. 登録認証メールを少し加工して、HTMLでもろもろをパラメータに含めたリンクを仕込む
1. リンクの飛び先では裏で登録認証をしつつ、ユーザー側にはパスワードだけ入力すれば通れる画面を用意しておく
1. そこで登録認証完了後にログイン処理を走らせることで見た目としては登録完了と同時にログインしているという状況を作る

結果こういう飛び技的ソリューションを使っていたため、SNS認証の部分は工数やスケジュール観点から断念しました。ですが、それでもここを乗り越えることで**Cognitoというセキュリティの後ろ盾と、比較的使いやすい登録UIの両方を得られた**のは良かったと思います。
実際の実装では全ページに共通するところにReactContext.Providerを仕込んで、そこ経由でフロント側に認証処理を共有するようにしました。こうすることで、**実装のしやすさは担保しながら、認証の細かいロジックを全てCognitoのライブラリに任せて安全性も担保しています**。
その際はこちらの記事を参考にしたので詳しくはリンク先を参考にしてください（その時出ていた、ほぼ唯一のAmplify-UIを使わない記事です）

- [AWS Amplify での Cognito アクセスは React Context.Provider を使って認証処理を Hooks 化しよう](https://qiita.com/G-awa/items/99cb84c62fcd113943a6)

## 中間サーバー役のLambda関数

認証まわり・共通コンポーネントの実装を終えた自分は、続いて決済部分を担当することになりました。この段階ではStripeによるクレカ決済のみ対応する予定でした。単純に実装すること自体はそこまで大変ではないのですが、Stripeを安全に使うためには中間サーバー的なAPIを用意する必要があります。多くの記事ではここもNext.jsのAPI作成機能でまかなっていることが多かったのですが、その頃AmplifyはSSR対応も出来たてであまりサーバー上で常に動かしておくといった使い方はできなかったのでここをLambdaに寄せることにしました。

LambdaにはLambdaなりのクセみたいなものもあったのですが、Amplify側から設定することで**バックエンドの環境ごとに同じLambdaを作れる**というのは魅力でした。また、Amplifyから作れる＝ローカルで開発できるということでもあるので、**普段慣れたエディタでLambda関数を書ける**というのもいいところだったと思います。結果としてその後増えたコンビニ決済や、メールの送信、問い合わせなどさまざまなニーズにこのLambda関数機能が使われることになりました。

## 公演演出という実装

2020年11月末、ついにリリースされた後は公演の演出実装との戦いになります。柿落としとなった「[それでも笑えれば](https://no.meets.ltd/soredemo/)」では独自チャット機能もリリースすることになりました。映像を配信しながら、オリジナルのチャットを提供するというのはなかなかにさまざまな観点で小規模チームにとっては難しい試みでしたが、AmplifyとGraphQLのおかげで無事提供できただけでなく、**チャット内に演出を組み込むという試みも後半の公演では実現することができました**。
この戦いの中では、**Amplifyのバックエンド環境を複数用意できる機能が役に立ちました**。元々はPull Requestごとに環境を立ち上げる機能なども活用しようとしていたのですが、そちらは**PRの数だけバックエンド環境が構築されてしまい管理コストがバカにならなかった**ため諦めました。でも最小限の環境はしっかり検証用に用意しておくことで、**影響の大きいバックエンド側の変更・さっと確認したいフロントエンド側の変更が本番環境と関係なく検証できた**ことで、安心して公演本番に向かうことができました。

その後の公演でも、スタンプ機能であったり、公演ページに入る際のローディング、文字化け演出などさまざまなオンラインならではの演出にチャレンジしてきました。これだけ色々してしまうとその実装コストも相当なものになりそうですが、**GraphQLのsubscription機能を活用することでフロント側の実装に集中でき、数々の演出を実現することができました**。

ちなみに公演実装中に使った技術としてこんな記事も書いています。Amplifyとは関係ないですが、興味があればぜひ。

- [p5.js×Next.js×TypeScriptを動かしてみる](https://qiita.com/touyoubuntu/items/f1051ad66520a13274a1)

## Amplifyアップデートの罠

しばらく公演が落ち着くとZAは定常改善に入るのですが、そんな中ネックになったのはAmplifyアップデートに対するところでした。例えばNext.js v11対応が発表された直後、アップデートが問題ないか試すために本番とは別環境でNext.js v11を試していた時に起こった問題がありました。どういうことかというと、その操作を行なった後に環境変数がテスト環境側に固定されてしまうというバグを踏み抜いてしまい、AWS側でも起票してもらいながら緊急対応をするということがあったのです。このようにAmplify側はまだまだ激しく開発が動いているので、**最新のものに単純に飛びついてしまうと、簡単には気付けないバグを踏み抜く**ということがあります。

ですが一方で、そういったところにも大胆かつ慎重に挑戦していくことで、**以前できなかったことがAmplifyの進化とともに実現できるようになっていく**というのは一つAmplifyに向き合う中で楽しいところでもあると思いました。実際に実現方法に悩みつつも、SSRの動作が安定してきたことで実現した動的なOGP機能に関しては以下にまとめています。

- [Amplify + Next.jsでフロントから登録した画像で動的にOGPする](https://qiita.com/touyoubuntu/items/039829405d39a1f3f8fc)

リリース前ほどユーザーに直接繋がるところのアップデートにAmplify自体が関わってくることは少なくなってきましたが、これからもその楽しさは忘れずに細かいところを徐々に進化させていこうと考えています。

## まとめ

各話題のさわり、特にAmplifyが関わる部分の話に限定したので思いのほかあっさりした記事になってしまいましたが、この記事で少しでもAmplifyでサービス運営をするということに関して伝わることがあれば幸いです。
この中でも随所で触れてきた通りAmplifyは、まだまだ進化の途上にある技術です。[2020年のAmplify進化の軌跡](https://qiita.com/yshd/items/69012f7a610edda4cdfc)という記事を見ると、一年前はこれすらなかったのか、みたいな気持ちになる方も多いのではないでしょうか。

そして今年は、**Next.jsへの追従や、ISRの対応（既存のAmplifyプロジェクトで有効にするのはまだできてませんが）、Amplify Studio周りの発表**などどんどんと簡単に協力なWebアプリが作れるような発表がされてきました。正直なところ最後の節で述べた通り、まだまだそれに**単純に追従するには安定しない部分が多いことから、全てをすぐに試せるわけではありません**。それでもこの進化は、否応無しにAmplifyでサービス開発をしている人たちをワクワクさせるものばかりだったのではないでしょうか。

今後もAmplifyと共にZAを進化させていこうと思った年末でした。

おしまい。