diff --git a/API_SPEC.md b/API_SPEC.md index b14598e..38cc341 100644 --- a/API_SPEC.md +++ b/API_SPEC.md @@ -13,13 +13,15 @@ - **POST /api/writing/recent**: 최근 글 (limit 파라미터) - **서버 레이어**: `src/lib/server/writing.ts` (Firestore CRUD) -### ⚡ Content Hash 기반 스마트 캐싱 +### ⚡ Content Hash 기반 3단계 스마트 캐싱 - **POST /api/analyze-pattern**: contentHash 파라미터 추가 -- **L1 캐시**: localStorage (영구, LRU 10개) -- **L2 캐시**: Server in-memory (5분, 50개) +- **L1 캐시**: localStorage (영구, LRU 10개) ~1ms +- **L2 캐시**: Firestore `patternAnalyses` 컬렉션 (영구) ~100ms +- **L3 캐시**: Server in-memory (5분, 50개) ~50ms - **해시 생성**: `id:updatedAt` 조합 (SHA-256) - **자동 변경 감지**: 글 추가/수정 → 해시 변경 → 재분석 -- **성능 개선**: 캐시 히트 시 1ms vs AI 분석 5~10초 +- **AI 비용 절감**: 동일 글 세트는 전체 사용자 기준 1회만 분석 +- **서버 레이어**: `src/lib/server/patternAnalysis.ts` (Firestore CRUD) ## ⚠️ 변경사항 (2025-11-11) @@ -295,12 +297,14 @@ const result = await analyzeText("오늘 날씨가 좋다."); - 권한: 팀 소유자만 - 팀 외 글(자유 주제, 다른 팀)은 제외 -**🆕 Content Hash 기반 캐싱** (2025-11-12): +**🆕 Content Hash 기반 3단계 캐싱** (2025-11-12): **캐싱 전략**: -- **L1 (Client)**: localStorage에 contentHash를 키로 저장 (영구, LRU 10개) -- **L2 (Server)**: In-memory에 contentHash를 키로 저장 (5분 TTL, 최대 50개) +- **L1 (Client)**: localStorage에 contentHash를 키로 저장 (영구, LRU 10개) ~1ms +- **L2 (Firestore)**: `patternAnalyses/{contentHash}` 컬렉션에 저장 (영구) ~100ms +- **L3 (Server)**: In-memory Map에 저장 (5분 TTL, 최대 50개) ~50ms - **변경 감지**: 글 추가/수정 시 `updatedAt` 변경 → 해시 변경 → 자동 재분석 +- **AI 비용 절감**: 동일 글 세트는 전체 사용자 기준 1회만 분석 (Firestore 공유) **Hash 생성 규칙**: ```typescript @@ -314,24 +318,38 @@ const result = await analyzeText("오늘 날씨가 좋다."); - 캐시 히트 (서버): ~50ms (in-memory) - 캐시 미스: 5~10초 (AI 분석) +**Firestore 저장 구조**: +```typescript +patternAnalyses/{contentHash} + - contentHash: string + - pattern: WritingPatternAnalysis + - createdAt: Timestamp +``` + **사용 흐름**: ```typescript // 클라이언트 (self 분석) 1. 글 목록 조회 2. contentHash 계산 -3. localStorage 확인 → 히트 시 즉시 반환 +3. L1 확인 (localStorage) → 히트 시 즉시 반환 (~1ms) 4. 서버 요청 (contentHash 포함) -5. 서버 응답 → localStorage에 저장 +5. 서버 응답 → L1에 저장 // 서버 -1. contentHash 받음 → 캐시 확인 → 히트 시 즉시 반환 -2. 캐시 미스 → 글 조회 -3. 서버 contentHash 계산 → 캐시 확인 -4. AI 분석 수행 -5. contentHash 키로 캐시 저장 -6. contentHash 포함하여 응답 +1. 클라이언트 contentHash로 L3 확인 (in-memory) → 히트 시 즉시 반환 (~50ms) +2. 권한 체크 및 글 조회 +3. 서버 contentHash 계산 +4. L3 재확인 (in-memory) → 히트 시 즉시 반환 +5. L2 확인 (Firestore) → 히트 시 반환 + L3 저장 (~100ms) +6. 캐시 미스: AI 분석 수행 (5~10초) +7. L2 (Firestore) + L3 (in-memory)에 저장 +8. contentHash 포함하여 응답 ``` +**AI 비용 절감**: +- 동일한 글 세트는 **전체 사용자 기준 1회만 분석** (Firestore 공유) +- 예: 학생 A가 글 10개 작성 → 학생 B도 같은 글 10개 작성 → B는 AI 분석 없이 Firestore에서 조회 + --- ## Team API diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md index 1168dcf..408374d 100644 --- a/PROJECT_STRUCTURE.md +++ b/PROJECT_STRUCTURE.md @@ -28,12 +28,14 @@ - 멤버 카드 메뉴에 "팀 내 글 분석" 버튼 (by-team) - TopicMemberAnalysisSection 컴포넌트 (by-topic - 추후 구현) - 🔒 **보안**: 팀 외 글(자유 주제, 다른 팀)은 분석에서 제외 -- ⚡ **Content Hash 기반 스마트 캐싱** - - L1 캐시: localStorage (영구, LRU 10개) - - L2 캐시: Server in-memory (5분, 50개) +- ⚡ **Content Hash 기반 3단계 스마트 캐싱** + - L1 캐시: localStorage (영구, LRU 10개) ~1ms + - L2 캐시: Firestore `patternAnalyses` 컬렉션 (영구) ~100ms + - L3 캐시: Server in-memory (5분, 50개) ~50ms - 해시 생성: `id:updatedAt` 조합 (SHA-256) - 변경 자동 감지: 글 추가/수정 시 해시 변경 → 재분석 - - 성능: 캐시 히트 시 1ms (localStorage) vs 5~10초 (AI 분석) + - AI 비용 절감: 동일 글 세트는 전체 사용자 기준 1회만 분석 + - 서버 레이어: `src/lib/server/patternAnalysis.ts` (Firestore CRUD) - 유틸리티: `contentHash.ts`, `patternCacheManager.ts` **2025-11-11 (PM) 업데이트**: @@ -399,7 +401,7 @@ | API | 경로 | 메서드 | 설명 | 상태 | |-----|------|--------|------|------| | **텍스트 분석** | `/api/analyze-text` | POST | **Gemini 기반 텍스트 분석** (Delta 지원, 캐싱, 히스토리 인식) | ✅ 완료 | -| **패턴 분석** | `/api/analyze-pattern` | POST | **글 작성 패턴 분석** (3가지 타입, contentHash 기반 2단계 캐싱, 변경 감지) | ✅ 완료 | +| **패턴 분석** | `/api/analyze-pattern` | POST | **글 작성 패턴 분석** (3가지 타입, contentHash 기반 3단계 캐싱, 변경 감지) | ✅ 완료 | | **맞춤법 검사** | `/api/spelling/check` | POST | **Gemini 기반 맞춤법 검사** (초등학생 눈높이) | ✅ 완료 | | **글 생성** | `/api/writing` | POST | 🆕 **글 생성** (wordCount/charCount 자동 계산) | ✅ 완료 | | **글 조회** | `/api/writing/[id]` | GET | 🆕 **글 조회** (작성자만 접근) | ✅ 완료 | @@ -419,6 +421,7 @@ - `user.ts` - 사용자 Firestore CRUD - `topic.ts` - 주제 Firestore CRUD - 🆕 `writing.ts` - 글 Firestore CRUD (createWriting, getWriting, updateWriting, deleteWriting, getUserWritings, getRecentWritings, isWritingOwner) +- 🆕 `patternAnalysis.ts` - 패턴 분석 결과 Firestore 저장/조회 (contentHash 키, 영구 저장) --- diff --git a/ROADMAP.md b/ROADMAP.md index f95b75f..213e95e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -82,7 +82,7 @@ | **Toast 알림 추가** | **텍스트 분석/맞춤법 검사 시작/완료/실패 알림, 점수/에러 개수 표시, 로딩 상태 (duration: Infinity)** | **2025-11-11** | | **Writing API 구현** | **POST /api/writing (글 생성), GET/PUT/DELETE /api/writing/[id] (조회/수정/삭제), POST /api/writing/user (목록), POST /api/writing/recent (최근 글), src/lib/server/writing.ts (Firestore CRUD), 권한 체크 (작성자만), 텍스트 통계 자동 계산** | **2025-11-12** | | **패턴 분석 - 팀 소유자 기능** | **3가지 분석 타입 (self/by-team/by-topic), API 권한 체크, 팀 주제 필터링, WritingPatternDialog Props 확장, TopicMemberAnalysisSection (UI만), 팀 관리 페이지에 멤버 분석 메뉴** | **2025-11-12** | -| **Content Hash 기반 스마트 캐싱** | **글 목록 해시 생성 (id+updatedAt), L1: localStorage (영구, LRU 10개), L2: Server in-memory (5분, 50개), 변경 자동 감지, 재분석 최소화, contentHash.ts + patternCacheManager.ts** | **2025-11-12** | +| **Content Hash 기반 3단계 캐싱** | **글 목록 해시 생성 (id+updatedAt), L1: localStorage (영구, LRU 10개), L2: Firestore patternAnalyses (영구), L3: Server in-memory (5분, 50개), 변경 자동 감지, AI 비용 절감 (전체 사용자 기준 1회 분석), contentHash.ts + patternCacheManager.ts + patternAnalysis.ts** | **2025-11-12** | ### 🚧 진행 중