refactor: 파일 분리 리팩토링 (routes, services, tools, utils)
아키텍처 개선: - index.ts: 921줄 → 205줄 (77% 감소) - openai-service.ts: 1,356줄 → 148줄 (89% 감소) 새로운 디렉토리 구조: - src/routes/ - Webhook, API, Health check 핸들러 - webhook.ts (287줄) - api.ts (318줄) - health.ts (14줄) - src/services/ - 비즈니스 로직 - bank-sms-parser.ts (143줄) - deposit-matcher.ts (88줄) - src/tools/ - Function Calling 도구 모듈화 - weather-tool.ts (37줄) - search-tool.ts (156줄) - domain-tool.ts (725줄) - deposit-tool.ts (183줄) - utility-tools.ts (60줄) - index.ts (104줄) - 도구 레지스트리 - src/utils/ - 유틸리티 함수 - email-decoder.ts - Quoted-Printable 디코더 타입 에러 수정: - routes/webhook.ts: text undefined 체크 - summary-service.ts: D1 타입 캐스팅 - summary-service.ts: Workers AI 타입 처리 - n8n-service.ts: Workers AI 타입 + 미사용 변수 제거 빌드 검증: - TypeScript 타입 체크 통과 - Wrangler dev 로컬 빌드 성공 문서: - REFACTORING_SUMMARY.md 추가 - ROUTE_ARCHITECTURE.md 추가 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
217
ROUTE_ARCHITECTURE.md
Normal file
217
ROUTE_ARCHITECTURE.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# Route Architecture
|
||||
|
||||
## Before Refactoring
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ index.ts (921 lines) │
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────┐ │
|
||||
│ │ fetch() Handler │ │
|
||||
│ │ • /setup-webhook │ │
|
||||
│ │ • /webhook-info │ │
|
||||
│ │ • /health │ │
|
||||
│ │ • /api/deposit/balance │ │
|
||||
│ │ • /api/deposit/deduct │ │
|
||||
│ │ • /api/test │ │
|
||||
│ │ • /api/contact │ │
|
||||
│ │ • /webhook (+ handleMessage + handleCallbackQuery) │ │
|
||||
│ └───────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────┐ │
|
||||
│ │ email() Handler │ │
|
||||
│ │ • SMS parsing │ │
|
||||
│ │ • Auto-matching │ │
|
||||
│ │ • Notifications │ │
|
||||
│ └───────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────┐ │
|
||||
│ │ scheduled() Handler │ │
|
||||
│ │ • 24h expiration cleanup │ │
|
||||
│ └───────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## After Refactoring
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ index.ts (205 lines) │
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────┐ │
|
||||
│ │ fetch() Handler (Router) │ │
|
||||
│ │ • /setup-webhook ──────────┐ │ │
|
||||
│ │ • /webhook-info ───────────┤ │ │
|
||||
│ │ • /health ──────────────────┼──→ routes/health.ts │ │
|
||||
│ │ • /api/* ───────────────────┼──→ routes/api.ts │ │
|
||||
│ │ • /webhook ─────────────────┴──→ routes/webhook.ts │ │
|
||||
│ └───────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────┐ │
|
||||
│ │ email() Handler (unchanged) │ │
|
||||
│ └───────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────┐ │
|
||||
│ │ scheduled() Handler (unchanged) │ │
|
||||
│ └───────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌───────────────┼───────────────┐
|
||||
▼ ▼ ▼
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ health.ts │ │ api.ts │ │ webhook.ts │
|
||||
│ (14 lines) │ │ (318 lines) │ │ (287 lines) │
|
||||
├──────────────┤ ├──────────────┤ ├──────────────┤
|
||||
│ • status │ │ • balance │ │ • message │
|
||||
│ • timestamp │ │ • deduct │ │ • callback │
|
||||
│ │ │ • test │ │ • rate limit │
|
||||
│ │ │ • contact │ │ • commands │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
## Request Flow Examples
|
||||
|
||||
### 1. Telegram Message
|
||||
```
|
||||
User sends message
|
||||
↓
|
||||
Telegram API → /webhook
|
||||
↓
|
||||
index.ts:fetch() → routes/webhook.ts:handleWebhook()
|
||||
↓
|
||||
validateWebhookRequest() (security check)
|
||||
↓
|
||||
handleMessage()
|
||||
├─ checkRateLimit() (KV-based)
|
||||
├─ getOrCreateUser() (DB)
|
||||
├─ handleCommand() OR generateAIResponse()
|
||||
└─ sendMessage() (Telegram API)
|
||||
```
|
||||
|
||||
### 2. Deposit Balance Inquiry
|
||||
```
|
||||
namecheap-api → /api/deposit/balance?telegram_id=123
|
||||
↓
|
||||
index.ts:fetch() → routes/api.ts:handleApiRequest()
|
||||
↓
|
||||
X-API-Key authentication
|
||||
↓
|
||||
DB query (users + user_deposits)
|
||||
↓
|
||||
JSON response { telegram_id, balance }
|
||||
```
|
||||
|
||||
### 3. Contact Form Submission
|
||||
```
|
||||
Web form → /api/contact (POST)
|
||||
↓
|
||||
index.ts:fetch() → routes/api.ts:handleApiRequest()
|
||||
↓
|
||||
CORS check (hosting.anvil.it.com)
|
||||
↓
|
||||
Validation (email format, message length)
|
||||
↓
|
||||
sendMessage() to admin (Telegram notification)
|
||||
```
|
||||
|
||||
### 4. Health Check
|
||||
```
|
||||
Monitoring → /health (GET)
|
||||
↓
|
||||
index.ts:fetch() → routes/health.ts:handleHealthCheck()
|
||||
↓
|
||||
JSON response { status: 'ok', timestamp }
|
||||
```
|
||||
|
||||
## Module Dependencies
|
||||
|
||||
```
|
||||
routes/webhook.ts
|
||||
├── types.ts (Env, TelegramUpdate)
|
||||
├── security.ts (validateWebhookRequest, checkRateLimit)
|
||||
├── telegram.ts (sendMessage, sendMessageWithKeyboard, etc)
|
||||
├── domain-register.ts (executeDomainRegister)
|
||||
├── summary-service.ts (addToBuffer, processAndSummarize, generateAIResponse)
|
||||
└── commands.ts (handleCommand)
|
||||
|
||||
routes/api.ts
|
||||
├── types.ts (Env)
|
||||
├── telegram.ts (sendMessage)
|
||||
├── summary-service.ts (addToBuffer, processAndSummarize, generateAIResponse)
|
||||
└── commands.ts (handleCommand)
|
||||
|
||||
routes/health.ts
|
||||
└── (none - standalone)
|
||||
|
||||
index.ts
|
||||
├── types.ts (Env, EmailMessage)
|
||||
├── telegram.ts (sendMessage, setWebhook, getWebhookInfo)
|
||||
├── services/bank-sms-parser.ts (parseBankSMS)
|
||||
├── services/deposit-matcher.ts (matchPendingDeposit)
|
||||
├── routes/webhook.ts (handleWebhook)
|
||||
├── routes/api.ts (handleApiRequest)
|
||||
└── routes/health.ts (handleHealthCheck)
|
||||
```
|
||||
|
||||
## Code Organization Benefits
|
||||
|
||||
### 1. Separation of Concerns
|
||||
- **webhook.ts**: Telegram-specific logic
|
||||
- **api.ts**: REST API endpoints
|
||||
- **health.ts**: Monitoring
|
||||
- **index.ts**: Routing + email + cron
|
||||
|
||||
### 2. Testability
|
||||
Each route can be tested independently:
|
||||
```typescript
|
||||
import { handleHealthCheck } from './routes/health';
|
||||
const response = await handleHealthCheck();
|
||||
expect(response.status).toBe(200);
|
||||
```
|
||||
|
||||
### 3. Maintainability
|
||||
- Smaller files (14-318 lines vs 921 lines)
|
||||
- Clear responsibilities
|
||||
- Easier to locate bugs
|
||||
- Safe to modify without affecting other routes
|
||||
|
||||
### 4. Reusability
|
||||
Route handlers can be:
|
||||
- Imported by other modules
|
||||
- Wrapped with middleware
|
||||
- Tested in isolation
|
||||
- Deployed independently (future: multiple workers)
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Potential Middleware Layer
|
||||
```typescript
|
||||
// src/middleware/auth.ts
|
||||
export function withAuth(handler: RouteHandler) {
|
||||
return async (req, env, url) => {
|
||||
if (!validateAuth(req)) {
|
||||
return Response.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
return handler(req, env, url);
|
||||
};
|
||||
}
|
||||
|
||||
// Usage in routes/api.ts
|
||||
export const handleApiRequest = withAuth(async (req, env, url) => {
|
||||
// ... existing logic
|
||||
});
|
||||
```
|
||||
|
||||
### Route Registration Pattern
|
||||
```typescript
|
||||
// src/router.ts
|
||||
const routes = {
|
||||
'/health': handleHealthCheck,
|
||||
'/api/*': handleApiRequest,
|
||||
'/webhook': handleWebhook,
|
||||
};
|
||||
|
||||
// index.ts
|
||||
const handler = routes[pathname] || notFound;
|
||||
return handler(request, env, url);
|
||||
```
|
||||
Reference in New Issue
Block a user