# v9: 통합 및 자동 요약 실행 ## 전체 워크플로우 통합 이제 모든 컴포넌트를 하나로 통합하여 완전한 자동 재무 분석 시스템을 완성합니다. ### 워크플로우 단계 ``` 1. Money Forward OAuth 인증 확인 ↓ 2. 거래 데이터 조회 ↓ 3. 데이터 전처리 및 정제 ↓ 4. Vertex AI 프롬프트 생성 ↓ 5. AI 분석 요청 ↓ 6. 결과 포맷팅 및 출력 ↓ 7. 파일 저장 (선택) ``` ## 메인 애플리케이션 통합 ### src/index.ts 완성 ```typescript import 'dotenv/config'; import { MoneyForwardClient } from './moneyforward/client'; import { FinancialAnalyzer } from './vertexai/analyzer'; import { TransactionAnalyzer, Formatter, FileSaver } from './utils'; import { format, subMonths, startOfMonth, endOfMonth } from 'date-fns'; import chalk from 'chalk'; interface AnalysisOptions { month?: string; // YYYY-MM detailed?: boolean; save?: boolean; output?: string; } async function analyzeFinance(options: AnalysisOptions = {}) { console.log(chalk.bold.blue('\n💰 Money Forward + Vertex AI 재무 분석\n')); console.log('='.repeat(70) + '\n'); try { // 1. 날짜 범위 설정 let fromDate: string; let toDate: string; if (options.month) { // 특정 월 지정 const date = new Date(options.month + '-01'); fromDate = format(startOfMonth(date), 'yyyy-MM-dd'); toDate = format(endOfMonth(date), 'yyyy-MM-dd'); } else { // 기본: 최근 1개월 toDate = format(new Date(), 'yyyy-MM-dd'); fromDate = format(subMonths(new Date(), 1), 'yyyy-MM-dd'); } console.log(chalk.cyan(`📅 분석 기간: ${fromDate} ~ ${toDate}\n`)); // 2. Money Forward 데이터 조회 console.log(chalk.yellow('📥 Money Forward에서 거래 데이터 조회 중...\n')); const mfClient = new MoneyForwardClient(); const transactions = await mfClient.getAllTransactions(fromDate, toDate); if (transactions.length === 0) { console.log(chalk.red('⚠️ 거래 내역이 없습니다\n')); return; } console.log(chalk.green(`✅ ${transactions.length}건의 거래 내역 조회 완료\n`)); console.log('='.repeat(70) + '\n'); // 3. 기본 통계 출력 const stats = TransactionAnalyzer.getBasicStats(transactions); console.log(chalk.bold('📊 기본 통계')); console.log('-'.repeat(70)); console.log(chalk.green(`총 수입: ${Formatter.formatAmount(stats.totalIncome)}`)); console.log(chalk.red(`총 지출: ${Formatter.formatAmount(stats.totalExpense)}`)); console.log( chalk.blue( `순자산 변동: ${Formatter.formatAmount(stats.netChange)} ${stats.netChange >= 0 ? '📈' : '📉'}` ) ); console.log(`거래 건수: ${stats.transactionCount}건`); console.log('\n' + '='.repeat(70) + '\n'); // 4. Vertex AI 분석 console.log(chalk.yellow('🤖 Vertex AI로 분석 중...\n')); const analyzer = new FinancialAnalyzer(); let analysis: string; if (options.detailed) { analysis = await analyzer.analyzeDetailed(transactions, fromDate, toDate); } else { analysis = await analyzer.analyzeSummary(transactions, fromDate, toDate); } // 5. 분석 결과 출력 console.log(chalk.bold.green('🤖 Vertex AI 분석 결과')); console.log('='.repeat(70) + '\n'); console.log(analysis); console.log('\n' + '='.repeat(70) + '\n'); // 6. 파일 저장 (옵션) if (options.save) { const timestamp = format(new Date(), 'yyyyMMdd-HHmmss'); const filename = `analysis-${timestamp}.md`; const directory = options.output || './reports'; const report = ` # 재무 분석 리포트 **분석 기간**: ${fromDate} ~ ${toDate} **생성일**: ${format(new Date(), 'yyyy-MM-dd HH:mm:ss')} ## 기본 통계 - 총 수입: ${Formatter.formatAmount(stats.totalIncome)} - 총 지출: ${Formatter.formatAmount(stats.totalExpense)} - 순자산 변동: ${Formatter.formatAmount(stats.netChange)} - 거래 건수: ${stats.transactionCount}건 ## AI 분석 ${analysis} --- *Generated by Money Forward + Vertex AI Analyzer* `.trim(); await FileSaver.saveAsMarkdown(report, filename, directory); // JSON 데이터도 저장 await FileSaver.saveAsJSON( { period: { from: fromDate, to: toDate }, stats, transactions, analysis, }, `data-${timestamp}.json`, directory ); } console.log(chalk.green.bold('✅ 분석 완료!\n')); } catch (error) { console.error(chalk.red('\n❌ 에러 발생:'), error); process.exit(1); } } // CLI 파라미터 파싱 function parseArgs() { const args = process.argv.slice(2); const options: AnalysisOptions = {}; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg === '--month' || arg === '-m') { options.month = args[++i]; } else if (arg === '--detailed' || arg === '-d') { options.detailed = true; } else if (arg === '--save' || arg === '-s') { options.save = true; } else if (arg === '--output' || arg === '-o') { options.output = args[++i]; } else if (arg === '--help' || arg === '-h') { console.log(` 사용법: npm run analyze [옵션] 옵션: -m, --month 분석할 월 지정 (기본: 최근 1개월) -d, --detailed 상세 분석 모드 -s, --save 분석 결과를 파일로 저장 -o, --output <경로> 저장 경로 지정 (기본: ./reports) -h, --help 도움말 표시 예시: npm run analyze # 최근 1개월 분석 npm run analyze -- -m 2025-11 # 2025년 11월 분석 npm run analyze -- -d -s # 상세 분석 + 파일 저장 `); process.exit(0); } } return options; } // 메인 실행 if (require.main === module) { const options = parseArgs(); analyzeFinance(options); } export { analyzeFinance }; ``` ### src/utils/file-saver.ts 업데이트 ```typescript import fs from 'fs/promises'; import path from 'path'; export class FileSaver { /** * 마크다운 파일로 저장 */ static async saveAsMarkdown( content: string, filename: string, directory: string = './reports' ): Promise { await fs.mkdir(directory, { recursive: true }); const filepath = path.join(directory, filename); await fs.writeFile(filepath, content, 'utf-8'); console.log(`✅ 리포트 저장: ${filepath}`); } /** * JSON 파일로 저장 */ static async saveAsJSON( data: any, filename: string, directory: string = './reports' ): Promise { await fs.mkdir(directory, { recursive: true }); const filepath = path.join(directory, filename); await fs.writeFile(filepath, JSON.stringify(data, null, 2), 'utf-8'); console.log(`✅ 데이터 저장: ${filepath}`); } /** * CSV 파일로 저장 */ static async saveAsCSV( transactions: any[], filename: string, directory: string = './reports' ): Promise { const header = 'Date,Content,Amount,IsIncome,Category,Account\n'; const rows = transactions.map((t) => [ t.date, `"${t.content}"`, t.amount, t.is_income, `"${t.category.name}"`, `"${t.account.name}"`, ].join(',') ); const csv = header + rows.join('\n'); await fs.mkdir(directory, { recursive: true }); const filepath = path.join(directory, filename); await fs.writeFile(filepath, csv, 'utf-8'); console.log(`✅ CSV 저장: ${filepath}`); } } ``` ## 실행 예제 ### 1. 기본 분석 ```bash npm run analyze ``` 출력: ``` 💰 Money Forward + Vertex AI 재무 분석 ====================================================================== 📅 분석 기간: 2025-10-30 ~ 2025-11-30 📥 Money Forward에서 거래 데이터 조회 중... ✅ 87건의 거래 내역 조회 완료 ====================================================================== 📊 기본 통계 ---------------------------------------------------------------------- 총 수입: ¥500,000 총 지출: ¥320,000 순자산 변동: ¥180,000 📈 거래 건수: 87건 ====================================================================== 🤖 Vertex AI로 분석 중... 🤖 Vertex AI 분석 결과 ====================================================================== [AI 분석 내용...] ====================================================================== ✅ 분석 완료! ``` ### 2. 특정 월 분석 ```bash npm run analyze -- -m 2025-10 ``` ### 3. 상세 분석 + 파일 저장 ```bash npm run analyze -- -d -s ``` 저장되는 파일: ``` reports/ ├── analysis-20251130-143022.md └── data-20251130-143022.json ``` ### 4. 커스텀 출력 경로 ```bash npm run analyze -- -s -o ./my-reports ``` ## 정기 실행 자동화 ### Cron Job 설정 (Linux/Mac) 월초에 자동으로 전월 분석: ```bash # crontab -e 0 9 1 * * cd /path/to/project && npm run analyze -- -s >> /var/log/finance-analysis.log 2>&1 ``` 매주 월요일 아침 9시에 실행: ```bash 0 9 * * 1 cd /path/to/project && npm run analyze -- -s ``` ### GitHub Actions (자동화) `.github/workflows/monthly-analysis.yml`: ```yaml name: Monthly Financial Analysis on: schedule: - cron: '0 0 1 * *' # 매월 1일 00:00 UTC workflow_dispatch: # 수동 실행 가능 jobs: analyze: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Install dependencies run: npm install - name: Run analysis env: MONEYFORWARD_CLIENT_ID: ${{ secrets.MF_CLIENT_ID }} MONEYFORWARD_CLIENT_SECRET: ${{ secrets.MF_CLIENT_SECRET }} GOOGLE_CLOUD_PROJECT: ${{ secrets.GCP_PROJECT }} GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }} run: npm run analyze -- -s - name: Upload reports uses: actions/upload-artifact@v3 with: name: financial-reports path: reports/ ``` ## 대화형 CLI ### src/cli-interactive.ts ```typescript import readline from 'readline'; import { MoneyForwardClient } from './moneyforward/client'; import { FinancialAnalyzer } from './vertexai/analyzer'; import { format, subMonths } from 'date-fns'; async function main() { console.log('💬 대화형 재무 분석 CLI\n'); const mfClient = new MoneyForwardClient(); const analyzer = new FinancialAnalyzer(); // 최근 1개월 데이터 로드 const toDate = format(new Date(), 'yyyy-MM-dd'); const fromDate = format(subMonths(new Date(), 1), 'yyyy-MM-dd'); console.log('📥 데이터 로딩 중...\n'); const transactions = await mfClient.getAllTransactions(fromDate, toDate); console.log(`✅ ${transactions.length}건의 거래 내역 로드 완료\n`); console.log('질문을 입력하세요 (종료: exit)\n'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const askQuestion = () => { rl.question('💬 질문: ', async (question) => { if (question.toLowerCase() === 'exit') { rl.close(); return; } try { const answer = await analyzer.answerQuestion(transactions, question); console.log(`\n🤖 답변:\n${answer}\n`); } catch (error) { console.error('❌ 에러:', error); } askQuestion(); }); }; askQuestion(); } main(); ``` ### package.json 스크립트 추가 ```json { "scripts": { "dev": "tsx src/index.ts", "auth": "tsx src/cli-auth.ts", "fetch": "tsx src/cli-fetch-transactions.ts", "test:ai": "tsx src/cli-test-vertexai.ts", "analyze": "tsx src/index.ts", "chat": "tsx src/cli-interactive.ts", "build": "tsc", "start": "node dist/index.js" } } ``` ## 사용 예시 ### 대화형 모드 ```bash npm run chat ``` ``` 💬 대화형 재무 분석 CLI 📥 데이터 로딩 중... ✅ 87건의 거래 내역 로드 완료 질문을 입력하세요 (종료: exit) 💬 질문: 가장 많이 쓴 카테고리는? 🤖 답변: 가장 많이 지출한 카테고리는 식비로 총 ¥85,000입니다. 전체 지출의 26.6%를 차지하며, 외식이 주를 이루고 있습니다. 💬 질문: 절약할 수 있는 부분은? 🤖 답변: 다음 항목에서 절약이 가능합니다: 1. 외식비 - 주 2-3회 자취로 약 ¥20,000 절감 2. 온라인 쇼핑 - 충동구매 자제로 ¥10,000 절감 3. 미사용 구독 서비스 3개 해지 - ¥2,400/월 절감 💬 질문: exit ``` ## 체크리스트 v9를 완료하기 전에 다음을 확인하세요: - [ ] 메인 애플리케이션 통합 완료 - [ ] CLI 파라미터 파싱 구현 - [ ] 파일 저장 기능 구현 - [ ] 대화형 CLI 구현 - [ ] 다양한 옵션으로 테스트 - [ ] 자동화 스크립트 작성 (선택) ## 다음 단계 v10에서는 에러 핸들링, 로깅, 테스트, 문서화를 완료하고 프로젝트를 마무리합니다. --- **작성일**: 2025-11-30 **상태**: ✅ 완료 **다음**: v10 - 에러 핸들링 및 프로젝트 마무리