# 프로젝트 진행 상황 (Progress) ## 사용자 요구사항 ### 1. Freee API 데이터 및 Google Sheets 업데이트 방식 * **목표**: 매일의 거래 내역을 Google Sheets에 새로운 행으로 추가합니다. ### 2. Vertex AI 역할 * **목표**: 거래 내역의 내용을 바탕으로 카테고리를 자동 분류합니다. --- ## 진행 완료 (2025-11-27) ### Phase 1: 기본 환경 및 Google Sheets 연동 (2025-11-26) * **v1: 프로젝트 환경 설정 (완료):** Node.js/TypeScript 프로젝트를 초기화하고, `dotenv`, `typescript`, `ts-node` 등 초기 의존성을 설치. `tsconfig.json` 파일 설정 완료. * **v2: Google Sheets API 연동 (완료):** 서비스 계정을 설정하고 Google Sheets API를 활성화. TypeScript 코드를 통해 Google Sheet에 성공적으로 연결하고, 테스트 데이터를 읽는 것을 확인. * **v3: Google Sheets 데이터 읽기 (완료):** `Transaction` 인터페이스를 정의하고, 시트에서 데이터를 읽어와 해당 인터페이스에 맞게 파싱하는 `readTransactionData` 함수를 구현. ### Phase 2: Freee API 완전 자동화 (2025-11-27) * **v4 & v5: Freee API OAuth2 인증 및 토큰 자동 갱신 (완료):** 1. **OAuth2 인증 흐름 구현:** 정적 액세스 토큰 방식에서 벗어나, `authorization_code`를 받아 `access_token`과 `refresh_token`을 발급받는 표준 OAuth2 인증 흐름을 구현. 2. **토큰 발급 성공:** 사용자로부터 받은 `authorization_code`를 사용하여 새로운 `access_token`과 `refresh_token`을 성공적으로 발급. 3. **자동 갱신 로직 구현:** 발급받은 `refresh_token`을 사용하여 만료된 `access_token`을 자동으로 갱신하는 로직을 `axios` 인터셉터를 이용해 구현. 4. **주요 이슈 해결:** - `invalid_grant` 오류: 잘못된 BUSINESS_ID (12261708 → 12261605로 수정) - 만료된 리프레시 토큰: 새로운 authorization code로 재발급 * **v6: 토큰 영구 저장 시스템 (완료):** - `src/tokenManager.ts` 생성: 리프레시 토큰을 `tokens.json`에 자동 저장/로드 - Freee의 Rotating Refresh Token 문제 해결 - 새 리프레시 토큰 자동 저장 로직 구현 - **성과**: 한 번의 수동 인증으로 이후 완전 자동화 달성 ### Phase 3: Vertex AI 통합 (2025-11-27) * **v7: Vertex AI (Gemini) 설정 및 연동 (완료):** - `@google-cloud/vertexai` 패키지 설치 - Google Cloud 프로젝트 ID 확인: `spatial-cargo-456805-u2` - Vertex AI API 활성화 - Billing 활성화 (필수) - `src/vertexAiClient.ts` 생성 및 기본 테스트 * **v8: Gemini를 사용한 거래 카테고리 자동 분류 (완료):** - 카테고리 정의: 식비, 교통비, 통신비, 사무용품, 임대료, 인건비, 광고선전비, 접대비, 수수료, 기타 - `classifyTransaction()` 함수 구현: 개별 거래 분류 - `classifyTransactionsBatch()` 함수 구현: 배치 처리 (500ms 딜레이로 레이트 제한 방지) - **주요 이슈 해결:** - 모델 404 오류: `gemini-1.5-flash` → `gemini-2.5-pro`로 변경 - BILLING_DISABLED 오류: 사용자가 Billing 활성화 - PROJECT_ID 오류: `planitai-co-jp` → `spatial-cargo-456805-u2`로 수정 ### Phase 4: 통합 및 자동화 (2025-11-27) * **v9: Google Sheets 자동 저장 및 중복 제거 (완료):** - `appendFreeeDeals()` 함수 구현: 카테고리 포함 데이터 저장 - `ensureSheetExists()`: 시트 자동 생성 - `checkHeaderExists()`: 헤더 자동 추가 - `getExistingDealIds()`: 기존 거래 ID 조회로 중복 방지 - 거래 ID 기반 중복 제거 시스템 완성 * **v10: 전체 시스템 통합 및 테스트 (완료):** - `src/index.ts`: Freee → Vertex AI → Google Sheets 전체 플로우 통합 - `src/testVertexAI.ts`: AI 분류 기능 단독 테스트 스크립트 - 실제 테스트 성공: - 11개 거래 조회 - AI로 카테고리 자동 분류 (수수료 2건, 식비 1건, 기타 8건) - Google Sheets에 저장 (중복 제거 동작 확인) ### Phase 5: 문서화 (2025-11-27) * **블로그 시리즈 작성 (완료):** - v6.md: 토큰 영구 저장 및 자동 갱신 완성 - v7.md: Vertex AI (Gemini) 설정 및 연동 - v8.md: Gemini를 사용한 거래 내역 자동 카테고리 분류 - v9.md: Google Sheets에 카테고리가 포함된 거래 내역 자동 저장 - v10.md: 자동화 완성 및 운영 가이드 * **일본어 기술 블로그 작성 (완료):** - v1~v10 내용을 약 절반으로 축약 - 일본어로 번역 및 재구성 - `googlesheet-vertexai-freee-script-ja.md` (528줄) - 회사 기술 블로그 투고용 형식으로 작성 - 클릭 가능한 목차 추가 --- ## 최종 구현 결과 ### 전체 시스템 아키텍처 ``` ┌─────────────┐ │ Freee API │ ──► OAuth2 인증 (자동 토큰 갱신) └─────────────┘ │ ▼ ┌─────────────────┐ │ 거래 내역 조회 │ ──► 이번 달 거래 데이터 └─────────────────┘ │ ▼ ┌─────────────────┐ │ Vertex AI │ ──► Gemini 2.5 Pro로 카테고리 자동 분류 │ (Gemini) │ (식비, 교통비, 수수료 등) └─────────────────┘ │ ▼ ┌─────────────────┐ │ Google Sheets │ ──► 중복 제거 후 자동 저장 │ │ (카테고리 포함) └─────────────────┘ ``` ### 파일 구조 ``` /20251126-googlesheet-vertexai-freee-script ├── /src │ ├── index.ts # 메인 통합 스크립트 │ ├── testVertexAI.ts # Vertex AI 테스트 전용 │ ├── freeeClient.ts # Freee API 클라이언트 (OAuth2 자동화) │ ├── googleSheetClient.ts # Google Sheets API 클라이언트 │ ├── vertexAiClient.ts # Vertex AI 클라이언트 (Gemini) │ ├── tokenManager.ts # 토큰 영구 저장 관리 │ └── interfaces.ts # TypeScript 인터페이스 정의 ├── /credentials │ └── freee-sheets-service-key.json # Google 서비스 계정 키 ├── .env # 환경 변수 ├── tokens.json # 자동 생성되는 토큰 파일 (리프레시 토큰) ├── package.json ├── tsconfig.json ├── .gitignore ├── progress.md # 이 파일 ├── prompts.md # 주요 프롬프트 및 상호작용 기록 └── /블로그 포스트 ├── googlesheet-vertexai-freee-script-v1.md ~ v10.md └── googlesheet-vertexai-freee-script-ja.md (일본어 통합본) ``` ### 핵심 기능 1. ✅ **Freee API OAuth2 완전 자동화** - Rotating Refresh Token 자동 저장 - 한 번의 인증으로 영구 사용 - Axios 인터셉터를 통한 자동 토큰 갱신 2. ✅ **Vertex AI 자동 카테고리 분류** - Gemini 2.5 Pro 모델 사용 - 10개 카테고리 자동 분류 - 500ms 딜레이로 레이트 제한 방지 3. ✅ **Google Sheets 자동 동기화** - 거래 ID 기반 중복 제거 - 시트 및 헤더 자동 생성 - 카테고리 포함 데이터 저장 4. ✅ **완전 무인 운용 가능** - Cron, GitHub Actions 등으로 스케줄링 가능 - 에러 핸들링 완비 - 로깅 시스템 구축 ### 실제 테스트 결과 (2025-11-27) ``` 🚀 Freee → Vertex AI → Google Sheets 자동 동기화 시작... 📅 조회 기간: 2025-10-31 ~ 2025-11-27 1️⃣ Freee API에서 거래 내역 조회 중... ✅ 11개의 거래 내역을 가져왔습니다. 2️⃣ Vertex AI로 카테고리 자동 분류 중... Vertex AI로 11개의 거래 분류 중... 진행: 5/11 진행: 10/11 진행: 11/11 ✅ 11개의 거래 카테고리 분류 완료 3️⃣ Google Sheets에 거래 내역 추가 중... 추가할 새로운 거래가 없습니다. ✅ 동기화 완료! - 추가된 거래: 0개 - 중복 스킵: 11개 - AI 분류된 카테고리: 11개 ``` 분류 결과: - [수수료] 2건 (은행 수수료) - [식비] 1건 - [기타] 8건 --- ## 해결한 주요 기술 과제 ### 1. Rotating Refresh Token 관리 **문제**: Freee API는 새 액세스 토큰 발급 시마다 새로운 리프레시 토큰을 반환하며, 이전 토큰은 무효화됨. **해결**: `tokenManager.ts`를 통해 `tokens.json`에 최신 리프레시 토큰을 자동 저장. 토큰 갱신 시마다 새 토큰을 파일에 쓰기. ### 2. Vertex AI 모델 및 프로젝트 설정 **문제**: - `gemini-1.5-flash` 모델 404 오류 - 잘못된 프로젝트 ID 사용 - BILLING_DISABLED 오류 **해결**: - `gemini-2.5-pro` 모델로 변경 - 서비스 계정 JSON에서 정확한 프로젝트 ID 확인 - Google Cloud Console에서 Billing 활성화 ### 3. API 레이트 제한 **문제**: Vertex AI를 연속 호출 시 레이트 제한 가능성. **해결**: 배치 처리 시 각 요청 사이에 500ms 딜레이 추가. ### 4. 중복 데이터 방지 **문제**: 스크립트를 여러 번 실행 시 동일 거래가 중복 저장됨. **해결**: Google Sheets에서 기존 거래 ID를 모두 조회하여 Set에 저장하고, 새 거래만 필터링하여 추가. --- ## 향후 개선 사항 1. **캐싱 시스템**: 동일한 파트너 ID에 대한 분류 결과 재사용으로 API 비용 절감 2. **배치 프롬프트**: 여러 거래를 하나의 프롬프트로 처리하여 API 호출 횟수 감소 3. **에러 알림**: Slack 또는 이메일로 오류 발생 시 알림 4. **데이터 시각화**: Google Sheets 데이터 기반 월간/연간 리포트 자동 생성 5. **다중 회사 지원**: 여러 Freee 회사 계정을 하나의 스크립트로 관리 --- ## 프로젝트 상태: ✅ 완료 모든 목표가 달성되었으며, 실제 운영 환경에 배포 가능한 상태입니다. **최종 업데이트**: 2025-11-27