AWSを活用したサーバーレスWebアプリの制作

# AWSを活用したサーバーレスWebアプリの制作

## はじめに
2019年後半『[Mosaic(モザイク)](https://mosaic.w2or3w.com/)』というサーバーレスWebアプリを作りました。
画像をアップロードする → 人の顔を検出する → 切り抜き画像を表示して選んでもらう → 選んだ画像にモザイクをかける

作りっぱなしは良くないということで、振り返りと定着のためハンズオン的な記事としてまとめます。
以下のようにいくつかの記事に分けて投稿を予定しています。

## コンテンツ
- [サーバーレスWebアプリを開発するためのCloud9環境構築](https://qiita.com/w2or3w/items/6cda6177ca6b0f704974)
Cloud9で開発してまして、なので、その環境構築からはじめます。
VueのWebアプリ、Lambda用のPython(3.6)、などを開発・ビルドできるようにします。

- [Vue CLIで新規プロジェクト作成と、よくある雛形の実装](https://qiita.com/w2or3w/items/20d393560571f1531041)
Vue CLI 3でSPA(シングルページアプリケーション)の雛形を新規作成します。
UI用のフレームワークとして、マテリアルデザインのVuetifyを利用。
ヘッダー、フッター、いくつかのページへのルーティング、ハンバーガーメニューなどを実装します。

- Vue Routerのヒストリーモードとリダイレクトの話 (T.B.D.)
Vue Routerを利用するとURLに #(ハッシュ) が付くのですが、なんだか気持ち悪いですよね。
そこで、#が付かないようにするための手段としてヒストリーモードというものがあるのですが、色々と検討した結果、ワタシはヒストリーモードを諦めました。#を受け入れともに歩んでゆくことにした、そのワケとは。

- [AWS Amplifyのセットアップ](https://qiita.com/w2or3w/items/bb0ddecb8fe7c5dca8ae)
開発環境にAWS Amplify CLIをインストールして、AWS Amplifyをセットアップします。

- [AWS Amplifyを利用してS3へファイルアップロードとLambda呼び出し](https://qiita.com/w2or3w/items/fb82544f001296087bd7)
VueのプロジェクトへAWS Amplify CLIでStorageとそれをトリガーとするFunctionをセットアップします。
WebアプリからS3にファイルをアップロードしてそれをトリガーにLambdaが動く仕組みをAmplifyでサクッと構築します。

- [AWS Amplify Consoleでビルド＆デプロイ](https://qiita.com/w2or3w/items/da1134fa3a14660dcc54)
VueのプロジェクトをAWS Amplify Consoleにより、プロビジョン→ビルド→デプロイ→検証します。
指定のリポジトリ&ブランチに対するコミットをトリガーにデプロイが走り、また、amplifyapp.comドメインにホストしてくれます。

- [S3への静的サイトホスティングとAmplify Consoleによるデプロイ比較](https://qiita.com/w2or3w/items/8f4050482fee5a9307e0)
Amplify Consoleの楽さをより実感するために、あえてS3にもデプロイして静的サイトとしてホストします。
静的サイトといえど、Webアプリのとして動作します。

- [Lambda + OpenCVで画像処理 (グレー画像作成)](https://qiita.com/w2or3w/items/e6feac50c751bbc64697) 
S3への画像アップロードをトリガーに、その画像に対して画像処理をさせるLambdaのファンクションをPython3.6で実装します。
画像処理にはOpenCVを利用します。

- [AppSyncをフロントエンドとバックエンドで利用する](https://qiita.com/w2or3w/items/70f6b6d8d13b60afaee5)
アップロードした画像や処理された画像のデータ管理や、クライアント側とのデータ受け渡しのために、AppSyncというAPIを利用します。AppSyncのデータソースにはDynamoDBが使われます。
AppSyncはAmplify CLIでもセットアップ可能なのですが、DynanoDBのパーティションキーやソートキーの指定ができないようだったので、Amplify CLIは使いません。AWSコンソールでDynamoDBとAppSyncを構築します。
フロントエンドのVueからはAmplifyを利用してSubscription、バックエンドのLambda(Python)からはHTTPでリクエストします。

- Lambda(Python) + OpenCV で顔検出 (T.B.D.)
- [Lambda(Python) + Rekognition で顔検出](https://qiita.com/w2or3w/items/48bc05684c6dafbf5253)
  顔検出を実現する手段としてOpenCVが最初に思い立つ古い人間なのですが、OpenCVで納得いく検出をさせようと思うとなかなかしんどいんです。で、このAWS Rekognitionを利用してみたのですが感動しました。角度や回転に影響されず、高精度、そして早い！
- [API Gatewayでリクエストして、Lambdaで処理させて、AppSyncで受け取る](https://qiita.com/w2or3w/items/227465969ecbbef21787)
  検出した顔を並べて表示しました。次はいよいよ顔にモザイクをかけてゆきます。
処理をキックするためにAPI GatewayとLambdaを利用します。また、実行結果はAppSyncのSubscriptionで受け取ります。
- [Floating Action Button でスクロール制御](https://qiita.com/w2or3w/items/a14d6f7ba6c89572a49b)
  最近のアプリで良く見かける、ずっと定位置にあるあのボタン。
最近のアプリで良く見かける、するする〜っとなめらか〜にスクロールするあの機能。
それらをVueのWebアプリに実装します。
- [Lambda(Python)でGoogle Driveへファイルアップロード](https://qiita.com/w2or3w/items/b66a4a8e45e6001a9c46)
S3ってファイルを保存するだけならいいのですが、そのファイルを人が参照するのには向いてないですよね。画像にしてもWebブラウザ上でそのまま見ることができず、一度ダウンロードしてから見る必要がある。ちょっと手間なんですよね。
その点、Google DriveはPCにしろスマホにしろ、ブラウザやアプリでいい感じに画像を参照することができますのでいい感じです。
- [S3ファイルやDynamoDBレコードの自動削除](https://qiita.com/w2or3w/items/045a1facd15291d7a51a)
S3やDynamoDBって、もちろん長期的に保存したい用途に利用することもありますが、一時的なデータ保存場所として利用するケースも多いですよね。ワタシのMosaicなんかも、30分くらいで消えてしまって何ら問題ありません。
そんな時は自動的に削除される仕組みがありますので、それを利用しましょう。

- [お名前.comで取得した独自ドメインのサブドメインをAmplify Consoleで割り当てる](https://qiita.com/w2or3w/items/ddb7c4c1a602470ef96b)
Amplify Consoleを利用すれば、amplifyapp.comのサブドメインでサイトを公開することは簡単にできました。このままでも問題ないのですが、いつかは自分のドメインを取ってそこで公開したいですよね。
ここでは、「お名前.com」でドメインを取得し、そのサブドメインをAWSでホストするサイトに割り当てる、という事をしたいと思います。

- [Vue.jsで作ったWebアプリのPWA対応とキャッシュ問題への対策](https://qiita.com/w2or3w/items/74a6e471501ee28ee9dd)
Webアプリをドメイン取って公開したら、次はPWA対応もしたくなりますよね。PWA(Progressive Web Apps)とは、Webアプリをモバイルアプリのようにスマホにインストールすることができる技術です。インストールするというか、スマホのホームにアイコンが追加され、一見モバイルアプリのように動作させることができます。
Vueで作成したWebアプリなら、簡単にPWA対応を実装することができます。
この技術のアルアルとして、「キャッシュがクリアされなくてバージョンアップしたアプリが反映されない」という問題がありまして(特にiOSのSafari)、それへの対応についても書きます。

## あとがき
2019年6月頃から勉強会コミュニティ(主にJAWS UG [浜松](https://jawsug-hamamatsu.doorkeeper.jp/) / [磐田](https://jawsug-iwata.connpass.com/))に参加するようになり、そこでアウトプットするために『[Mosaic](https://mosaic.w2or3w.com "Mosaic")』を制作しました。
https://mosaic.w2or3w.com

制作期間は2019年9月末〜2019年12月頭の約3ヶ月。
2019年12月上旬に『[浜松IT合同勉強会2019 LT大会](https://hamamatsu-it.connpass.com/event/106184/ "浜松IT合同勉強会2019 LT大会")』なるものに参加し、そこでこのWebアプリとともに初LTを経験。
初めてのQiita投稿をと、この記事の下書きを書き始めたのが2019年12月中旬です。
2019年は、勉強会に参加してみるという行動がそれなりに大きな変化やさらなる行動に繋がったと思ってます。

Qiitaへのこの初投稿も、JAWS UG 浜松のボスが息をするように自然にAmplifyのアドベントカレンダーへ参加してるのを見たり、勉強会に参加する皆さんのLT、AWSのコミュニティプログラムマネージャやエバンジェリストの方が発信しているのを直接見る機会があったことが大きいです。

2020年も引き続き、アプリ開発とサービス運用を通じてインプットしつつ、勉強会、LT、記事投稿、などでアウトプットしていこうと思ってます。
今後ともよろしくお願いします。

---
Qiita初めてなもので、もしお気付きの点などがあればご指摘をいただけると幸いです。
ご感想やご要望、各種SNSのフォロー、大歓迎です。

---
## 履歴
* 2019/12/31 : 7記事 / 17記事
年内に10記事くらいいけるかなぁと思ってたけど、残念ながら7記事でタイムアップ。
なかなか大変ですね、書くの。慣れない。時間かかる。
年始の連休中にもう5記事くらい書き足したいが、果たして、、。

* 2020/1/3 : 8記事 / 17記事
「AppSyncをフロントエンドとバックエンドで利用する」を投稿しました。
内容が少し多くなりすぎてしまったかなと感じるのと、ちょっと雑な感じになってしまった気もする。
技術記事を書くって大変ですね、なかなか慣れなさそうです。

* 2020/1/5(朝) : 9記事 / 17記事
「Lambda(Python) + Rekognition で顔検出」を投稿しました。
OpenCVで顔検出をついつい飛ばしてしまいました。
年始の連休中にもう5記事くらいと書きましたが達成できそうにありませんね。
あぁ、明日から仕事かぁ、もう1週間くらい休みたい！

* 2020/1/5(夜) : 10記事 / 17記事
「Floating Action Button でスクロール制御」を投稿しました。
一番時間がかからなそうな記事を選びました。さて明日は久しぶりのお仕事です。おやすみなさい！

* 2020/1/8(夜) : 11記事 / 17記事
「Lambda(Python)でGoogle Driveへファイルアップロード」を投稿しました。
あと6記事、なかなか先は長いですね。飽きてきたわけではないですが、早くMosaicのリファクタリングや機能追加を再開したい欲がムラムラと、、。
飽きたわけではないですよ。

* 2020/1/12(夜) : 12記事 / 17記事
「S3ファイルやDynamoDBレコードの自動削除」を投稿しました。
嫁がインフルになりまして。この3連休は毎年大学時代の友人と雪山合宿を恒例行事としてて14年続けているのですがついに穴を開ける日が来てしまいました。ツライ。
そうこうしているうちに、娘(4)もインフルになりまして。初めて夜間救急を利用しました。かなり混んでるんですね、あそこ。
家事・育児・看病・買出し、、などやることは比較的多いのですが、それ以外にやることもなく暇という状況の中書き上げた思い出に残る記事です。しかしS3のライフサイクルルールよろしく、DynamoDBのTimeToLiveよろしく、そのうち忘れてしまうのでしょう。
夜間救急のくだりは、いつか結婚式とかで思い出して涙するやつかもしれないですね！

* 2020/1/18(昼) : 13記事 / 17記事
「お名前.comで取得した独自ドメインのサブドメインをAmplify Consoleで割り当てる」を投稿しました。
あとがきの自分語りが長くなりました。

* 2020/1/28(夜) : 14記事 / 17記事
「Vue.jsで作ったWebアプリのPWA対応とキャッシュ問題への対策」を投稿しました。
この記事のシリーズとは別に2件ほど浮気してしまいました。
「[PythonでGoogleのCloud Vision APIを利用して画像から日本語文字検出する](https://qiita.com/w2or3w/items/c7288e8ce62d061ff6d2)」
「[AmplifyのStorageと認証まわり](https://qiita.com/w2or3w/items/9208b43b4e97750dc7f0)」

* 2020/3/14(夜) : 15記事 / 17記事
「API Gatewayでリクエストして、Lambdaで処理させて、AppSyncで受け取る」を投稿しました。
何ということでしょう。約2ヶ月ぶりです。
ただ、このシリーズとは別に3記事書いてますのでセーフです。
ではまたしばらく。ごきげんよう！