AWS Amplify + API gateway + Lambda + Dynamodb でシンプルなサーバレスWebアプリを作ってみた

AWSのお勉強、Webアプリのお勉強、その他もろもろを兼ねてサーバレスWebアプリを作ってみた。
アプリ自体は簡単なものなので、本記事ではAWSの構成を中心に記述する。

#　アプリ概要
フリー麻雀の成績、収支を管理するアプリ。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306681/4e30d3ca-4bcb-93a3-f257-778d694f25a7.png)

入力モードでは店舗名と着順（例：113234244）、収支を入力し、データベースに記録する。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306681/b7b79b9a-8d59-c59b-5258-e8d891c672ba.png)
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306681/928eb492-461f-52eb-12c9-f345f03cca14.png)
閲覧モードではこれまでの履歴を集計して平均順位やゲーム単価などを算出し、表示する。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306681/1e26dba9-cc66-3f31-92e5-fb646b464f88.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306681/ed780430-7a52-f6c0-c88e-a0eb2b81e31a.png)

これまでExcelで管理していたものを代替するような感じで作っている。
自分用に作っているので申し訳ないですが現物は公開できません。ごめんね。
将来的にはユーザー管理できるようにして公開とかするかもしれない。

# インフラ構成

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306681/1419033d-1201-9baa-c298-ffe04a1e5e9e.png)

Amplifyでフロント部分の構成を管理する。
といってもアプリ自体は基本的なHTMLとjavascriptだけの簡単なものなので、実質的にはS3の静的Webサイトホスティングを使っているだけに等しい。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306681/af6aa520-8545-0930-c1a3-be7e32b61826.png)
見ての通りとても簡単な構成。
概ねやっていることはこちらの記事と同じことである。

https://dev.classmethod.jp/articles/amplify-console-simple-static-site/

S3にHTMLとjsのファイル群を置いて、静的ファイルホスティングして、それにCloudfrontをつなげて、ということをやるだけだから、必ずしもAmplifyを使う必要はない。
だが、Amplifyを使えば**Gitのレポジトリを連携するだけでこれらを簡単に設定できる。**特にGitとの連携はCodebuildを使わないといけないし、別に細かいビルド作業をやるわけでもないのにそういう設定をいちいちやるのは大変面倒なので、その部分を簡単に繋ぎこんでくれるのはとても便利である。

バックエンドはAPI gatewayでLambda(python)に中継し、その中でDynamoDBに接続する。
本音を言えば**めちゃくちゃRelational Databaseを使いたい。どう考えてもアプリの内容的にDynamoDBではなくRDSを使うべきである。**でもRDSは常時起動しているとクソ高いので仕方なくDynamoDBを使用している。必要な時だけ起動するとかも面倒だし。
DynamoDBを使ったことでLambdaのロジック部分の記述が死ぬほど面倒なのでマジでつらい（SQL書きたい……）。ただ、コネクションに関してはboto3のお陰で超簡単に書けるのでその点はよかった。


# APIGatewayの管理 - プロキシ統合を使うかどうか
APIGatewayは、GUIベースで色々な設定を簡単に管理できるように見えるが、APIの数が増えると途端に管理がめちゃくちゃ面倒になる。GUIの宿命でもあるので仕方ないのだが……
特にAPI GatewayとLambdaを繋いで使用する場合、管理の仕方として大きく２つの選択肢がある。
#### ①プロキシ統合を使用せず、APIごとに別々のLambdaを用意し、パスの管理はAPI Gatewayで行う
今回採用した方法。APIGateway内に、API1個ごとにパスを振り分けてリソースを作っていく。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306681/a7d4313f-ac42-e318-5c6d-80286de1d7c1.png)
さらに、バックエンドにはAPIごとに別々のLambdaを配置する。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306681/c083da0f-e6bf-496b-b62e-0fc3e076f668.png)
今はまだAPIの数が少ないので全然管理できているが、これが何十個となったら死ぬほど面倒になることは明白である。
特に面倒なのが、現状ではリソースの複製やLambdaの複製などはコンソール上からできないので、いちいち同じ設定をしなければならないこと。また、Lambdaコードの管理もできていない。現状各関数をそのまま編集しているだけなので、管理とはほど遠い状態になってしまっている。

Serverless Frameworkを使えばこれらの問題を解決できるので、そのうち導入したいと考えている。
（ただ、これはこれでローカルでどのようにLambdaのテストをするかという問題はある）

#### ②プロキシ統合を使用して、一つのLambdaにAPIの全機能をまとめる
プロキシ統合を使えば、パスなどの情報もLambdaに渡すことができる。
①のようにパスをAPIGateway上で管理せず、Lambda側でパスに応じてメソッドを振り分けるようにすれば、APIGatewayのリソースも1つで済むし、Lambdaも1つで済む。
Lambdaが1つでいいのであればコード管理も簡単だし、Gitと連携すれば自動デプロイなどの設定も容易に出来るだろう。
また、API内でAPIを呼び出す（処理を共通化する）みたいな事をしたいのであれば②一択だと思う。現状はそこまで複雑なことをしていないので①でもまぁ間に合っている。

この形式のデメリットとしては、ローカルのテスト環境を整えてやらないとまともにbugfixが出来ないということ。さらに言えば、単にpythonが動くだけではなく、Lambda上で動く時の動作、DynamoDBと接続、さらにAPI Gatewayとの連携も再現できなければいけないので、環境構築のハードルもめちゃめちゃ高い。これが面倒すぎるという理由で今回は採用を見送った。

#まとめ
+ AWS Amplify 超便利～～～
+ API Gateway便利なようでいてめんどくせ～～～
+ サーバーレス安い～～～（今のところドメイン代以外1円もかかってない）
+ RDS使いて～～～