【React × Django】カップル・家族向け共有家計簿アプリ「Futari-Note」を作ってみた
はじめに
カップルや家族向けの共有家計簿・ライフログアプリケーション「Futari-Note」を開発したので、その魅力と開発過程をご紹介したいと思います。
「家計簿を共有したいけど、既存のアプリは機能が足りない」「パートナーとの日常をもっと共有したい」そんな想いから生まれたアプリケーションです。
🎯 Futari-Noteとは?
Futari-Noteは、カップルや家族向けの包括的なライフスタイル管理アプリケーションです。単なる家計簿アプリではなく、パートナー間でのコミュニケーションを促進する様々な機能を搭載しています。
主な機能
💰 家計簿機能
- 収支管理: 収入・支出の登録・編集・削除
- カテゴリ管理: カスタムカテゴリの作成・編集
- 予算管理: 月次予算設定・予算アラート
- レポート機能: 月次・年次レポート、グラフ表示
- カレンダー表示: 日付ごとの収支確認
🤝 パートナーシップ機能
- パートナー招待・承認システム
- 家計簿データの共有
- リアルタイム同期(WebSocket)
- 共有データの編集権限管理
🏠 ホームダッシュボード
- 支払い予定管理: 定期支払いの設定・通知
- 日記機能: 日々の記録・共有
- 気持ち投稿: 感情の記録・共有
- TODO管理
- 家計サマリー表示
📝 ノート・リンク集機能
- ノート管理: タグ付きノート機能
- リンク集: お気に入りサイトの共有管理
🔔 通知機能
- アプリ内通知
- メール通知
- 予算アラート
- パートナーシップ関連通知
🛠️ 技術スタック
バックエンド
- Django 4.2 - Webフレームワーク
- Django REST Framework 3.15.0 - API開発
- Django Channels 4.2.2 - WebSocket対応
- PostgreSQL - データベース
- Azure Database for PostgreSQL - クラウドデータベース
- Azure Blob Storage - ファイルストレージ
フロントエンド
- React 18.2.0 - UIフレームワーク
- TypeScript 4.9.5 - 型安全性
- Material-UI (MUI) 5.15.5 - UIコンポーネント
- Chart.js 4.4.1 - データ可視化
- React Context API - 状態管理
- Axios 1.6.5 - HTTP通信
インフラ・デプロイ
- Microsoft Azure - クラウドプラットフォーム
- GitHub Actions - CI/CD
- Gunicorn - WSGIサーバー
- Daphne - ASGIサーバー
🚀 開発過程で工夫したポイント
1. リアルタイム同期の実装
パートナー間でのデータ共有において、リアルタイム同期は必須機能でした。Django ChannelsとWebSocketを使用して実装しました。
# consumers.py(一部抜粋)
class HomeConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.user = self.scope["user"]
if self.user.is_anonymous:
await self.close()
return
# パートナーシップグループに参加
partnership = await self.get_partnership()
if partnership:
self.group_name = f"partnership_{partnership.id}"
await self.channel_layer.group_add(
self.group_name,
self.channel_name
)
await self.accept()
2. モバイルファーストなUI設計
Material-UIを活用して、モバイルデバイスでの使いやすさを重視したレスポンシブデザインを実装しました。
// BottomNav.tsx(一部抜粋)
const BottomNav: React.FC = () => {
const location = useLocation();
const [value, setValue] = useState(0);
return (
<Paper
sx={{
position: 'fixed',
bottom: 0,
left: 0,
right: 0,
zIndex: 1000
}}
elevation={3}
>
<BottomNavigation
value={value}
onChange={(event, newValue) => setValue(newValue)}
showLabels
>
<BottomNavigationAction
label="ホーム"
icon={<HomeIcon />}
component={Link}
to="/finances/home"
/>
{/* 他のナビゲーション項目 */}
</BottomNavigation>
</Paper>
);
};
3. 型安全性の確保
TypeScriptを活用して、フロントエンドの型安全性を確保しました。APIレスポンスの型定義も徹底しています。
// types/index.ts
export interface Transaction {
id: string;
amount: number;
description: string;
category: Category;
date: string;
transaction_type: 'income' | 'expense';
created_by: User;
updated_by: User;
}
export interface NotificationPreference {
budget_alerts: boolean;
partnership_notifications: boolean;
email_notifications: boolean;
push_notifications: boolean;
notification_frequency: 'immediate' | 'daily' | 'weekly';
}
4. 段階的な開発アプローチ
開発は5つのフェーズに分けて進めました:
- フェーズ1: 開発環境セットアップ(1週間)
- フェーズ2: バックエンド開発(3週間)
- フェーズ3: フロントエンド開発(5週間)
- フェーズ4: テストと品質保証(2週間)
- フェーズ5: デプロイと運用準備(2週間)
特に、パートナーシップ機能の実装では、データの整合性とリアルタイム同期の両立に苦労しました。
🎨 UI/UXで重視したポイント
1. 直感的な操作性
家計簿アプリは日常的に使うものなので、操作が複雑だと続きません。Material-UIのコンポーネントを活用して、直感的な操作を実現しました。
2. 視覚的なフィードバック
予算の進捗状況や支出の傾向を、グラフやプログレスバーで視覚的に表示しています。
// FinanceSummaryWidget.tsx(一部抜粋)
<LinearProgress
variant="determinate"
value={budgetProgress}
sx={{
height: 8,
borderRadius: 4,
backgroundColor: 'rgba(0,0,0,0.1)',
'& .MuiLinearProgress-bar': {
backgroundColor: budgetProgress > 80 ? '#f44336' : '#4caf50',
},
}}
/>
3. パートナー間のコミュニケーション促進
単なる家計簿ではなく、日記や気持ち投稿機能を通じて、パートナー間のコミュニケーションを促進する設計にしました。
🔧 技術的な挑戦
1. WebSocketを使ったリアルタイム同期
複数ユーザーが同時に編集する際の競合解決が最大の技術的挑戦でした。
# partnership_utils.py(一部抜粋)
async def handle_data_conflict(partnership_id, data_type, data_id, user_id):
"""データ競合の解決処理"""
# 最後の更新者を確認
last_updated_by = await get_last_updated_user(data_type, data_id)
if last_updated_by != user_id:
# 競合を検出した場合の処理
await notify_conflict_to_users(partnership_id, data_type, data_id)
return False
return True
2. Azure環境でのデプロイ
Azure App ServiceとAzure Database for PostgreSQLを使用したクラウドデプロイも大きな学びでした。
3. セキュリティ対策
パートナー間でのデータ共有において、適切な認証・認可の実装は必須でした。
# views_partnership.py(一部抜粋)
class PartnershipViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated, IsPartnershipMember]
def get_queryset(self):
# ユーザーが参加しているパートナーシップのみ取得
return Partnership.objects.filter(
Q(user1=self.request.user) | Q(user2=self.request.user)
)
📊 開発で得られた学び
1. ユーザー中心設計の重要性
技術的な実装に夢中になりがちですが、実際にユーザーが使いやすいかどうかが最も重要だと実感しました。
2. リアルタイム機能の複雑さ
WebSocketを使ったリアルタイム同期は、想像以上に複雑でした。特に、ネットワーク切断時の再接続処理や、データの整合性確保が課題でした。
3. モバイルファーストの重要性
家計簿アプリは外出先でも使うことが多いため、モバイルでの使いやすさが非常に重要でした。
🔮 今後の展望
短期的な改善
- ノート機能の画像添付対応
- リンク集機能の完全実装
- パフォーマンス最適化
長期的な展望
- AI による支出分析・予測機能
- 銀行API連携による自動取込
- 多言語対応の拡充
- モバイルアプリ化
🎉 まとめ
Futari-Noteの開発を通じて、フルスタック開発の面白さと難しさを実感しました。特に、リアルタイム同期機能の実装は技術的に挑戦的でしたが、パートナー間でのスムーズなデータ共有を実現できたときの達成感は格別でした。
家計簿アプリは数多く存在しますが、パートナー間でのコミュニケーションを重視した設計にすることで、差別化を図ることができたと思います。
🔗 リンク
最後まで読んでいただき、ありがとうございました!
質問やフィードバックがあれば、コメントでお気軽にお声かけください 🙌