HobbyHub

AWS Django PostgreSQL
HobbyHub

概要

HobbyHub は、趣味のレッスンやアクティビティの検索・登録と、サプライヤー側の運営管理(施設・講師・レッスン・開催日程の管理)を行える Django マーケットプレースアプリです。

AWS ECS によるコンテナ構成と、Lambda を活用した非同期画像処理基盤を備えた本番グレードのインフラで運用しています。

HobbyHub は大きく 2 つの利用者向け機能を提供します。

  • 参加者(Participant): 公開レッスンの開催日程の閲覧・登録、レビュー投稿
  • サプライヤー(Supplier): 施設・レッスン・講師・開催日程の作成と管理

参加者としてアカウント登録したユーザーが施設(Organization)を登録した時点で、自動的にサプライヤーとして扱われ、サプライヤー専用の管理機能にアクセスできる設計です。Django の既存権限モデルを拡張することなく、シンプルかつ直感的なロール切り替えを実現しています。

サーバーサイドレンダリングの Django テンプレートを中心に、Webpack + Babel でフロントエンドのアセットをバンドルしています。

開発のこだわり

  • 参加者(Participant)とサプライヤー(Supplier)の 2 ロール構成を、Django の既存権限モデルを拡張せずシンプルな設計で実現
  • AWS Lambda を使った非同期 WebP 画像処理パイプラインを設計・実装
  • Tech-In-Bytes(EC2 直接構成)との比較を意識し、ECS によるコンテナ化構成を採用・習得
  • mypyflake8blackisort を導入し、型安全性とコード品質を重視した開発
  • 設計・開発から AWS インフラ構築・運用まで、すべての工程を一人で担当

工夫した点・学んだこと

本プロジェクトでは、前作(Tech-In-Bytes)の EC2 直接構成との違いを体験するため、意図的に AWS ECS を選択しました。クラスター・サービス・タスク定義・コンテナ間通信など、コンテナオーケストレーションの概念を一から習得する必要があり、インフラ設計の難易度は前作より大幅に高くなりました。

また、Lambda を使った非同期画像処理パイプラインの実装も大きな挑戦でした。ユーザーが画像をアップロードすると S3 の processing/ プレフィックスへの書き込みイベントが Lambda をトリガーし、WebP への変換・リサイズ処理後に media/ へ保存するという流れで、Django・S3・Lambda の 3 者を正確に連携させる必要がありました。各サービス間の権限設定やイベント設定など、複数のコンポーネントを組み合わせる難しさを実感し、AWS サービス連携への理解が深まりました。

機能一覧

認証・アカウント管理

  • ユーザー登録 / ログイン / ログアウト
  • アカウント設定、プロフィール編集、アカウント削除
  • パスワードリセット(SMTP メール送信)

サプライヤー機能

  • サプライヤー初期登録フロー(施設 → レッスン → 講師 → 開催日程の順に作成)
  • 施設 / レッスン / 講師 / 開催日程の CRUD
  • 参加者管理(支払いステータスの管理を含む)

参加者機能

  • 公開レッスン・開催日程の検索・フィルタ・閲覧
  • レッスンへの登録・キャンセル
  • レビュー(評価)投稿

メディアパイプライン

  • 画像アップロード対応:プロフィール / 施設 / レッスン / 講師
  • S3 processing/ プレフィックスへのアップロードをトリガーに Lambda が起動
  • Lambda(Pillow)が WebP バリアント(small / medium / original)を生成し media/ へ保存
  • エンティティ削除時に S3 上の画像バリアントを自動クリーンアップ

UX / UI

  • Bootstrap 5 ベースのレスポンシブ UI
  • django-crispy-forms + crispy-bootstrap5 によるフォームレンダリング

運用・デプロイ

  • AWS SSM Parameter Store によるシークレット管理(ECS タスク定義と連携)
  • ECS サービスへのデプロイスクリプト整備
  • CloudFront 設定ドキュメントの整備

技術スタック

  • フロントエンド: Django テンプレート、JavaScript、Bootstrap 5、Webpack、Babel
  • バックエンド: Python 3、Django 5.2
  • データベース: PostgreSQL on AWS RDS
  • フォーム / UI: django-crispy-formscrispy-bootstrap5
  • タグ機能: django-taggit
  • ストレージ連携: django-storages + boto3(AWS S3)
  • 画像処理: AWS Lambda + Pillow
  • コンテナ実行基盤: AWS ECS(EC2 launch type)、Gunicorn + Nginx
  • CDN / エッジ: AWS CloudFront
  • DNS / 証明書: AWS Route 53 + ACM
  • シークレット管理: python-decouple、AWS SSM Parameter Store
  • コード品質: mypy(django-stubs)、flake8、black、isort

アーキテクチャ

ECS サービス(EC2 launch type)

  • 2 コンテナ構成:django(Gunicorn)と nginx(リバースプロキシ)
  • シークレットは AWS SSM Parameter Store から ECS タスク定義経由で注入
  • 注記: 本アプリはポートフォリオ用途のため、コスト最適化を優先し ALB は未使用です(月額約 16 ドルの削減)。実運用環境では ALB の導入を想定しています。また、RDS インスタンスは別プロジェクト(Tech-In-Bytes)と共有しています(月額約 20 ドルの削減)。

RDS(PostgreSQL)

  • Django のメインデータベース
  • ECS タスクとはプライベートネットワーク経由で接続

S3(Static & Media)

  • static/:Django の静的ファイル(collectstatic により配置)
  • processing/:アップロード直後の一時領域(Lambda のトリガー元)
  • media/:Lambda 処理済みの画像ファイル(WebP バリアント)

Lambda(画像処理)

  • S3 の processing/ プレフィックスへの書き込みイベントで Lambda が起動
  • Pillow により WebP バリアント(small / medium / original)を生成
  • 処理後のファイルを media/ プレフィックスに保存

CloudFront

  • サイト全体の HTTPS エンドポイント(ACM 証明書による SSL 終端)
  • /static/* / /media/* を S3 に振り分けるパスベースのキャッシュビヘイビア
  • それ以外のリクエストは ECS(Nginx)に転送

Route 53 + ACM

  • ドメインの A / ALIAS レコードを CloudFront ディストリビューションに向ける
  • ACM 証明書を CloudFront にアタッチし HTTPS を提供

スクリーンショット

ホームページ
ホームページ
レッスン検索ページ
レッスン検索ページ
レッスン詳細ページ
レッスン詳細ページ
登録済みレッスンページ
登録済みレッスンページ
レッスン開催日程の管理画面
レッスン開催日程の管理画面
レッスン参加者の管理画面
レッスン参加者の管理画面

デモ動画