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:
kappa
2026-01-19 15:36:17 +09:00
parent 3bf42947a7
commit ab6c9a2efa
18 changed files with 2578 additions and 1958 deletions

View File

@@ -0,0 +1,48 @@
/**
* Email Decoder Utility
*
* Quoted-Printable 인코딩된 이메일 본문을 UTF-8 문자열로 디코딩합니다.
* RFC 2045 Quoted-Printable 표준을 준수합니다.
*/
/**
* Quoted-Printable UTF-8 디코딩
*
* @param str - Quoted-Printable 인코딩된 문자열
* @returns 디코딩된 UTF-8 문자열
*
* @example
* ```typescript
* const encoded = "=ED=99=8D=EA=B8=B8=EB=8F=99";
* const decoded = parseQuotedPrintable(encoded);
* console.log(decoded); // "홍길동"
* ```
*/
export function parseQuotedPrintable(str: string): string {
// 줄 연속 문자 제거 (=\r\n 또는 =\n)
str = str.replace(/=\r?\n/g, '');
// =XX 패턴을 바이트로 변환
const bytes: number[] = [];
let i = 0;
while (i < str.length) {
if (str[i] === '=' && i + 2 < str.length) {
const hex = str.slice(i + 1, i + 3);
if (/^[0-9A-Fa-f]{2}$/.test(hex)) {
bytes.push(parseInt(hex, 16));
i += 3;
continue;
}
}
bytes.push(str.charCodeAt(i));
i++;
}
// UTF-8 바이트를 문자열로 변환
try {
return new TextDecoder('utf-8').decode(new Uint8Array(bytes));
} catch {
// 디코딩 실패 시 원본 반환
return str;
}
}