- 概要
- デモ
- 主要機能
- 技術スタック
- こだわりの設計
- セットアップ方法
「レシピの森」は、冷蔵庫の余り物や予算、調理時間からAIが最適なレシピを提案してくれるWebアプリケーションです。単なるレシピ検索ではなく、「後片付けのラクさ(洗い物スコア)」の計算や、作った料理を記録するカレンダー機能など、自炊を楽しく継続するための機能を備えています。
(※ここに実際のアプリケーションのスクリーンショットや、操作中のGIFアニメーションを貼り付けます)
- AIレシピ提案画面
- お気に入り一覧画面
- 月間カレンダー&食費レポート画面
- AIレシピ生成: 予算・時間・食材などの条件をもとに、AIが独自のレシピを考案。
- 洗い物スコア算出: レシピの工程や使用する調理器具から「後片付けの面倒さ」を自動計算。
- お気に入り機能: 気に入ったレシピを保存し、いつでも見返すことが可能。
- 料理記録(カレンダー): 「作った!」ボタンを押すことでカレンダーに履歴が残り、月間の自炊回数と合計食費を自動で集計。
- ユーザー認証: JWTベースのログイン/サインアップ機能で個人のデータを安全に管理。
- フロントエンド: React, Vite, Tailwind CSS
- バックエンド: Java, Spring Boot
- データベース・O/Rマッパー: PostgreSQL, MyBatis
- インフラ・環境: Docker, Render (クラウドホスティング)
- 外部API: Gemini API (レシピ自動生成用)
本アプリケーションの開発においては、単に動くものを作るだけでなく、保守性の高いバックエンド設計とユーザー視点のフロントエンド設計にこだわりました。
データの予期せぬ変更によるバグを防ぐため、すべてのデータ転送オブジェクトをJavaの record クラス(不変オブジェクト)で設計しました。当初、MyBatisの仕様(遅延ロード)と record の相性が悪くマッピングエラーが多発しましたが、これを「Mapper(DB層)が複雑な画面用DTOを作ろうとしている設計の歪み」と捉え、アーキテクチャを根本からリファクタリングしました。
DBの結果と1対1で対応する**「軽量Entity」をMapperに返させ、Service層がそれらを組み立てて最終的な「画面用DTO」**を生成するという教科書通りの美しいレイヤー分離を実現しています。
サーバーのスケーラビリティを確保するため、セッションを使わないJWT(JSON Web Token)によるステートレス認証を実装しました。Spring Securityを用いて公開APIと非公開APIのアクセスを厳密に制御しています。また、フロントエンド(React Context)側でトークンの有効期限を監視し、期限切れの際は自動的にエラーメッセージとともにログイン画面へ誘導するなど、セキュアでありながらユーザーを迷わせないシームレスなUXを構築しました。
バックエンドのホスティングに利用している無料クラウドサービス(Render)は、一定時間アクセスがないとサーバーが休止し、次回の起動に数十秒かかるという制約(コールドスタート)がありました。 この待機時間によるユーザーの離脱(「アプリが壊れた」という誤解)を防ぐため、Reactからバックエンドへ5秒間隔で死活監視(ポーリング)を行う機能を実装しました。サーバーが立ち上がるまでの間、「シェフが準備をしています...」といった遊び心のあるアニメーションを画面下部に表示し、起動完了と同時にフェードアウトさせることで、技術的な弱点をUI/UXの工夫によって見事にカバーしました。
ローカル環境でアプリケーションを動かすための手順です。Dockerがインストールされていることを前提とします。
git clone https://github.com/Tom-myself/recommend-dish.git
cd recommend-dish# ビルドと起動(初回は少し時間がかかります)
docker compose up --build- フロントエンド (React):
http://localhost:3000にアクセスしてください。 - バックエンド (Spring Boot):
http://localhost:8080でAPIが稼働します。
docker compose down
# データベースのデータもリセットしたい場合は -v オプションを付けます
# docker compose down -v