ババ抜きに、革命を!

https://github.com/periotto3/rakko

Next.js

TypeScript

AWS

世界に没入できるリアタイババ抜きゲーム!!!

warisuno

zatunohito

Teba_eleven

星野瑞貴

g9gjf7lk5rs

推しアイデア

背景画像が毎回変わる!? 待機時間が楽しくなる!

作った背景

ゲームにAWSリソースをいろいろな意味で組み込みたかったから!!!

推し技術

AWSをつかってサーバーレスのみの構成です! ECSとかは甘え!!!

プロジェクト詳細

image# Topaz - AI背景生成オンラインババ抜き

リアルタイムでオンライン対戦可能なババ抜きにおいて、ルームごとにテーマを決定し、テーマに基づいた画像をAIが生成してプレイ画面の背景とするプロダクト

リポジトリ

https://github.com/periotto3/rakko

1. プロダクト概要

リアルタイムでオンライン対戦可能なババ抜きにおいて、ルームごとに別のテーマを決定し、テーマに基づいた画像をAIが生成し、プレイ画面の背景とするプロダクトを作成した。

アーキテクチャ図

image


2. 背景・テーマ決めの過程

ブレインストーミング

テーマ決め時に FigJam を利用してチームメンバー全員でブレインストーミングや案出しを行い、簡単な設計を進めた。 image

アイデアの変遷

  1. 初期案: 麻雀の採点アプリの作成
  2. 方向転換: AWSリソースを手札としたポーカーやババ抜き → しかし「画像/動画」というハッカソンテーマに沿わないことに気付く
  3. 転機: メンバーが NovelAI の Lorebook(物語設定を保持し、随時生成AIが参照する機能)を紹介
  4. 最終決定: そこから着想を得て「ゲーム画面のUIをAIで随時生成し、世界観を変える」というコンセプトが生まれた

アイデアを決めるのには苦労したが、メンバーの多様な知見を活かして独自性のあるコンセプトに辿り着いた。


3. チーム開発

開発体制と議論

  • FigJam を用いた全員でのブレインストーミング・設計
  • フロントエンドは二人でペアコーディングし、基本的に一人が Pull Request を作成し、もう一人がレビューしてマージするフローを採用
  • DI/DIP を活用して Mock とオンラインの共存を実現し、チーム間の並行開発を可能にした

議論:画像生成の設計方針

もともとカードと背景どちらもAIに別々に生成させる要件だった。生成完了をどう検知してユーザーに通知するかについて、チーム内で意見が分かれた。

提案者概要
DynamoDB でステータス管理メンバーAS3の状況を追跡する DynamoDB を導入し、ステータスで管理する
S3 ディレクトリのポーリング監視メンバーBS3のディレクトリ構造をポーリングして生成完了を検知する

客観的に見れば「ステータス管理が必要かどうか」が論点だったが、双方の提案の具体性が不十分で共通認識を持てず、論点を明確にした議論ができなかった。

振り返り: 次回は図や表にすべて書き起こし、議論に必要な情報を明示してから進めたい。


4. 技術詳細

4.1 フロントエンド

image image image image image

使用技術

カテゴリ技術バージョン
フレームワークNext.js16.1.6
UIライブラリReact19.2.3
言語TypeScript^5
スタイリングTailwind CSS^4
リンターESLint^9

ディレクトリ構成

src/ ├── app/ │ └── babanuki/ │ └── page.tsx ← 画面遷移の管理(親コンポーネント) └── features/ └── babanuki/ ├── components/ ← UI(画面・部品) ├── services/ ← バックエンドとの通信・ゲームロジック └── lib/ ← 純粋なゲームエンジン・型定義

こだわり

  • DI/DIP で Mock とオンラインを共存させ、バックエンド完成前からフロントエンド開発を並行して進められた
  • AWS公式の GitHub リポジトリからAWSリソースカードのアイコンを取得し、UIの完成度を高めた
  • アイコンではなくアバターを作成してUIの完成度を向上
  • プレイするカード(引く人と引かれる人)のトランプを拡大し、操作性を改善
  • features ディレクトリで機能ごとに分離
  • AWS Amplify にデプロイ
  • Bedrock の API から Claude Code を利用し、フロントエンド実装を加速
  • 二人でペアコーディング、Pull Request ベースのレビューフローを実施

苦労ポイント

  • 二人で並行作業していたため、依存関係の解決に時間がかかった
  • Coding Agent(Claude Code)で多くの実装が可能だったが、最適なUIを作ることは難しく、具体的な指示を出して何度もUIを作り直した
  • features ディレクトリへの機能分離が想定通りにできず、デバッグ時に複数ファイルの変更が必要になった

4.2 バックエンド - WebSocket サーバー

使用技術

カテゴリ技術
言語TypeScript
APIAPI Gateway (WebSocket)
コンピュートAWS Lambda
データベースAmazon DynamoDB
IaCAWS CDK

アーキテクチャ

image image

ディレクトリ構成(Clean Architecture)

backend/websocket/ ├── bin/ │ └── websocket.ts # CDKエントリーポイント ├── lib/ │ └── websocket-stack.ts # CDKスタック定義 ├── lambda/ # Lambda関数(クリーンアーキテクチャ) │ ├── index.ts # Lambdaハンドラーエントリーポイント │ │ │ ├── presentation/ # 🔵 プレゼンテーション層 │ │ ├── handler/ │ │ │ ├── connectHandler.ts # WebSocket接続ハンドラー │ │ │ ├── disconnectHandler.ts # WebSocket切断ハンドラー │ │ │ └── messageHandler.ts # メッセージルーティング │ │ └── dto/ │ │ ├── clientMessage.ts # クライアント→サーバーのDTO │ │ └── serverMessage.ts # サーバー→クライアントのDTO │ │ │ ├── application/ # 🟢 アプリケーション層(ユースケース) │ │ ├── useCase/ │ │ │ ├── connectUseCase.ts # 接続ユースケース │ │ │ ├── disconnectUseCase.ts # 切断ユースケース │ │ │ ├── joinGameUseCase.ts # ゲーム参加ユースケース │ │ │ ├── drawCardUseCase.ts # カードを引くユースケース │ │ │ └── getStateUseCase.ts # 状態取得ユースケース │ │ └── error/ │ │ └── applicationError.ts # アプリケーション例外 │ │ │ ├── domain/ # 🟡 ドメイン層(ビジネスロジック) │ │ ├── model/ │ │ │ ├── card/ │ │ │ │ ├── card.ts # カードエンティティ │ │ │ │ └── deck.ts # デッキ(カードの集合) │ │ │ ├── player/ │ │ │ │ ├── player.ts # プレイヤーエンティティ │ │ │ │ └── publicPlayer.ts # 公開プレイヤー情報 │ │ │ ├── game/ │ │ │ │ ├── game.ts # ゲーム集約ルート │ │ │ │ ├── gamePhase.ts # ゲームフェーズ(値オブジェクト) │ │ │ │ ├── gameRepository.ts # ゲームリポジトリIF │ │ │ │ └── ranking.ts # ランキング │ │ │ ├── connection/ │ │ │ │ ├── connection.ts # 接続エンティティ │ │ │ │ └── connectionRepository.ts # 接続リポジトリIF │ │ │ ├── matchmaking/ │ │ │ │ ├── matchmaking.ts # マッチメイキングエンティティ │ │ │ │ ├── matchmakingRepository.ts # マッチメイキングリポジトリIF │ │ │ │ ├── rouletteSlot.ts # ルーレットスロット │ │ │ │ ├── promptBuilder.ts # プロンプト生成 │ │ │ │ └── themeData.ts # テーマデータ │ │ │ ├── notification/ │ │ │ │ └── notificationService.ts # 通知サービスIF │ │ │ └── imageGeneration/ │ │ │ └── imageGenerationService.ts # 画像生成サービスIF │ │ └── error/ │ │ └── domainError.ts # ドメイン例外 │ │ │ └── infrastructure/ # 🔴 インフラストラクチャ層(実装詳細) │ ├── dynamodb/ │ │ ├── dynamoDBClient.ts # DynamoDBクライアント │ │ ├── connectionDynamoDBRepository.ts # 接続リポジトリ実装 │ │ ├── gameDynamoDBRepository.ts # ゲームリポジトリ実装 │ │ └── matchmakingDynamoDBRepository.ts # マッチメイキングリポジトリ実装 │ ├── websocket/ │ │ └── apiGatewayNotificationService.ts # 通知サービス実装(API Gateway) │ └── http/ │ └── httpImageGenerationService.ts # 画像生成サービス実装(HTTP) │ ├── test/ # テスト │ ├── actions.test.ts │ ├── game-logic.test.ts │ └── websocket.test.ts ├── docs/ # ドキュメント ├── package.json ├── tsconfig.json ├── cdk.json └── jest.config.js

こだわり

  • フルサーバーレス構成: ECS や EC2 を使わず、API Gateway + Lambda + DynamoDB で構成
    • ユーザー数やアクセス数を考慮する必要がなく、ビジネスロジックに集中できた
    • ユーザー数が急激に増加しても完全にオートスケールするため、大規模サービスにも対応可能
  • Clean Architecture の採用
    • DI/DIP により Mock サーバーやデバッグ用 API サーバーとの切り替えが容易
    • UseCase でルームマッチメイキング処理や生成待機などの処理フローを明確に記述
    • ゲームロジックをインフラ層から完全に分離
    • テストを記述し品質を担保
    • UseCase が肥大化しないよう責務を分割
  • AWS CDK: IaC から Lambda の実装までフル TypeScript で統一

苦労ポイント

  • WebSocket: 従来は Socket.io を利用していたが、API Gateway は純粋な WebSocket のみ対応のため、Room 処理やイベントハンドラの作成・デバッグに多くの時間を費やした
  • 画像生成との連携: 通常の HTTP 通信であれば非同期での画像生成・表示は容易だが、WebSocket での実装のため、画像生成完了の待機処理が複雑になった
    • 生成完了時のユーザーへのイベント通知、エラー時の再生成、他ルームに影響しないステート管理などが必要になった

4.3 バックエンド - 画像生成サーバー

使用技術

カテゴリ技術
コンピュートAWS Lambda
AI モデルAmazon Bedrock (stability.sd3-5-large-v1:0)
ストレージAmazon S3

アーキテクチャ

image

こだわり

  • AIに頼らず手動でコーディングし、技術の深い理解を重視した

苦労ポイント

  • モデル選定: Amazon Bedrock の Nova 系モデルではガードレールに引っかかり、鋭い単語を含むプロンプトで画像生成できない問題が発生 → Stability AI のモデルに切り替えることで、自由度の高い画像生成を実現
  • S3 の学習コスト: S3 の概念・仕組み(Bucket と Key の関係、ストレージとディレクトリ構造の考え方)を初歩から学ぶ必要があった

4.4 Bedrock / SageMaker 周り

使用技術

カテゴリ技術
AIAmazon Bedrock, Amazon SageMaker
コンテナAmazon ECR
ストレージAmazon S3

こだわり

  • ローカルでの Docker イメージビルド → ECR Push が遅すぎたため、EC2 インスタンスを立ててそこでビルド・Push を行うことで高速化
  • Hugging Face の巨大モデルでは推論が重すぎるため、軽量で safetensors 化されたモデルの中から自然言語とタグの両方が使用可能なものを選定

苦労ポイント

  • 初めて使う技術ばかりで、IAM の概念からハンズオンで学習する必要があった
  • 当初 Workshop Studio は us-east-1 のみ対応と思い込んでおり、モデルの対応リージョン調査やモデルIDの指定方法で約1時間を要した
  • 16:9 画像の生成ができない問題や、プロンプト制約による表現力の限界に直面し、途中からオープンソースで商用利用可能なモデルを SageMaker に Deploy する方針に切り替えた

5. まとめ

チーム開発の工夫

  • FigJam でのブレインストーミングによる全員参加のアイデア出し
  • Pull Request ベースのコードレビューフロー
  • DI/DIP によるフロントエンド・バックエンドの並行開発
  • Coding Agent(Claude Code via Bedrock)を活用した開発効率の向上

技術的チャレンジ

  • フルサーバーレス × Clean Architecture によるスケーラブルな設計
  • WebSocket を用いたリアルタイムオンライン対戦
  • AI 画像生成とリアルタイム通信の融合
  • IaC から実装までフル TypeScript で統一

議論と学び

  • 画像生成の設計方針について活発な議論が行われ、ステータス管理の必要性を巡って複数のアプローチを比較検討した
  • 議論では具体性が不足したことを振り返り、図表を用いた明示的な議論の重要性を学んだ
  • 新しい技術(API Gateway WebSocket, SageMaker, Bedrock)への挑戦と、チーム内での知見共有が成長につながった

おまけ: Claude Code on Amazon Bedrock

https://code.claude.com/docs/en/amazon-bedrock

次のAWSハッカソンで使いたいと思ったので、備忘録として残しておきます。

  • claudeのインストール 使用したことがなかったので、インストールから始めました。
curl -fsSL https://claude.ai/install.sh | bash
  • AWS認証 aws-cliを使用しました。
aws configure
  • Amazon Bedrockを使用するための設定 今回は、提供された環境で初めからSonnet 4.5が解放されていたので、特にAWS側では設定は不要でした。 Bedrockを使用するために、環境変数の設定が必要です
# ClaudeでBedrockを使用するための設定 export CLAUDE_CODE_USE_BEDROCK=1 export AWS_REGION=us-east-1 # 使用するモデルの設定 # 例: 各モデルのデフォルトを特定のBedrock推論プロファイルIDに固定 export ANTHROPIC_DEFAULT_SONNET_MODEL='us.anthropic.claude-sonnet-4-5-20250929-v1:0'

常にBedrockを使いたい場合は~/.bashrcで設定しましょう。

これでclaudeで起動すると、Bedrock経由でClaudeを使用できます! image

warisuno

@MountWario