🔖
【個人開発】マンガを楽しむWebアプリを支える技術の共有:インフラアーキテクチャおよび技術選定
はじめに
- 各出版社さんがWebでマンガを公開しているのをご存知でしょうか?かなり大量のタイトルを読むことができるので、私はひたすら読ませてもらっています。
- ただしネックがあり、各Webサイトはバラバラに運営されているため、マンガの新着確認が面倒でした。また公開日が限定されているため、読み逃すこともしばしばありました。
- このような課題を解決するために、複数サイトを横断してチェック可能で、かつ公開日を簡単に把握できるサービスを作ることにしました。
- ちまちま作っていましたが、ようやく人様にも見せられそうなレベルになったので、それまでに技術的につまったところ、発見したことなどを記事にして公開していこうと思います。
- 完璧独学で取り組んだので、「おいおい…」というような実装もあるかもですが…。
作成したWebアプリ:
APIのキャパシティをかなり絞ってあるので、その状態でまともに動作するか確認をしてみたく、試しに覗いて行ってもらえると助かります。インフラ構築
-
AWSの基礎を学んだことがあったため、AWSを活用することに決めました。あまり真剣に選定はしていません…。
-
紆余曲折を経て、下図のようなインフラ構成に落ち着きました。
-
サーバーの管理はとてもできないので、ひたすらサーバレスに徹しました。
-
ホスティング+認証+APIはAmplifyを使って構築しています。
- フロントエンドはNuxt.jsで構築し、SPAモードで運用しています。
- Amplifyホスティングする場合、SPA、SSR、SSGのどれでも行けるようですが、SSRは公式ドキュメントにすらNuxt.jsでのデプロイ方法が見当たらないので見送り、ある程度リアルタイムの更新が必要なサイトの性格からSSGは不向きだと考え、消去法でSPAにしました。
- UIフレームワークは、過去に使ったことがあるVuetifyを選定しました。
- フロントエンドはNuxt.jsで構築し、SPAモードで運用しています。
-
各出版社のWebサイトから情報を取得する必要があるため、スケジューリング動作するLambdaを構築しています。様々な関数を共通化する複数のLambdaをデプロイするため、SAM(Serverless Application Model)を活用しました。
- 情報の取得は、各サイト様に過度な負荷をかけないように、API・RSSの活用を第一として、どうにもならない場合だけ十分にアクセス頻度を下げた上でクローリングしています。(robots.txtを確認する限り、禁止されているサイト様はないです)
- 取得した情報をユーザがAPIを通じてアクセスするDynamoDBに保存します。
- Lambdaの言語はGoにしました。別記事にしますが、記述の自由度が少ない&型安全なため、数ヶ月前の自分が書いたコードでもすっと頭に入ってきて、とても開発がしやすかったですね…。並行処理を行う場面はほぼ無いので、goroutineを活用する機会はなかったですが…。
-
マンガのサムネイル画像や、その他静的なコンテンツもAmplifyで生成するホスティング用のS3に置ければよいのですが、それができなかったのでCMS用にS3+CloudFrontを手動で構築しています。静的コンテンツはGithubアクションを使って、GithubにPushすると自動でS3にアップロードするようにしています。
- ただ、この時のCloudFrontの設定に失敗するとcorsで怒られてコンテンツが取得できない場合がありました…。下記にまとめてます。
技術選定
フロントエンド
- Nuxt.js + Vuetify.js で構築しています。
- PWA対応やルーティングなど、面倒なことを抱えたくなかったのでNuxt.jsを使うことにしました。Next.jsにしなかったのは、React書いたことがなかったからです…。(あとから、Amplify+Nextの方が(主観ですが)開発が盛んなことを知り、何度かNextに浮気したくなりましたが…)
- Vuetify.jsも比較的使いやすいですが、設定を工夫しないとbundleサイズが大きくなりすぎてヤバいですね…。あとコンポーネントを大量に描画するとレンダリングがおっつかなくなるので、大量に繰り返し描画する部分は自前でゴリゴリcss書く必要がありました。ToDo:後日別記事を書いてリンクを貼る
バックエンド
Amplify CLIとAWS SAM CLIを使ってサーバレスに構築しています。
認証
- Amplify CLIからAuthを追加して構築しています。
- ユーザ登録有無に関わらず使用可能な機能と、ユーザのみ使える機能の両方が存在するため、認証方法としてIAMとCognitoユーザプールの両者を活用しています。詳細は別記事にします。
API
- Amplify CLIからAPI(AppSync+DynamoDB)を追加して構築しています。
- 最初はAppSyncって何やねん…と思い、手動でDynamoDBのテーブルとそれを叩くLambdaを作っていたのですが、コールドスタート時のレスポンスが遅かったためボツにしました。
- どの項目に認証が必要かなどもコードベースで簡潔に記述できるため、かなり使いやすいです。
- ただし入力のバリデーションなどはAmplify CLIからは設定しきれないため、vtlを自前で書き換えたりする必要がありました。書き換え方はこちらの記事にまとめました。
Lambda(クローラ)
- 手間はかかりますが、特に難しいことはしてないですね…。
goquery
が便利でした。
おわりに
- 今現在更新状況をウォッチしているコンテンツは1,000を超えました。素人の個人開発者が、こんなシステムをポンと組めるのは良い時代だな、と感じる次第です。
- AWSを使うにもお金がぼちぼちいるので、収益化の取り組みも進めて行きたいところですが、サービスの性質上『独自コンテンツが少ない』と見なされそうなので悩みますね…。
Discussion