API Gateway + Lambda + DynamoDB サーバレスWebAPI開発まとめ

#はじめに
スマホアプリのバックエンドとしてAWSの「API Gateway + Lambda + DynamoDB」でサーバレスなWebAPIを開発しました。
![スクリーンショット 2020-10-20 22.19.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410068/512b85f4-02d6-a872-2f9a-d83d517d037c.png)
現在、開発環境と本番環境を運用しています。
「API Gateway + Lambda + DynamoDB」の構築手法はたくさん紹介されていますが、知識ゼロの状態から構築するのは難しく、時間がかかりました。
この記事では[API Gateway](https://aws.amazon.com/jp/api-gateway/)、[Lambda](https://aws.amazon.com/jp/lambda/)、[DynamoDB](https://aws.amazon.com/jp/dynamodb/)それぞれの概要と、私がサーバレスWebAPIを構築する上で参考になった記事を紹介します。

#API Gateway + Lambda + DynamoDB
とりあえず「API Gateway + Lambda + DynamoDB」の構成でWebAPIを開発する際には以下が参考になると思います。
まずは簡単なサーバーレスアプリケーションを作成して感覚を掴むのが良いと思います。
[初めてのサーバーレスアプリケーション開発 ～DynamoDBにテーブルを作成する～](https://dev.classmethod.jp/articles/serverless-first-dynamodb/)
[初めてのサーバーレスアプリケーション開発 ～LambdaでDynamoDBの値を取得する～](https://dev.classmethod.jp/articles/serverless-first-lambda/)
[初めてのサーバーレスアプリケーション開発 ～API GatewayからLambdaを呼び出す～](https://dev.classmethod.jp/articles/serverless-first-apigateway/)

#API Gateway
スマホアプリなどのクライアントからのHTTPリクエストは、API Gatewayで受け付けてLambda関数で処理されます。API GatewayではLamba関数に渡す前のデータ形式を調整し、Lambda関数から返ってきたデータの形式を調整してクライアントにHTTPレスポンスとして返却します。
![スクリーンショット 2020-10-23 14.03.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410068/8d0c0a75-4490-5875-c670-c5d740df1363.png)
###初期設定など
API Gatewayの設定、Lambdaへのパラメータの受け渡しなどについて、以下が参考になりました。
https://qiita.com/naoki_koreeda/items/c2a32198c86e8d9a5bb6
###統合レスポンスやヘッダーの設定
統合レスポンスやステータスコードのLambdaでのエラーの正規表現の書き方、ヘッダーのマッピングの仕方などについて、以下が参考になりました。
https://qiita.com/naoki_koreeda/items/5351f8ab803db655b0b4
###formでPOSTする際のマッピングテンプレート
「application/x-www-form-urlencoded」の形式でPOSTする際のマッピングテンプレートの作成に苦労しました。以下の記事を参考に作成しました。
https://dev.classmethod.jp/articles/sugano-013-api-gateway/
###OpenAPI、Swagger形式でエクスポート
API GatewayでREST APIを作成および設定したら、API GatewayコンソールなどからOpenAPIファイルやSwaggerファイルにエクスポートできます。
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-export-api.html
逆にOpenAPI、Swaggerファイルからインポートすることもできるので、ドキュメントを変更してそれを環境に反映させるのも簡単です。開発効率が向上します。
### API Gatewayのドメインを変更したい
API GatewayではデフォルトのURLを使用する代わりに、任意のカスタムドメイン名を使用することができます。
API Gatewayでカスタムドメインを設定し、HTTPS化する際に以下が参考になりました。
https://dev.classmethod.jp/articles/api-gateway-custom-domain-ssl/
https://dev.classmethod.jp/articles/api-gateway-custom-domain/

### 応答性を強化するためにAPIキャッシュを設定したい
APIキャッシュを有効にして、エンドポイントのレスポンスがキャッシュされるようにできます。
キャッシュを有効にすると、エンドポイントへの呼び出しの数を減らすことができ、また、APIへのリクエストのレイテンシーを短くすることもできます。
メソッド毎にのキャッシュを有効または無効にしたり、TTL期間を変更したりすることもできます。
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-caching.html

###開発環境、本番環境で使用するLambdaやDynamoDBを変更したい
2つの異なるHTTPエンドポイントが存在する場合に、API Gatewayのステージ変数を使用することで、異なるAPIデプロイステージのHTTPとLambdaバックエンドにアクセスできます。
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/amazon-api-gateway-using-stage-variables.html

API Gatewayで設定したステージ変数をLambdaへパラメータとして渡すことで、ステージ変数を元にLambda内で使用するDynamoDBのテーブルを変更することができます。

###Basic認証したい
https://qiita.com/diaphragm/items/b87d700ef36fa62c1aa8

#Lambda
Lambdaはサーバーの準備・管理をしなくても、コードを実行できるサービスです。
今回の構成ではAPI Gatewayをトリガーにして実行されます。
![スクリーンショット 2020-12-07 8.21.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410068/a72090e8-5e05-96a0-67c8-80f61e0c3158.png)
###Lambda関数内でサードパーティのライブラリを使いたい
Lambdaでrequestsを使いたいなど、サードパーティのライブラリを使いたいときに、以下の記事が参考になりました。
https://qiita.com/Hironsan/items/0eb5578f3321c72637b4

###Lambdaで環境変数を使いたい
Lambdaではキーバリュー形式で環境変数を設定することができます。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.html

Lambdaにデフォルトで設定されている環境変数は以下です。
https://qiita.com/ykarakita/items/c9b1ee133fe03bbd4f1e

###LambdaでHTMLを返す
LambdaでHTMLを返す方法は以下が参考になりました。
https://qiita.com/yoshidasts/items/d58c555aed2693e99ae6

###LambdaからLambdaを非同期で呼び出したい
Lambdaから別のLambdaを呼び出したいときは`invoke`を使います。
呼び出す際に同期/非同期を設定することができます。
以下が参考になりました。
https://qiita.com/ume1126/items/8170a10fad6b21f0f54a
#DynamoDB
DynamoDBはフルマネージド型のNoSQLデータベースサービスです。
Lambdaとの相性が良く、サーバレスなWebAPIではDynamoDBを使用するのが最も一般的です。
DynamoDBではパーティションキーを設定する必要があります。パーティションキーのみで一意にならない場合は、ソートキーを設定します。
完全一致検索、範囲検索、前方一致検索などが可能です。

以下の例ではパーティションキーに型番、ソートキーにメーカー名を設定しています。
imageURLやtypeなど、他の項目をキーにして検索したい場合は、グローバルインデックスを設定することで検索可能になります。
![スクリーンショット 2020-12-07 19.52.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410068/3395d35b-3d0e-209f-2728-4ade26d6b871.png)
[Amazon DynamoDB とは - Amazon DynamoDB](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Introduction.html)

AWSのDBには多くの選択肢が存在します。それぞれのユースケースなどは以下に記載されています。
https://aws.amazon.com/jp/products/databases/


###DynamoDBのデータを自動で削除したい
DynamoDBに登録したデータを自動で削除したいことがあったので調べました。
リアルタイム性が重要でない場合、DynamoDBのTTL機能で自動削除できます。
https://dev.classmethod.jp/articles/try-dynamodb-ttl/

リアルタイム性が必要な場合は、AWSStepFunctionsを使って自動削除を実現できます。
https://qiita.com/se_fy/items/dfe5bccaca80deebfa1b\

AWSStepFunctionsについては以下が参考になりました。
https://dev.classmethod.jp/articles/step-functions-parameters/

###DynamoDBのデータをインポート・エクスポートしたい
DynamoDBのデータはDataPipelineを使用してインポート・エクスポートをすることができます。
https://www.wakuwakubank.com/posts/694-aws-data-pipeline-dynamodb/

DynamoDBではデータをJSON形式でエクスポートしたときに、単純なキーバリュー形式ではなく、間にデータ型が入ってしまいます。
このようなJSONからデータタイプを排除する方法は以下が参考になりました。
https://bbh.bz/2019/12/09/delete-data-type-from-dynamodb-json/

# CloudWatch Logs
CloudWatch Logsでは、ログの簡単な表示や特定のエラーコードまたはパターンの検索などが可能です。
Lambda関数には、CloudWatch Logsのロググループが付属しており、ログが自動で出力されます。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-logging.html
###ログデータを分析したい
CloudWatch Logs Insightsを使用することで、ログデータを簡単に分析することができます。
ログの操作にはクエリ言語を使用します。
CloudWatch Logs Insightsについては以下の記事が参考になりました。
https://qiita.com/sakochi/items/8e60654ffe36432c5228

CloudWatch Logs Insightsではクエリが保存できます。
https://hacknote.jp/archives/57401/

###CloudWatch Logsのエラーログ内容をメールで送信したい
CloudWatch Logsで出力しているログファイルに特定の文字列がログに存在した場合に、メールで通知することができます。以下の記事が参考になりました。
https://dev.classmethod.jp/articles/notification_cloudwatchlogs_subscriptoinfilter/

メトリクスフィルターでのパターンマッチングについては以下が参考になりました。
https://dev.classmethod.jp/articles/cloudwatch-metricsfilter-filterpattern/
###CloudWatch Logsのエラーログ内容をSlackに通知したい
Slackで通知する方法は以下が参考になると思います。
https://qiita.com/yahagin/items/2248287c5285cd1e9201

#おわりに
私がサーバレスWebAPIを構築する上で参考になった記事を紹介しました。
これらの記事のおかげでサーバレスWebAPIを構築し、運用することができました。
この記事が、私のように初めてAPI Gateway、Lambda、DynamoDBに触れる方やAWSのサーバレス開発で困っている方の一助になれば幸いです。
この記事は自分用のメモでもあるので、今後運用する中で困ったことがあれば参考にした記事などを順次追加していきます。