iT邦幫忙

2025 iThome 鐵人賽

DAY 16
2
佛心分享-SideProject30

AI-Driven Development 實戰篇:30 天 Side Project 開發全紀錄系列 第 16

Day 16 - 智慧記帳 Day 5:架構設計日,打造可擴展的現代化技術底座

  • 分享至 

  • xImage
  •  

昨天完成了 UI/UX 設計,今天要搭建技術架構。這不是選技術棧的炫技大會,而是要設計一個能撐起 MVP、又能優雅擴展到百萬用戶的架構。

為什麼架構設計是 MVP 的隱形地雷?

很多人覺得 MVP 階段不用管架構,「能動就好」。但我見過太多專案因為初期架構債累積,導致:

  • 加個功能要改十個地方
  • 效能問題無法定位
  • 擴展時要整個重寫
  • 團隊協作困難重重

正確的架構不是過度設計,而是剛好夠用的設計

技術選型:站在巨人的肩膀上

核心技術棧決策

經過與 AI 深度討論,我選擇了這套現代化架構:

前端框架:Next.js 15 (App Router)
後端服務:Supabase (BaaS)
AI 服務:OpenAI + Vercel AI SDK
部署平台:Vercel
監控分析:Vercel Analytics + Sentry

為什麼是這個組合?

Next.js 15 + App Router 的選擇邏輯:

  • Server Components 降低客戶端 bundle size
  • Streaming SSR 改善首屏體驗
  • 內建 API Routes 省去獨立後端
  • 原生支援 TypeScript
  • 與 Vercel 完美整合

Supabase 作為 BaaS 的價值:

  • PostgreSQL 而非 NoSQL(財務數據需要 ACID)
  • 內建認證系統(省 2 週開發時間)
  • Real-time 訂閱(未來的協作功能)
  • Row Level Security(資料隔離)
  • Edge Functions(無伺服器計算)

關鍵決策:不自建後端

傳統架構:前端 + Node.js API + PostgreSQL + Redis + Auth
我的架構:Next.js + Supabase(包含所有後端功能)

省下的時間:至少 3 週
省下的成本:每月 $100+ 的伺服器費用

分層架構設計:關注點分離的藝術

整體架構圖

┌─────────────────────────────────────────┐
│          Presentation Layer             │
│  (React Components + Next.js Pages)     │
├─────────────────────────────────────────┤
│          Application Layer              │
│    (Use Cases + Business Logic)         │
├─────────────────────────────────────────┤
│           Domain Layer                  │
│    (Entities + Domain Services)         │
├─────────────────────────────────────────┤
│        Infrastructure Layer             │
│ (Supabase + OpenAI + External APIs)     │
└─────────────────────────────────────────┘

Layer 1:展示層(Presentation)

負責用戶介面和互動,但不包含業務邏輯。

目錄結構:

app/
├── (auth)/          # 認證相關頁面
│   ├── login/
│   └── register/
├── (dashboard)/     # 主要應用頁面
│   ├── page.tsx     # 首頁(記帳)
│   ├── timeline/    # 時間軸
│   ├── insights/    # 洞察報表
│   └── settings/    # 設定
├── components/      # 共用元件
│   ├── ui/         # 基礎 UI 元件
│   ├── features/   # 功能元件
│   └── layouts/    # 布局元件
└── hooks/          # Custom Hooks

設計原則:

  • Server Components 優先(減少 JS bundle)
  • Client Components 只在需要互動時使用
  • 使用 Suspense 實現漸進式載入
  • 元件職責單一化

Layer 2:應用層(Application)

協調領域層和基礎設施層,實現具體的使用案例。

目錄結構:

lib/
├── use-cases/       # 使用案例
│   ├── expenses/    # 支出相關
│   │   ├── quick-entry.ts
│   │   ├── categorize.ts
│   │   └── bulk-import.ts
│   ├── subscriptions/ # 訂閱相關
│   │   ├── identify.ts
│   │   ├── manage.ts
│   │   └── remind.ts
│   └── insights/     # 洞察相關
│       ├── generate-report.ts
│       └── analyze-pattern.ts
├── services/        # 應用服務
│   ├── auth.ts     # 認證服務
│   ├── notification.ts
│   └── export.ts
└── dto/            # 資料傳輸物件

核心職責:

  • 實現 User Story 的業務流程
  • 協調多個領域物件
  • 處理跨領域的交易
  • 權限檢查和驗證

Layer 3:領域層(Domain)

包含核心業務邏輯,與技術無關。

目錄結構:

domain/
├── entities/        # 領域實體
│   ├── expense.ts
│   ├── subscription.ts
│   ├── budget.ts
│   └── category.ts
├── value-objects/   # 值物件
│   ├── money.ts
│   ├── period.ts
│   └── confidence.ts
├── aggregates/      # 聚合根
│   ├── expense-aggregate.ts
│   └── subscription-aggregate.ts
├── services/        # 領域服務
│   ├── categorization.ts
│   └── budget-guardian.ts
└── events/          # 領域事件
    ├── expense-events.ts
    └── subscription-events.ts

DDD 實踐要點:

  • 實體有唯一標識
  • 值物件是不可變的
  • 聚合根保護不變規則
  • 領域服務處理跨實體邏輯

Layer 4:基礎設施層(Infrastructure)

所有外部系統的介面和實作。

目錄結構:

infrastructure/
├── supabase/        # Supabase 整合
│   ├── client.ts
│   ├── auth.ts
│   ├── database.ts
│   └── migrations/
├── ai/              # AI 服務
│   ├── openai.ts
│   ├── categorizer.ts
│   └── analyzer.ts
├── repositories/    # 資料存取
│   ├── expense.repo.ts
│   └── subscription.repo.ts
└── external/        # 第三方 API
    ├── telegram.ts
    └── bank-api.ts

資料流設計:從輸入到洞察

核心資料流程

用戶輸入「星巴克 120」
    ↓
[Presentation] Input Component
    ↓
[Application] QuickEntryUseCase
    ↓
[Domain] ExpenseAggregate.create()
    ↓
[Infrastructure] AI Categorizer
    ↓
[Domain] Category.assign()
    ↓
[Infrastructure] [ExpenseRepository.save](http://ExpenseRepository.save)()
    ↓
[Application] NotificationService
    ↓
[Presentation] UI Update

Server Component 資料流

Next.js App Router 的 Server Components 改變了資料流:

// app/(dashboard)/page.tsx
// 這在伺服器端執行,不會發送到客戶端
async function DashboardPage() {
  // 直接在元件中 fetch 資料
  const expenses = await getRecentExpenses()
  const insights = await generateInsights(expenses)
  
  // 只傳送 HTML 到客戶端
  return (
    <Dashboard 
      expenses={expenses}
      insights={insights}
    />
  )
}

優點:

  • 減少客戶端 JavaScript
  • 改善 SEO 和首屏速度
  • 簡化資料獲取邏輯

Real-time 更新架構

利用 Supabase Realtime 實現即時同步:

訂閱建立 → Supabase Channel
    ↓
資料變更 → PostgreSQL Trigger
    ↓
事件廣播 → WebSocket
    ↓
客戶端更新 → React State

應用場景:

  • 多設備同步
  • 協作記帳(未來功能)
  • 即時通知

狀態管理策略:簡單但不簡陋

三層狀態架構

1. Server State(伺服器狀態)

  • 使用 React Query (TanStack Query)
  • 自動快取和同步
  • 樂觀更新支援

2. Client State(客戶端狀態)

  • 使用 Zustand(輕量級)
  • 只存 UI 狀態和臨時資料
  • 避免狀態重複

3. URL State(路由狀態)

  • 使用 Next.js 的 searchParams
  • 可分享和書籤
  • 天然的狀態持久化

狀態流動原則

URL State(篩選、排序、頁數)
    ↓
Server State(資料查詢)
    ↓
Client State(UI 互動)

避免的反模式:

  • 把伺服器資料複製到客戶端狀態
  • 在多處維護相同狀態
  • 過度使用全域狀態

AI 整合架構:智慧但可控

AI 服務分層

AI Gateway Layer
├── Rate Limiting
├── Fallback Logic
└── Response Cache
    ↓
AI Services
├── Categorization Service
├── Pattern Recognition
└── Insight Generation
    ↓
Model Layer
├── OpenAI GPT-4
├── Local Fallback Rules
└── User Feedback Loop

智慧分類的架構設計

// 三層分類策略
class CategorizationStrategy {
  async categorize(expense: Expense): Promise<Category> {
    // Layer 1: 用戶歷史規則
    const userRule = await findUserRule(expense)
    if (userRule?.confidence > 0.9) return userRule.category
    
    // Layer 2: AI 預測
    const aiPrediction = await openAI.categorize(expense)
    if (aiPrediction.confidence > 0.7) return aiPrediction.category
    
    // Layer 3: 預設規則
    return applyDefaultRules(expense)
  }
}

AI 成本控制架構

Request → Cache Check → AI Call → Cache Store
              ↓              ↓
         Cache Hit      Token Count
              ↓              ↓
         Return Cache   Cost Control

策略:

  • 相似輸入使用快取
  • 批量請求減少 API 呼叫
  • 降級到本地規則

安全架構:預設安全

多層安全防護

Layer 1: Edge Security (Vercel)
├── DDoS Protection
├── Rate Limiting
└── Geographic Restrictions

Layer 2: Application Security (Next.js)
├── CSRF Protection
├── Content Security Policy
└── Input Validation

Layer 3: API Security (Supabase)
├── Row Level Security
├── JWT Validation
└── API Key Management

Layer 4: Data Security
├── Encryption at Rest
├── Encryption in Transit
└── PII Masking

Row Level Security 設計

Supabase 的 RLS 確保資料隔離:

-- 用戶只能看到自己的支出
CREATE POLICY "Users can only see own expenses" 
ON expenses FOR SELECT 
USING (auth.uid() = user_id);

-- 防止跨用戶資料洩漏
CREATE POLICY "Users can only insert own expenses" 
ON expenses FOR INSERT 
WITH CHECK (auth.uid() = user_id);

效能優化架構:快但不浪費

三級快取策略

L1: Browser Cache
├── Static Assets (永久快取)
├── API Responses (SWR)
└── Service Worker

L2: CDN Cache (Vercel Edge)
├── HTML Pages
├── API Routes
└── Images

L3: Database Cache
├── PostgreSQL Query Cache
├── Materialized Views
└── Connection Pool

關鍵效能指標架構

監控點布局:
User Action → Performance Mark
    ↓
API Call → Timing Measure
    ↓
Database Query → Trace
    ↓
Response → Core Web Vitals

目標指標:

  • LCP < 2.5s
  • FID < 100ms
  • CLS < 0.1
  • API Response < 200ms

擴展性設計:為未來準備

垂直擴展路徑

MVP (Now)
├── Vercel Hobby
├── Supabase Free
└── OpenAI Pay-as-you-go

Growth (1K users)
├── Vercel Pro
├── Supabase Pro
└── OpenAI with Cache

Scale (10K users)
├── Vercel Enterprise
├── Supabase Team
├── OpenAI + Self-hosted Models
└── Redis Cache Layer

Enterprise (100K+ users)
├── Multi-region Deployment
├── Database Sharding
├── Custom AI Infrastructure
└── Dedicated Support

水平擴展預留

雖然 MVP 不需要,但架構已預留:

  1. 微服務化預留
    • Use Case 可獨立部署
    • 領域邊界清晰
    • 事件驅動架構
  2. 多租戶預留
    • 資料模型支援 tenant_id
    • RLS 規則可擴展
    • 獨立資料庫可能性
  3. 國際化預留
    • 時區處理
    • 多語言架構
    • 多幣別支援

開發體驗優化

開發環境架構

Local Development
├── Next.js Dev Server
├── Supabase Local (Docker)
├── TypeScript Watch
└── Hot Module Replacement

Testing Environment
├── Unit Tests (Vitest)
├── Integration Tests (Playwright)
├── E2E Tests
└── Visual Regression

CI/CD Pipeline
├── GitHub Actions
├── Vercel Preview
├── Automatic Deploy
└── Rollback Support

類型安全架構

// 從資料庫到前端的類型安全
Database Schema (Supabase)
    ↓
TypeScript Types (Generated)
    ↓
Zod Schemas (Runtime Validation)
    ↓
React Components (Type-safe Props)

監控與可觀測性

四柱監控架構

1. Application Monitoring (Sentry)
   - Error Tracking
   - Performance Monitoring
   - User Sessions

2. Infrastructure Monitoring (Vercel)
   - Function Execution
   - Edge Network
   - Build Performance

3. Business Monitoring (Custom)
   - User Behavior
   - Feature Usage
   - Conversion Funnel

4. AI Monitoring
   - Token Usage
   - Response Quality
   - Cost Tracking

架構決策紀錄(ADR)

ADR-001: 為什麼選擇 Monorepo?

狀態: 採用

決策: 使用單一 repository

原因:

  • MVP 階段降低複雜度
  • 共享類型定義容易
  • 部署流程簡化

風險: 未來可能需要拆分

緩解: 保持模組邊界清晰

ADR-002: 為什麼不用 Microservices?

狀態: 延遲

決策: 保持 Monolithic 架構

原因:

  • 過早優化是萬惡之源
  • 單人團隊維護困難
  • MVP 不需要這種規模

未來: 當 DAU > 10K 時重新評估

ADR-003: 為什麼選擇 PostgreSQL over MongoDB?

狀態: 採用

決策: 使用關聯式資料庫

原因:

  • 財務資料需要 ACID
  • 複雜查詢需求(報表)
  • Supabase 原生支援

補充: JSONB 欄位提供彈性

技術債管理策略

刻意的技術債

這些是我知道但故意延後的:

  1. 沒有訊息佇列
    • 現在:同步處理
    • 未來:引入 Redis Queue
  2. 沒有 API Gateway
    • 現在:直連 Supabase
    • 未來:Kong 或 AWS API Gateway
  3. 簡單的錯誤處理
    • 現在:基本 try-catch
    • 未來:Circuit Breaker Pattern

技術債追蹤

## Technical Debt Registry
| ID | Description | Impact | Effort | Priority |
|----|------------|--------|--------|----------|
| TD-001 | No message queue | Medium | High | P2 |
| TD-002 | Simple error handling | Low | Medium | P3 |
| TD-003 | No rate limiting | High | Low | P1 |

架構演進路線圖

Phase 1: MVP (Now)

  • 基礎架構搭建
  • 核心功能實現
  • 基本安全措施

Phase 2: Growth (Month 3)

  • 引入快取層
  • 優化資料庫查詢
  • 加入 A/B Testing

Phase 3: Scale (Month 6)

  • 微服務化評估
  • 多區域部署
  • 自建 AI 模型

Phase 4: Enterprise (Year 2)

  • 完整微服務架構
  • 多租戶系統
  • 合規認證

反思:架構是演化的

今天設計的架構不是終點,而是起點。好的架構應該:

  1. 適應當前規模 - 不過度設計
  2. 預留擴展空間 - 不鎖死未來
  3. 保持簡單清晰 - 不增加複雜度
  4. 支援快速迭代 - 不阻礙開發

最重要的是:架構服務於業務,而非相反

明日預告

Day 17 - 智慧記帳 Day 6:核心功能開發日

  • 實作快速記帳 API
  • AI 分類服務整合
  • 支出管理 CRUD
  • 前後端連接測試

今天打好了地基,明天開始蓋房子!


上一篇
Day 15 - 智慧記帳 Day 4:三秒記帳的 UI/UX 設計哲學
系列文
AI-Driven Development 實戰篇:30 天 Side Project 開發全紀錄16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言