【個人開発】オンラインディベートアプリ「DebateMatch」を開発しました！AI講評機能あり

## 1. はじめに

**オンラインディベートアプリ「DebateMatch」** を開発しました。

DebateMatch: [https://debate-match.com](https://debate-match.com) (<- ゲストログイン機能を追加しました!)

この記事では、

*   DebateMatchが**どのような課題を解決し、どんな体験を提供するか** (アプリ紹介)
*   開発で利用した**技術スタック**とその**選定理由**
*   特に**こだわった・苦労した技術的なポイント** (websocket、AI連携、接続管理など)

について共有します。

**DebateMatchとは:**

*   「ディベートの練習をしたいけど、相手が見つからない…」
*   「自分の議論力を客観的に知りたい」
*   「オンラインで気軽にディベート練習がしたい」
*   「違う意見の人と建設的な議論がしたい」

DebateMatchは、このような世界中のディベーターの課題を解決するために開発しました。

**主な機能:**

*   **リアルタイム対人ディベート:** ルームを作成または参加し、他のユーザーとオンラインでディベート！
*   **AIディベート:** AIを相手にいつでも気軽にディベート！
*   **AIによる客観的評価:** ディベート終了後、AIがあなたの議論を分析し、勝敗判定、論理構成、改善点などをフィードバック！

**デモ動画** 👇️

<blockquote class="twitter-tweet" data-media-max-width="1920" data-dnt="true"><p lang="ja" dir="ltr">【新サービス】DebateMatch公開！<br><br>議論力が鍛えられるオンラインディベートアプリ<br><br>✅他ユーザーとチャットでディベート<br>✅AIによる講評・フィードバック<br>✅AIとの練習で気軽に上達<br>✅日本語 / 英語対応<br><br>無料でスタート！<br>🔗<a href="https://t.co/VrvWRKU2lQ">https://t.co/VrvWRKU2lQ</a><a href="https://twitter.com/hashtag/%E3%83%87%E3%82%A3%E3%83%99%E3%83%BC%E3%83%88?src=hash&amp;ref_src=twsrc%5Etfw">#ディベート</a> <a href="https://twitter.com/hashtag/%E8%AB%96%E7%90%86%E7%9A%84%E6%80%9D%E8%80%83?src=hash&amp;ref_src=twsrc%5Etfw">#論理的思考</a> <a href="https://twitter.com/hashtag/AI?src=hash&amp;ref_src=twsrc%5Etfw">#AI</a> <a href="https://t.co/BTilHsP3NE">pic.twitter.com/BTilHsP3NE</a></p>&mdash; DebateMatch JP (@debatematch_jp) <a href="https://twitter.com/debatematch_jp/status/1918368557760680445?ref_src=twsrc%5Etfw">May 2, 2025</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## 2. 開発したWebアプリケーション「DebateMatch」について

### 開発の背景・動機

<details>
<summary>長くなってしまったので読みたい人だけ読んでみてください</summary>
もともと私は議論が好きで、オンラインでもっと気軽に、そして建設的に議論できる場所がないかと考えていました。既存のSNS、例えばTwitter（現X）などでは、自由闊達な意見交換ができる一方で、時に議論が本筋から逸れたり、建設的とは言えない方向に進んでしまったりすることも少なくありません。「もっと集中して、質の高い議論ができる場所が欲しい」と感じていました。

そこで、「秩序ある議論が安心してできるオンラインプラットフォームを自分で作れないか？」と思い立ったのが、DebateMatch開発の最初のきっかけです。自分の欲しいものを作ることで、同じような思いを持つ人の役にも立てるかもしれない、と考えました。

しかし、ただ新しいプラットフォームを作るだけでは、結局SNSと同じような課題に直面するのではないか、という懸念もありました。健全な議論を促進するためには、何らかの共通認識となる「ルール」が必要だと考えました。

様々なルールを検討する中で、公平性や客観性を重視し、論理的な思考や構成力を鍛えるのに適した「競技ディベート」 のルール体系に着目しました。競技ディベートには確立されたフォーマットや時間管理があり、これを導入することで、単なる自由な議論の場ではなく、より構造化され、質の高い議論の実践・練習ができるプラットフォームになるのではないかと考えました。

そこで、アプリの方向性を「競技ディベートの練習・対戦プラットフォーム」と定め、特にディベート部の方や大会を目指す方々、あるいは論理的な議論スキルを高めたいと考えている方々にとって役立つツールとなることを目指して開発を進めることにしました。さらに、練習相手が見つからない、客観的なフィードバックが得にくいといった課題も解決するため、**AIとの対戦機能やAIによる評価機能**を盛り込むことにしました。

これが、AIと対戦・評価できるWebアプリ「DebateMatch」のコンセプトが固まった経緯です。
</details>

### アプリ概要と主な機能

DebateMatchは、オンラインでディベート練習を行い、議論力向上をサポートするWebアプリケーションです。

*   **ルーム機能:** ディベートのトピックや形式を設定してルームを作成・公開したり、既存のルームに参加したりできます。
*   **リアルタイムディベート:** 設定されたディベート形式（持ち時間、発言順など）に沿って、肯定側・否定側に分かれてテキストベースでリアルタイムにディベートを行います。
*   **AIディベート:** 対戦相手が見つからない時でも、AIを相手にディベート練習が可能です。
*   **AI評価・フィードバック:** ディベート終了後、議論内容全体をAIが分析。勝敗判定とその理由、各サイドへの具体的なフィードバックを提供し、客観的な視点から議論を振り返ることができます。
*   **多言語対応:** 現在、日本語と英語に対応しています。
*   **ディベート履歴:** 過去のディベートの記録やAI評価結果をいつでも確認できます。
*   **ユーザー認証:** メールアドレス/パスワードに加え、Googleアカウントでのログインも可能です。

### ターゲットユーザー

*   ディベート初心者〜上級者
*   競技ディベート大会に向けて練習したい学生
*   議論力・論理的思考力を鍛えたい社会人
*   気軽にディベートを楽しみたい方
*   自分の論理を試したい方
*   議論が好きな方

### アプリへのリンク

ぜひ、DebateMatchを体験してみてください！フィードバックもお待ちしています！

**DebateMatch:** [https://debate-match.com](https://debate-match.com/)

## 3. 技術スタックと選定理由

DebateMatchの開発で採用した主な技術スタックです。

*   **バックエンド:** Laravel 11 (PHP 8.3)
*   **フロントエンド:** Livewire 3, Alpine.js, JavaScript, Tailwind CSS, Vite
*   **データベース:** MySQL
*   **キャッシング & キュー:** Redis, Laravel Horizon
*   **リアルタイム通信:** Pusher, Laravel Echo
*   **認証:** Laravel Breeze, Laravel Socialite (Googleログイン)
*   **AI連携:** OpenRouter API (バックエンドでGemini APIを利用)
*   **インフラ:** AWS (EC2, RDS, Route 53, SES, Cloud Watch), Docker, Docker Compose, Nginx, Supervisor

主な技術の選定理由は以下の通りです。

*   **Laravel:**
    *   PHPフレームワークのデファクトスタンダードであり、エコシステムが充実。
    *   ドキュメントやコミュニティ情報が豊富で、個人開発でも学習・実装を進めやすい。
    *   Eloquent ORM、キュー、イベント、ブロードキャストなど、Webアプリ開発に必要な機能が一通り揃っており、生産性が高い。
*   **Livewire:**
    *   Laravelとの親和性が非常に高く、PHP中心でSPAライクなインタラクティブUIを効率的に構築できる。
    *   JavaScriptのコード量を抑えつつ、リアルタイムな更新（チャット、参加者リスト、タイマーなど）を実現できる。Alpine.jsとの連携もスムーズ。
*   **Pusher (リアルタイム通信):**
    *   WebSocketを簡単に利用できるマネージドサービス。サーバー側の負担を軽減できる。
    *   Laravel Echoとの連携が容易で、イベントブロードキャストをスムーズに実装できる。
    *   Presence ChannelやWebhookを活用し、ユーザーのオンライン/オフライン状態管理や接続管理に利用。
*   **OpenRouter (AI連携):**
    *   複数のLLM（今回はGoogleのGemini）を統一的なAPIで利用できる。
    *   AIディベートの応答生成や、ディベート終了後の評価・フィードバック生成というコア機能の実装に活用。モデルの切り替えや比較検討が容易になることを見越して採用。
*   **Redis (キュー & キャッシュ):**
    *   AI評価やAI応答生成など、時間のかかる可能性のある処理を非同期化し、ユーザー体験を損なわないようにするためキュー(Laravel Horizonで管理)を利用。
    *   セッション管理や頻繁にアクセスされるデータのキャッシュに利用し、パフォーマンスを向上。
*   **Docker:**
    *   開発環境(Laravel Sail)と本番・ステージング環境をコンテナ化。環境差異による問題を最小限に抑え、デプロイプロセスを簡素化。
    *   Nginx, PHP-FPM, Redis, MySQL, Supervisor(Horizon用)をコンテナで管理。

## 4. こだわった点・苦労した点

DebateMatchの開発では、特に以下の点に注力・苦労しました。
[GitHubリポジトリ](https://github.com/rytkhs/debatematch)

### 4.1. リアルタイムなディベート体験の実現 (Pusher + Echo + Livewire)

ディベートの臨場感を出すために、リアルタイム性は非常に重要でした。

*   **メッセージ同期:** Livewireコンポーネント(`Debates\Chat`)内でメッセージを送信すると、`DebateMessageSent`イベントが発火。これがPusher経由でブロードキャストされ、他の参加者の画面でも`#[On("echo-private:debate.{debate.id},DebateMessageSent")]`でイベントを検知し、メッセージリストをリアルタイムに更新します。
*   **パート進行:** ディベートの各パートには制限時間があります。サーバー側で`AdvanceDebateTurnJob`を遅延実行し、終了時刻になったら次のパートへ移行させます。パートが進行すると`TurnAdvanced`イベントがブロードキャストされ、各クライアントのタイマー表示(`debate/countdown.js`)や現在のパート表示(`Debates\Timeline`, `Debates\Header`)が更新されます。
*   **参加者表示:** ユーザーの入退室時には`UserJoinedRoom`/`UserLeftRoom`イベントがブロードキャストされ、Livewireコンポーネント(`Rooms\Participants`)がリアルタイムに参加者リストを更新します。

### 4.2. AIによる評価と応答生成 (OpenRouter + Gemini API + Queue)

AI機能はDebateMatchのコアバリューです。

*   **AI評価:** ディベートが終了すると(`DebateFinished`イベント)、`EvaluateDebateJob`がキューに追加されます。このジョブ内で、`AIEvaluationService`がディベートの全メッセージ履歴と評価基準プロンプト(`config/ai_prompts.php`で管理)をOpenRouter経由でGemini APIに送信し、評価結果を取得・保存します。評価完了後、`DebateEvaluated`イベントをブロードキャストし、ユーザーに結果ページへの遷移を促します。
*   **AIディベート応答:** AIディベートでは、ユーザーの発言後、`GenerateAIResponseJob`がキューに追加されます。`AIService`がこれまでの議論の流れを考慮したプロンプトを生成し、AIに応答を作成させ、`DebateMessage`として保存・ブロードキャストします。これにより、ユーザーはAIとの自然な対話形式でディベート練習ができます。
*   **非同期処理:** AIの応答生成や評価は時間がかかる場合があるため、Laravel Horizonを利用したキューイングで非同期に処理し、ユーザーの操作をブロックしないようにしました。

### 4.3. 接続安定性の確保 (Heartbeat + Pusher Webhook + Job)

オンラインサービス、特にリアルタイム性が求められるアプリでは、ユーザーの接続状態を正確に把握し、切断に適切に対応することが重要です。

*   **ハートビート:** クライアント側(`heartbeat-service.js`)から定期的に`HeartbeatController`へリクエストを送信。サーバー側では`ConnectionManager`サービスを通じて、ユーザーの最終アクティブ時刻をキャッシュ(Redis)に記録します。
*   **Pusher Webhook:** PusherのWebhook (`member_added`, `member_removed`) を利用し、ユーザーがPresence Channel (`presence-room.{roomId}`, `presence-debate.{debateId}`) に参加/退出したことを検知。`PusherWebhookController`で受け取り、`ConnectionManager`に通知します。
*   **切断検知と対応:** `ConnectionManager`は、ハートビートの途絶やPusher Webhookからの退出通知を受け取ると、一定時間後にユーザーが本当に切断したかを確認します。
    *   **ルーム待機中:** `RoomConnectionService`がユーザーをルームから退出させ、必要に応じて`UserLeftRoom`イベントを発火します。
    *   **ディベート中:** `DebateConnectionService`が`HandleUserDisconnection`ジョブをディスパッチします。このジョブは、一定時間待機してもユーザーが再接続しない場合、ディベートを強制終了(`DebateTerminated`イベント)させる処理を行います。これにより、相手が切断してもディベートが不必要に継続するのを防ぎます。
*   **再接続:** ユーザーが再接続した場合、ハートビートが再開され、`ConnectionManager`がこれを検知。ディベート中であれば、スケジュールされていた`HandleUserDisconnection`ジョブをキャンセルし、接続ログを更新します。
*   **接続状態表示:** Livewireコンポーネント(`ConnectionStatus.php`)で、自分や相手のオフライン状態を検知し、UIに警告を表示します。
*   **接続ログ:** ConnectionLogモデルとConnectionManagerサービスで、ユーザーの接続/切断/再接続イベントやIPアドレス、User-Agentなどのメタデータを記録し、問題発生時の調査や分析（ConnectionAnalyticsController）に役立てています。

### 4.4. LivewireによるインタラクティブUI

前述のリアルタイム機能に加え、以下のUIもLivewireで実装し、インタラクティブな操作感を実現しました。

*   **ステータス表示:** ルームやディベートの状態 (`Rooms\Status`)
*   **メッセージ入力:** (`Debates\MessageInput`)
*   **ボタン制御:** ディベート開始ボタンの状態制御 (`Rooms\StartDebateButton`)
*   **Flashメッセージ:** 操作結果などの通知 (`FlashMessage.php`)

### 4.5. 多言語対応

初期リリース直後、日本よりも英語圏からのアクセスが多かったため、急遽英語対応することにしました。Laravelの多言語対応機能を利用しています。

*   UI上のテキストは`lang/`ディレクトリ以下の言語ファイルで管理 (`__('messages.some_key')`)。
*   利用規約やプライバシーポリシーなどの長文コンテンツは`resources/markdown/{locale}/`にMarkdownファイルとして配置し、表示時に読み込んでいます。
*   `SetLocale`ミドルウェアで、ユーザーの選択言語（セッション）やブラウザの言語設定(`Accept-Language`)に基づき、表示言語を自動的に切り替えます。

## 5. 今後の展望

今後、以下のような機能追加や改善を考えています。

*   **音声ディベート機能:** テキストだけでなく、音声でのディベートも可能に。(チャットの音声入力に対応しました!)
*   **レーティングシステム:** ユーザーの実力を可視化。
*   **チームディベート:** 2対2などのチーム戦形式に対応。
*   **ディベート形式の追加:** 様々なフォーマットに対応。
*   **UI/UXの継続的改善:** ユーザーフィードバックを元に、より使いやすく。
*   **観戦機能:** 他のユーザーのディベートを観戦できる機能。
*   **結果の共有機能:** ディベート結果をSNSで共有。

「こんな機能がほしい！」「ここが使いにくい」といったご意見・ご感想があれば、ぜひお気軽にお寄せください！

## 6. おわりに

個人開発は大変な面もありますが、自分の作りたいものを形にしていく過程は非常に楽しく、学びも多かったです。特に、websocketやAI連携、非同期処理などは挑戦しがいのある技術要素でした。

この記事が、これから個人開発を始める方や、同じような技術に興味を持つ方への何かしらのヒントになれば嬉しいです。

**改めて、DebateMatchをぜひ使ってみてください！**

**DebateMatch:** [https://debate-match.com](https://debate-match.com)

GitHub: [https://github.com/rytkhs/debatematch](https://github.com/rytkhs/debatematch)