【AWSハンズオン】サーバーレスクラウドを利用してSNSアプリを実装する。

こんにちは、k_ukiです。
現在、「AWSではじめるクラウド開発入門」という書籍の12章を進めています。
ここでは、10章,11章で学習したサーバレスクラウド（Lambda,S3,DynamoDB）を使用し、シンプルなWebアプリを実装するという内容でした。今回のハンズオンで学んだことをここにまとめていきます。

## アプリの説明
### アプリの概要
利用者が考えて作った俳句を投稿し、ユーザがいいねできるようなSNSアプリです。
また、アプリ名を"Bashoutter"としています。
機能要件は以下の通りです。
- 俳句の一覧を取得
- 俳句を新規投稿する。
- 俳句にお気に入り表を一つ入れる
- 俳句を削除する
### API

上記の機能要件を満たすための最小限の設計として4つのREST APIを実装しています。
<table>
<tr>
 <td>GET/haiku</td><td>俳句の一覧を取得</td>
</tr>
<tr>
 <td>POST/haiku</td><td>俳句を新規投稿する。</td>
</tr>
<tr>
 <td>PATCH/haiku/{item_id}</td><td>俳句にお気に入り表を一つ入れる</td>
</tr>
<tr>
 <td>DELETE/haiku/{item_id}</td><td>俳句を削除する</td>
</tr>
</table>

### 設計
今回デプロイするアプリの設計を以下に簡単に示す。
- クライアントからのAPIリクエストをAPI Gatewayに送信しAPIのURIで指定されたLambda関数へ転送する。
- APIのパスごとに別のLambdaを用意する
- 俳句の情報をDynamoDBに登録する。
- LambdaにはDynamoDBへのアクセス権を与える
- webページのコンテンツ（htmlファイル等）を表示するためのS3バケットを用意する。クライアントはS3バケットにアクセスしページを取得する。

## 導入に必要な用語
### S3＜ Public access mode
今回使用するS3バケット作成用のコードには以下の一文があります。
```
public_read_access=True 
```
S3には<b>Public access mode </b>という機能があります。この機能をOnにすることで認証なしで誰でもコンテンツを閲覧できるようになります。今回はwebページで表示するためのhtmlファイルなどを誰でも閲覧できるようにするために適応しています。

### ハンドラ関数
送られてきたAPIリクエストを基に処理を行う関数のことをハンドラといいます。
### IAM(Identity and Access)
 IAMは、<b>リソースが他のリソースに対してどのような権限を持っているかを定義するもの</b>です。

 例えば、Lambdaはデフォルトの状態でほかのリソースにアクセスする権限を持っていません。そのため、デフォルトの状態ではDynamoDBにアクセスすることは不可能であるため、それを許可するIAMをLambdaに付与する必要があります。

### API Gateway
API GatewayはAPIのリクエストに従ってLambdaやS3などに接続を行う機能となっています。また、各リソースの処理の結果もAPI Gatewayを通り返されます。

## デプロイを実行する。
早速デプロイを実行してみます。まず、プロジェクトのディレクトに移動し以下のコマンド実行します。
```
$ python3 -m venv .env
$ source .env/bin/activate
$ pip install -r requirements.txt

$ cdk deploy
```
入力後、以下の画面が表示されデプロイが完了したことがわかります。
また、コンソールを確認するとデプロイしたアプリ名が表示されました。
![12-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2341225/fd2c5f5b-a5b7-4aee-eb7a-fba294367f09.png)
![12-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2341225/b8df57f8-5e93-4172-2da2-19d4d3e70d15.png)

本当にちゃんとデプロイが完了したのか確認します。
API Gatewayのコンソールのアプリ名をクリックすると、それぞれのメソッドを確認することができます。
![12-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2341225/e59dc372-8f5e-df1b-259b-322a2c0b129d.png)

次にS3のコンソールにアクセスします。
バケット名をクリックすることで中身を確認することができます。中にはウェブページの静的コンテンツが存在していたので正しくデプロイで来たことが確認できた。
![12-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2341225/bb45fbde-896b-f2c2-4b34-9cc6b3947e0d.png)

## APIリクエストを送信してみる
早速デプロイしたアプリにAPIリクエストを送信して操作してみようと思います。
まず、デプロイ実行時に得られたAPIのURLをコマンドライン変数に登録しておきます。
```
$ export ENDPOINT_URL= "APIのエンドポイントのURL"
```
登録が完了したら、俳句の一覧を取得してみます。現時点では何も登録していないので空の配列が返されました。
```
$ http GET "${ENDPOINT_URL}/haiku"
```
![12-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2341225/e2eac366-1302-7e08-1038-744fb612e045.png)

次に俳句の投稿を行ってみます。正常に作成されると以下のメッセージが出力されます。

```
http POST "${ENDPOINT_URL}/haiku"\
username="松尾芭蕉" \
first="閑さや" \
second="岩にしみ入る" \
third="蝉の声"
```

![12-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2341225/b0df74d2-7250-fe3b-564c-aa7037d4fa1f.png)

投稿が完了したので再度GETメソッドを実行してみます。
![12-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2341225/34086026-711e-246f-621e-74ceec9e946d.png)

今投稿した内容を確認できました！

次に、PATCHメソッドを使用して俳句にいいねをしてみます。
以下のコマンドを実行してみます。
```
http PATCH "${ENDPOINT_URL}/haiku/(GET メソッドで得たitem_id)"
```
再度GETメソッドを実行したところ、likesが1.0になっており更新処理が完了したことがわかります。
![12-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2341225/ceb30eef-a5d7-823a-7861-3c0cb1cf345f.png)
最後に、DELETEメソッドを実行してみます。
```
http DELETE "${ENDPOINT_URL}/haiku/(GET メソッドで得たitem_id)"
```
再度GETメソッドを実行すると空の配列が返されたので無事削除が完了したことがわかりました。

## GUIを動かしてみる
今まではCLI上でアプリを操作してきました。次はGUI上でアプリを操作してみます。
アクセスするにはデプロイ時に出力されたURLにアクセスします。

![12-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2341225/6ca0fd65-35c3-1b15-053b-d97b7ce6930d.png)

ページが表示されたら一番上にAPI ENDPOINT URLを入力し必要な情報を入力したところ、ちゃんと投稿することができました。
![12-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2341225/cb717e02-d7e3-3210-509c-0bad86010c3a.png)

## 最後に
以上が12章のハンズオンで実践した内容になります。サーバレスのサービスの使い方に加えAPIリクエストやハンドラ関数などの知識も学ぶことができました。