はじめに
(アプリ開発の備忘録です。読者のターゲットは将来の自分です。)
僕はお正月に スロットで お金を使ってしまいました。2026年はお金を貯める年にしようと決めたのもその瞬間です。
まず最初にお金の収支をつけ始めました。
いくらの収入と、いくらの支出があったのかを明確にすることで目処を立ててお金を貯められると思ったからです。
元々家計簿アプリを使用していましたが、グラフ化をしたいと思い、Notionで作ろうと思いました。ですが、データとチャートの連携がうまくいきませんでした。
そこで、この機会に web アプリを作ることにしました。自分自身に実務経験が殆ど無いため、今回は色々なことをAIに聞き、フィーリングのまま進めていくことにします。
構想としてはいくつかに記事を分けて、制作編/リファクタ編/全部AI駆動編/ほとんど人の手編などを考えていて、最終的にAI時代にどう制作するとよいものができるのか知見を得たいと思います。得られなかったらすみません。
完成した家計簿のデモ動画は下記です。
デモ動画
目次
- 流れについて
- 企画
- 要件定義
- 実装
- 総括
流れについて
この章では、今回の開発をどのように行っていくかを整理します。
個人で web アプリを作るのなら、Bolt.new にぶん投げれば済みそうですが、せっかくお仕事でプログラミングをしているのだから、実際にお金をもらって開発をしているようなステップを踏もうと思います。
しかし、お金をもらった開発プロセスがわからないので Gemini に聞こうと思います。
AI の回答
商用のソフトウェアの開発をした経験はないため、実際のプロセスをAIに聞いてみます。
アプリ作成工程の比較表(Gemini vs ChatGPT)
| 番号 | 工程 (Gemini) | 成果物 (Gemini) | 工程 (ChatGPT) | 成果物 (ChatGPT) |
|---|---|---|---|---|
| 1 | 企画・システム化計画 | 投資対効果(ROI)算出、現行業務分析書、ビジネス要件定義 | 企画・ゴール定義 | 企画書/PRD、ユースケース、KPI、初期SLO草案、体制図(RACI) |
| 2 | 要件定義 (RD) | 非機能要件定義書(可用性・セキュリティ等)、機能要件一覧 | 要件定義 | 要件定義書、API要件、データ分類(機密/個人情報)、受入基準(DoD) |
| 3 | 外部設計 / UI・UX設計 | 画面遷移図、ワイヤーフレーム、インフラ基本構成図 | アーキテクチャ設計 | アーキ図、データフロー図、脅威モデル、ADR(設計判断記録) |
| 4 | 内部設計 (詳細設計) | DB設計書(ER図)、API定義書、セキュリティ実装方針 | セキュア開発プロセスの組み込み | セキュア開発標準、CI/CD品質ゲート、SBOM運用ルール |
| 5 | 開発・実装 / 単体テスト | ソースコード、ユニットテストコード、レビュー記録 | 実装 | アプリ実装、IaC(インフラ構成コード)、テストコード、レビュー記録 |
| 6 | 結合テスト / システムテスト | 結合テスト仕様書・結果報告書、性能テストレポート | テスト・検証 | テスト計画/結果、性能レポート、脆弱性レポート、是正計画 |
| 7 | 運用テスト・受入テスト | 受入テスト結果報告書、本番移行判定書 | リリース管理 | リリースノート、変更記録、ロールバック手順、承認ログ |
| 8 | 移行・本番稼働 | データ移行計画書、切り戻し(ロールバック)手順書 | 運用 (Operate) | 監視設計、Runbook(手順書)、インシデント手順、ポストモーテム |
| 9 | 運用・保守・監視 | ログ監視設定、パッチ適用記録、改善バックログ | 継続的改善 (Improve) | DORA指標レポート、セキュリティ成熟度評価、改善バックログ |
大枠は企画 -> 要件定義 -> 設計 -> 実装 -> テスト -> 運用 ですね。
これに沿って今回は開発していこうと思います。
企画
この章では、作りたいアプリに対して分析を行います。
なぜ作るのか
ビジネス背景と課題(現行業務分析): 現在の課題として、お金の収支が管理できていない。
投資対効果(ROI): 効果は無駄遣いを抑えられるため、月+5万円くらいでしょうか。開発費用は無いため、投資対効果は爆発します。
KPI(重要業績評価指標):使途不明なお金が月に2万円以下、また入力継続率100%
差別化要素:貯まったお金がどのようなモノと等価か把握できるように、モチベーション・ビューアというモチベーション向上ページでも作り、貯まったお金とどのようなモノが買えるのか見られるページを作る
「誰が、どのように使うか」を具体化する(プロダクト定義)
PRD(プロダクト要求仕様書「この製品は何を解決し、何を実現するか」をまとめます。): お金の収支が管理できていないという現状を解決し、ユーザーのお金の流れについて透明性を実現する。
ユースケース「利用者がシステムを使って、具体的にどのような操作を行い、どのような結果を得るのか」というシナリオを描きます。: ユーザーがアプリのURLにログイン->IDとパスワードを入力->お金の収支をUI上で入力し保存する->チャートページに遷移し、チャートを確認できる
「どの程度の品質を求めるか」の初期合意(サービスレベル)
初期SLO(サービスレベル目標)草案 「24時間365日止まってはいけないのか」「週に1回のメンテナンス停止は許容されるのか」といった、サービスの稼働目標を仮決めします。: 稼働率90%(月間80時間の停止を許容)
データ分類: 扱うデータが「個人情報」や「機密情報」に該当するかを確認し、必要なセキュリティレベルを想定します。金銭面は個人情報なので、セキュリティ的に守るため、DBの暗号化を考える。
「誰が責任を持つか」を決める(体制構築)
RACI図の作成 誰が「実行責任者 (R)」で、誰が「承認者 (A)」なのかを明確にします。これにより「誰に相談すればいいかわからない」という事態を防ぎます。: 仕事の責任を直接担う実行責任者は僕になります。また、経営陣や取引先などのプロジェクト関係者に進捗や結果を報告する説明責任者も僕が適任でしょう。作業や成果物についてメンバーから相談を受け、サポートを行う役割である協業先は、必要な専門知識や経験がある人が望ましいためGeminiとChatGPTにしましょう。作業や成果物などを実行責任者から報告を受けるのもGeminiとChatGPTにしましょう。受けつけた内容に問題をみつけたときには説明責任者へ連絡を行ってもらいます。と思ったのですが、AIは意思決定の責任も実行の責任も負えないため、自分が行います。結局、責任の所在という点でAIと人間は差別化されるのかもしれませんね。
体制図 (社内のステークホルダーだけでなく、外部パートナーやインフラ担当などを含めた全体像を描きます。): 作業者:僕
下書きをGeminiに投げたところ、「言葉は並んでいますが、中身がスカスカで、このままでは確実に挫折するか、誰も使わないゴミが出来上がります。」とのことでした。
要件定義
この章で定義する要件については下記の4項目です。
- 機能要件の定義
- 非機能要件の定義
- 画面要件
- データ要件
です。再び一つずつ潰していきましょう
機能要件の定義
ここではシステムが提供する機能を全て洗い出します。
- 入力機能
- お金の支出について、日付・金額・カテゴリ・用途・メモ・支払い済みかそうではないかを保存できる
- チャート機能
- x軸単位が月、y軸単位が円のグラフで、折れ線グラフとして貯まったお金が見られる。また、収入と支出を棒グラフでも表示できる。チャートは二つで、それを貯まったお金のみ、収入のみ、支出のみ、収入と支出、収入と支出と折れ線グラフでフィルタできる。
- 現在までの確定したチャートと、支払い済みではないお金も盛り込んである予測チャートの二種類
- モチベーション機能
- 欲しいもの(名前、金額)を登録できる。
- やらないこと
- 支払いアプリとの連携(難しそうなので)。スマホで見られるようなレスポンシブ対応(いつかやる)
非機能要件の定義
- 認証
- 自前でID/PWを管理する
- バックアップ
- 取らない
- パフォーマンス
- 500件のデータが入っても、チャートが3秒以内に表示されること
画面要件・UI/UX
ここからやっと画面に入れます。いきなりFigmaや画面モックを作ると失敗してしまいがちらしいです。というかうまくいきませんでした。なので、考えられる限りのシナリオをここにまとめて行こうと思います。
シナリオ1
ログイン->コンビニで1000円使ったので、カレンダーの日付をクリック->ポップアップが開き、日付(カレンダーの日付)が自動入力、金額を入力、カテゴリをプルダウンから選択、用途を入力、メモを入力、確定済みのチェックボックスをクリックして保存ボタンを押す->カレンダーの該当日に、金額と収入か支出かが表示される->「チャート画面へ」ボタンをクリック->収入・支出・貯金の三つのチェクボックスと期間が表示され、その下にチャートが表示される。デフォルトは貯金にチェック、期間に過去半年と未来半年が入っていて、チャートが見られる。スクロールすると下にも同じようなチェックボックスとチャートがあり、こちらは未支払いのものもチャート化されている。
シナリオ2
ログイン->毎月20日にお給料が入るので、収支を作成ボタンをクリック->ポップアップが開き、日付を入力、金額を入力、カテゴリをプルダウンから選択、用途を入力、メモを入力、未確定のチェックボックスをクリックして保存ボタンを押す->カレンダーの該当日に、金額と収入か支出かが表示される->「チャート画面へ」ボタンをクリック->未確定の方のチャートで、支出が確認できる
シナリオ3
ログイン->トップページからモチベーションページにボタンでアクセス->モチベーションページに、未確定(確定+未確定の収入-確定+未確定の支出)の貯金額が表示されている->欲しいものを登録ボタンでポップアップが開き、名称と金額を入力することで、モチベーションページに表示される。
シナリオ4
ログイン->支払い予定だったが支払わなくて良くなったため、登録されているものを修正したい。カレンダーの下には2026年という文字と各月の収入、支出が表示されている。そこから2月の支出までスクロールし、該当する支出をクリック。入力の時と同じようなポップアップが開き、ポップアップ内の削除ボタンを押すことで削除や修正できる。
ここまでシナリオを考えてきましたが、シナリオを詰めることでAIにぶん投げればDB設計やAPI設計などができそうですね。ここから、画面一覧と各画面の項目要件を作成します。
- ログイン画面
- idとパスワードを入力し、DBに登録されているかチェックして通す
- 収支入力画面
- カレンダー、収支入力ポップアップ、選択された年の収支一覧
- チャート画面
- チェックボックス3つ、確定済みのチャート、未確定も含むチャート、期間選択欄
- モチベーション画面
- 年末までに貯まるお金、欲しいものと金額
こんな感じで良いでしょうか。ワイヤーフレームは大学ノートに書きました。
さて、データ要件について考えていきます。DB設計についてはやったことがないので、どうすれば良いかAI先生に聴きながらやります。ちなみに、ER図は非常に苦手です。
エンティティの洗い出し
システムが何を保存しなければいけないのかまとめます。ユーザー、入出金明細でしょうか
各項目の属性の定義も行いましょう。金額は整数、日付は時分まで考慮しないためDATE型、カテゴリは文字列、用途は文字列、メモは文字列、確定/未確定は真偽地、のような形でしょうか
また、欲しいものテーブルとして、欲しいものの名称は文字列、金額は整数ですね。
リレーションにも触れていきます。一人のユーザーは複数の明細を持ちます。一つの明細は日付、金額、カテゴリ、用途、確定/非確定を持ちます。
カテゴリはユーザーが追加できるようにします。どんどん追加されていく予定です。
AIによると、カテゴリを文字列としてテーブルに直接書き込むのはよくなく、カテゴリIDとして切り出す方が良いみたいです。「コンビニ」と「コンビニ」で異なってしまうためです。また、transactionに収入か支出か持たせようと思っていたのですが、食費かつ収入として登録できてしまうため、カテゴリに持たせた方が良いとのことです。
データ要件を整理します。
users
| カラム名 | 型 | 説明 |
|---|---|---|
| id | Int | ユーザーID |
| String | ログインID | |
| password | String | ハッシュ化されたパスワード |
categories
| カラム名 | 型 | 説明 |
|---|---|---|
| id | Int | カテゴリID |
| user_id | Int | 誰が作ったカテゴリか |
| name | String | カテゴリ名(食費、給与など) |
| is_income | Boolean | 収入(true)か支出(false)のカテゴリか |
transactions
| カラム名 | 型 | 説明 |
|---|---|---|
| id | Int | 明細ID |
| user_id | Int | 誰のデータか |
| category_id | Int | どのカテゴリか |
| amount | Int | 金額 |
| date | Date | 発生日 |
| content | String | 用途(何に使ったか) |
| memo | String | 補足メモ |
| is_confirmed | Boolean | 確定か未確定か |
rewards
| カラム名 | 型 | 説明 |
|---|---|---|
| id | Int | ご褒美ID |
| user_id | Int | 誰のご褒美か |
| name | String | 欲しいものの名前 |
| target_amount | Int | 必要な金額 |
さて、データ要件について固めることができました。
続きまして、APIのフローについてやっていきます。
ここでAPIの出し入れを考えます。何を送り、何を返して欲しいかですね。
- トップ画面 ここでカレンダーや各画面遷移ボタン、各明細についてを表示する
- GET /top
- Response: amount, date, content, memo, isConfirmed
- GET /top
- 明細を作成するダイアログ
- POST /top/transactions
- Request: userId, date, amount, categoryId, content, memo, isConfirmed
- Response: 200OK/400Error
- GET /top/transactions
- categoryId
- POST /top/transactions
- 明細を修正するダイアログ
- PUT /top/transactions
- Request: userId, date, amount, categoryId, content, memo, isConfirmed
- Response: 200OK/400Error
- PUT /top/transactions
- チャート画面
- POST /chart
- Request: date
- Response: amount, date, content, isConfirmed
- POST /chart
- 削除API
- DELETE /delete
- transactionsId
- DELETE /delete
ここでAIに投げてみました。
「1. エンドポイントの命名が「素人」すぎる
GET /top / POST /top/transactions / DELETE /delete
お前、これは趣味のメモ書きじゃないんだぞ。
指摘: /top や /delete という名前は、そのAPIが「何を」操作するのかを表現できていない。
2. 「全部取得(GET /top)」の傲慢
「データはそこまで大きくならないと思った」
指摘: 今はいいさ。だが、1年、2年と使い続けたらどうする? 毎回、過去数年分の全データをダウンロードして、ブラウザ側で「今月分はどれかな?」と探させるのか?
3. なぜチャートで「POST」を使う?
POST /chart
指摘: チャートのデータを取得するのは 「参照(Read)」 だろ?
・・・・・
」
厳しいですね。結局正解のAPIを考えてもらいました
| 機能 | メソッド | エンドポイント | リクエスト |
|---|---|---|---|
| ログイン | POST | /auth/login | email,password |
| 明細一覧取得 | GET | /transactions | ?from...&to... |
| 明細登録 | POST | /transactions | 明細のこと |
| 明細更新 | PUT | /transactions/{id} | 明細のこと |
| 明細削除 | DELETE | /transactions/{id} | |
| カテゴリ取得 | GET | /categories |
・・・スッキリしましたね。API設計についての観点をまとめます。
- APIのパスは対象となるリソースを表現する。/getTransactionsなどではなく、明細はすべて/transactionsなど。
- データの全件取得はデータが増えたときにクラッシュする危険性があるので、クエリパラメータやページネーションを活用すべき
- 認証情報はuser_idではなくサーバーから発行されたトークンを用い、リクエストにトークンを含め、サーバー側でトークンとユーザーを紐づける
- 冪等性を意識する
POSTでuser_idを送り、各明細について受け取るのかと思っていました。危険。
めでたくこれでAPI設計が終了しました。次は技術選定です。
技術選定
| 項目 | 技術 | 説明 |
|---|---|---|
| フロントエンド | TypeScript + React | 型安全で保守性が高く、モダンなUI開発が可能 |
| バックエンド / DB | Supabase | Backend + Database を兼ね備えた BaaS(Backend as a Service)。学習コストを抑えつつ、認証・DB・API をまとめて扱える |
| チャートライブラリ | Recharts | Reactとの相性が良く、シンプルにグラフを実装できる |
| デプロイ | Vercel | Reactとの親和性が高く、簡単にデプロイが可能 |
Next.jsなどを使用してバックエンドを作ろうかと考えていましたが、学習コストがかかりすぎて記事が終焉しそうだったのでやめます。
技術選定終わりです。
ここで、今までの流れを整理します
- 企画フェーズでなぜ作るか、誰が使うかを洗い出した
- 要件定義を行い、機能要件、非機能要件、画面要件、データ要件を整理
- 画面・操作シナリオの具体化
- データ要件・DB設計の整理
- API設計
- 技術選定
長かったですね。正直これを書いている今は今まで決めたことが本当に意味あったのかはっきりと掴めていません。役に立ちますように。
実装
Supabase
SQLは基本情報で触れましたが書けません。先ほどのデータ構造をもとにDBを作るSQLを出してもらいました。
次にReactのプロジェクトを立ち上げ、Supabaseへ接続します。
お馴染みのvite@latestで起動し、.env.localにsupabaseのURLとanonキーを入れ、App.jsの中でsupabase.auth.signUpをします。
import { useState } from 'react'
import { supabase } from './supabaseClient'
function App() {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const handleSignUp = async () => {
const { data, error } = await supabase.auth.signUp({ email, password })
if (error) alert(error.message)
else alert('確認メールを送ったぞ!メールボックスを見ろ!')
}
const handleLogin = async () => {
const { data, error } = await supabase.auth.signInWithPassword({ email, password })
if (error) alert(error.message)
else alert('ログイン成功だ!')
}
return (
<div style={{ padding: '20px' }}>
<h1>俺の家計簿 2026</h1>
<input type="email" placeholder="Email" onChange={(e) => setEmail(e.target.value)} />
<input type="password" placeholder="Password" onChange={(e) => setPassword(e.target.value)} />
<button onClick={handleSignUp}>新規登録</button>
<button onClick={handleLogin}>ログイン</button>
</div>
)
}
export default App
さて、こんな感じで入力してみました。

supabaseに入っていますね。バックエンド設計しなくてもDBが使えるのは楽ですごい。

その後も着々と作っていきます。
基本的にGeminiに作ってもらい、動作確認をしました。
Gemini奮闘中,,,
概ね完成したものがこちらです。
![FireShot Capture 003 - kakechan - [localhost].png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F4232438%2Ff9e236ce-ed0c-4b71-9ae3-a08bb870e50b.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=75e40f09dfa27c1fee09a50829ac9b1b)
画面のイメージを先に作っておくと、どこに何が欲しいかのプロンプトを書きやすくて良いですね。
ライブラリとしてReact-Router, MUIを使うように指示などはしました。
テスト
- 「テストコードを作成し、正しく動作するか確認してください」ではなく、システムにどういう機能が必要なのかを壁打ちして洗い出し、テストを生成してもらい、カバレッジを判断するのが良いそうです。ユーザーシナリオを明文化しておいたおかげで再利用できそうです。もっとユーザーシナリオを作っても良いかもしれないと感じました。
あとはvercelにデプロイして終了です。
総括
- 良かった点
- 簡単にアプリを作ることができました。掛かった時間は実装以外で15時間、実装が4時間ほどという短い時間でそれなりに動くものができて良かったです。ユーザーシナリオを満たす動作で、見た目も悪くないため概ね満足しています。
- APIやDBの要件をちゃんと考えたことは無かったため、良い経験になりました。ここら辺をAIと壁打ちできるのは非常にありがたいと思いました。
- 画面要件が固まっているとプロンプトを投げやすかったです。
- 悪かった点
- 全てが中途半端でちぐはぐだったと思う。実務のようなプロセスを踏んだのにBaaSを使用するのはおかしな話だとも思いました。速さを取って開発するのか、じっくり堅牢に開発するのかのどちらでもなく半端だったと思います。
- useEffectの処理の中でレンダリングが起こるかもしれないという旨の警告や依存配列の警告が8個くらい出て、修正しきれなかった。ちゃんとした実装をすべてAIで行うのは厳しそうだと思った。
- 動くものはできたが、冪等性などを考慮していないためバグが出てくる可能性が高いです。
- この記事の目的はアプリを作ることしか考えていませんでしたが、もっと学びを獲得できそうな場面が多かったと思います。AIが得意な部分と人間の介入が必要な部分をもう少し明文化したいと思いました。体感としては、実装ではなくAPIやDB設計が便利だと思った。
- 分からないが、正直Bolt.newに実装してもらい、Supabaseを使うようにし、デプロイすれば2時間ほどで同じようなものができるのではないかと思った。
- 認証回りやバックアップ、不正ログイン防止などを強化したいです。
- 感想
- 次は実務で学んだReactのことなどを活かしつつ、今回のコードをリファクタしてみようと思います。
- ユーザーシナリオがかなり柱になってくると感じたため、もう少しいろいろなシナリオを考えても良かったかもしれないと思いました。
- お金を貯めたいです。