【個人開発】マンガを楽しむWebアプリを支える技術の共有:インフラアーキテクチャおよび技術選定

3 min read読了の目安(約2900字

はじめに

  • 各出版社さんがWebでマンガを公開しているのをご存知でしょうか?かなり大量のタイトルを読むことができるので、私はひたすら読ませてもらっています。
  • ただしネックがあり、各Webサイトはバラバラに運営されているため、マンガの新着確認が面倒でした。また公開日が限定されているため、読み逃すこともしばしばありました。
  • このような課題を解決するために、複数サイトを横断してチェック可能で、かつ公開日を簡単に把握できるサービスを作ることにしました。
  • ちまちま作っていましたが、ようやく人様にも見せられそうなレベルになったので、それまでに技術的につまったところ、発見したことなどを記事にして公開していこうと思います。
  • 完璧独学で取り組んだので、「おいおい…」というような実装もあるかもですが…。

作成したWebアプリ:

https://www.comiclake.net/
APIのキャパシティをかなり絞ってあるので、その状態でまともに動作するか確認をしてみたく、試しに覗いて行ってもらえると助かります。

インフラ構築

  • AWSの基礎を学んだことがあったため、AWSを活用することに決めました。あまり真剣に選定はしていません…。

  • 紆余曲折を経て、下図のようなインフラ構成に落ち着きました。

  • サーバーの管理はとてもできないので、ひたすらサーバレスに徹しました。

  • ホスティング+認証+APIはAmplifyを使って構築しています。

    • フロントエンドはNuxt.jsで構築し、SPAモードで運用しています。
      • Amplifyホスティングする場合、SPA、SSR、SSGのどれでも行けるようですが、SSRは公式ドキュメントにすらNuxt.jsでのデプロイ方法が見当たらないので見送り、ある程度リアルタイムの更新が必要なサイトの性格からSSGは不向きだと考え、消去法でSPAにしました。
    • UIフレームワークは、過去に使ったことがあるVuetifyを選定しました。
  • 各出版社の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で怒られてコンテンツが取得できない場合がありました…。下記にまとめてます。

https://zenn.dev/foxtail88/articles/e77fd4626f11d5
https://zenn.dev/foxtail88/articles/8ce362bdf7e0d1

技術選定

フロントエンド

  • 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ユーザプールの両者を活用しています。詳細は別記事にします。

https://zenn.dev/foxtail88/articles/9580ec6c5c2164

API

  • Amplify CLIからAPI(AppSync+DynamoDB)を追加して構築しています。
    • 最初はAppSyncって何やねん…と思い、手動でDynamoDBのテーブルとそれを叩くLambdaを作っていたのですが、コールドスタート時のレスポンスが遅かったためボツにしました。
  • どの項目に認証が必要かなどもコードベースで簡潔に記述できるため、かなり使いやすいです。
  • ただし入力のバリデーションなどはAmplify CLIからは設定しきれないため、vtlを自前で書き換えたりする必要がありました。書き換え方はこちらの記事にまとめました。

https://zenn.dev/foxtail88/articles/86e6032b3aedeb

Lambda(クローラ)

  • 手間はかかりますが、特に難しいことはしてないですね…。goqueryが便利でした。

おわりに

  • 今現在更新状況をウォッチしているコンテンツは1,000を超えました。素人の個人開発者が、こんなシステムをポンと組めるのは良い時代だな、と感じる次第です。
  • AWSを使うにもお金がぼちぼちいるので、収益化の取り組みも進めて行きたいところですが、サービスの性質上『独自コンテンツが少ない』と見なされそうなので悩みますね…。