docs: Sync documentation from private repository
This commit is contained in:
parent
dd9d457332
commit
680b54519a
@ -1,26 +1,51 @@
|
|||||||
# 라온누리 - 프로젝트 구조
|
# 라온누리 - 프로젝트 구조
|
||||||
|
|
||||||
> 최종 업데이트: 2025-11-18 (팀 코드 다국어 생성 + Realtime DB 예약 시스템)
|
> 최종 업데이트: 2025-11-21 (수정 모드 UX 개선 + 주제 변경 차단)
|
||||||
|
|
||||||
초등학생을 위한 창작 글쓰기 교육 플랫폼
|
초등학생을 위한 창작 글쓰기 교육 플랫폼
|
||||||
|
|
||||||
**최신 업데이트** (2025-11-17):
|
**최신 업데이트** (2025-11-21):
|
||||||
|
- 🎨 **수정 모드 UX 대폭 개선**
|
||||||
|
- **Sticky 헤더바**: 오렌지/앰버 그라데이션 배경, 상단 고정 (z-index: 100)
|
||||||
|
- **강조된 테두리**: 주제 선택 + 글쓰기 영역에 오렌지 테두리 (2px solid)
|
||||||
|
- **섀도우 효과**: 글쓰기 영역에 오렌지 글로우 (라이트/다크 모드 대응)
|
||||||
|
- **Writing ID 표시**: 어떤 글을 수정 중인지 명확하게 표시
|
||||||
|
- **색상 시스템**: Light(#FFB366, #FF9800, #E65100) / Dark(#8B6B47, #C4A572)
|
||||||
|
- 기존 단순 배지 → 전체 UI 테마로 업그레이드
|
||||||
|
- 🔒 **수정 모드 주제 변경 차단**
|
||||||
|
- TopicSelector에 `readonly` prop 추가
|
||||||
|
- 수정 모드에서는 Select 드롭다운 숨김, "현재 주제" 라벨만 표시
|
||||||
|
- 데이터 무결성 보장 (템플릿 덮어쓰기 방지)
|
||||||
|
- AI 설정/실시간 모니터링 혼선 방지
|
||||||
|
- 다국어 지원: `readonlyNote`, `currentTopic` (ko, en, ja)
|
||||||
|
- 🧹 **UI 정리**
|
||||||
|
- "새 글쓰기" 버튼 제거 (불필요한 기능, 실수 방지)
|
||||||
|
- 상단 버튼 영역 단순화 ("저장된 글조각" 버튼만 유지)
|
||||||
|
- 미사용 i18n 키 정리 (`newWriting`, `discardConfirm`)
|
||||||
|
|
||||||
|
**이전 업데이트** (2025-11-20):
|
||||||
|
- 🎨 **AI 이미지 생성 스타일 일관성 개선**
|
||||||
|
- **Vertex AI Imagen 4.0 Fast**: 글 내용 기반 자동 이미지 생성 (모델 업그레이드)
|
||||||
|
- **일관된 스타일 가이드**: 모든 이미지에 동일한 화풍 적용
|
||||||
|
- 화풍: 따뜻한 디지털 일러스트, 애니메이션/만화 스타일
|
||||||
|
- 색감: 부드럽고 따뜻한 톤, 자연스러운 채도
|
||||||
|
- 분위기: 친근하고 밝은, 초등학생 눈높이
|
||||||
|
- **강화된 Negative Prompt**: 과도한 사실주의, 어두운 분위기, 유치한 캐릭터 차단
|
||||||
|
- **한국 문화권 고려**: "Korean elementary student" 명시로 아시아권 얼굴 특징 반영
|
||||||
|
- **AI 프롬프트 최적화**: Gemini Flash가 원문 → 핵심 키워드 추출 (6-12개) → 스타일 키워드 자동 추가
|
||||||
|
- **폴백 안전성**: AI 최적화 실패 시에도 일관된 스타일 적용
|
||||||
|
|
||||||
|
**이전 업데이트** (2025-11-17):
|
||||||
- 🎨 **AI 이미지 생성 시스템 + 장면 분리 + 프롬프트 최적화**
|
- 🎨 **AI 이미지 생성 시스템 + 장면 분리 + 프롬프트 최적화**
|
||||||
- **Vertex AI Imagen 3.0**: 글 내용 기반 자동 이미지 생성
|
|
||||||
- **AI 장면 분리**: Gemini가 글에서 3~5개 주요 장면 자동 추출
|
- **AI 장면 분리**: Gemini가 글에서 3~5개 주요 장면 자동 추출
|
||||||
- **AI 프롬프트 최적화**: Gemini Flash가 원문 → 핵심 키워드 추출 (string[]) → 최적화된 프롬프트 조합
|
- **4단계 플로우**: 장면 추출 → 장면 선택 → 프롬프트 최적화 → 이미지 생성 → 결과 표시
|
||||||
- **4단계 플로우**: 장면 추출 → 장면 선택 → **프롬프트 최적화** → 이미지 생성 → 결과 표시
|
|
||||||
- **사용자 선택권**: 여러 장면 중 원하는 장면만 이미지로 생성
|
- **사용자 선택권**: 여러 장면 중 원하는 장면만 이미지로 생성
|
||||||
- **구조화된 프롬프트**: 피사체/행동/배경/디테일/분위기/스타일 구분하여 추출
|
- **구조화된 프롬프트**: 피사체/행동/배경/디테일/분위기/스타일 구분하여 추출
|
||||||
- **이모지 표시**: 각 장면의 성격을 이모지로 시각화 (🏐 🎮 🍲)
|
|
||||||
- **원문 미리보기**: 각 장면의 원문 80자 표시
|
|
||||||
- **재선택 가능**: 이미지 생성 후 "다른 장면 선택"으로 여러 이미지 생성
|
- **재선택 가능**: 이미지 생성 후 "다른 장면 선택"으로 여러 이미지 생성
|
||||||
- **Fallback 안전성**: 프롬프트 최적화 실패 시 기본 방식으로 자동 전환
|
|
||||||
- **Firebase Storage 저장**: base64 이미지 → Storage 업로드 → 공개 URL 생성
|
- **Firebase Storage 저장**: base64 이미지 → Storage 업로드 → 공개 URL 생성
|
||||||
- **Writing 문서 업데이트**: generatedImage 필드에 이미지 정보 저장
|
- **Writing 문서 업데이트**: generatedImage 필드에 이미지 정보 저장
|
||||||
- **안전 필터링**: 부적절한 콘텐츠 자동 차단
|
- **안전 필터링**: 부적절한 콘텐츠 자동 차단
|
||||||
- **다국어 지원**: 한국어/영어/일본어 프롬프트 및 UI
|
- **다국어 지원**: 한국어/영어/일본어 프롬프트 및 UI
|
||||||
- **Multi-region failover**: vertexAI.ts 확장 (기존 인프라 재사용)
|
|
||||||
- **타입**: Scene, SceneExtractionResponse
|
- **타입**: Scene, SceneExtractionResponse
|
||||||
- **서비스**: sceneExtractionService.ts (장면 추출), imagenService.ts (프롬프트 최적화)
|
- **서비스**: sceneExtractionService.ts (장면 추출), imagenService.ts (프롬프트 최적화)
|
||||||
- **프롬프트**: sceneExtraction.ts (장면 분리), promptOptimization.ts (키워드 추출)
|
- **프롬프트**: sceneExtraction.ts (장면 분리), promptOptimization.ts (키워드 추출)
|
||||||
|
|||||||
@ -215,7 +215,7 @@ NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
|
|||||||
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
|
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
|
||||||
|
|
||||||
# 사이트 URL (프로덕션)
|
# 사이트 URL (프로덕션)
|
||||||
NEXT_PUBLIC_URL=https://raonnuri.com
|
NEXT_PUBLIC_URL=https://raonnuri.life
|
||||||
|
|
||||||
# API Base URL (선택적, 기본값: /api)
|
# API Base URL (선택적, 기본값: /api)
|
||||||
NEXT_PUBLIC_API_URL=/api
|
NEXT_PUBLIC_API_URL=/api
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# 라온누리 - 개발 로드맵
|
# 라온누리 - 개발 로드맵
|
||||||
|
|
||||||
> 최종 업데이트: 2025-11-19 (AI Delta 개선 + Draft 동기화 + Firebase Functions Phase 1)
|
> 최종 업데이트: 2025-11-21 (수정 모드 UX 개선 + 주제 변경 차단)
|
||||||
|
|
||||||
초등학생을 위한 창작 글쓰기 교육 플랫폼 개발 계획
|
초등학생을 위한 창작 글쓰기 교육 플랫폼 개발 계획
|
||||||
|
|
||||||
@ -89,6 +89,7 @@
|
|||||||
| **AI 글쓰기 도우미 시스템** | **4단계 점진적 힌트 시스템 (질문 → 방향 → 선택지 → 예시 문장), useWritingInactivityDetection 훅 (5분 작성 멈춤 감지, 타이머 리셋, 남은 시간), UI 컴포넌트 3개 (InactivityPrompt 플로팅 버튼, HintDisplay Dialog, AIAssistancePanel), writingAssistanceService.ts (Vertex AI, 주제 맥락 활용, 서버 캐싱), writingAssistance.ts 프롬프트 (4단계 × 3개 언어 ko/en/ja), 글쓰기 페이지 통합 (AI 도움 요청, 서버 에러 처리), POST /api/writing-assistance (주제 정보 전달, 팀 설정 검증), GET/PUT /api/team/[teamId]/ai-config (AI 설정 조회/업데이트), Team.aiAssistanceConfig 필드 (enabled, detectionTimeMinutes, maxHintsPerWriting, cooldownMinutes, allowedHintLevels, requireSelfEdit), DEFAULT_AI_ASSISTANCE_CONFIG 상수, 팀 관리 페이지 AI On/Off 토글 (Switch.Root v3), TeamManager AI 메서드 (getAIConfig, updateAIConfig), lib/server/team.ts AI 함수 (getTeamAIConfig, updateTeamAIConfig), 서버 검증 (enabled=false → 403, allowedHintLevels 체크), 사용 제한 (글당 5회, 3분 쿨다운), 다국어 번역 추가 (messages/*.json, aiAssist namespace 19개 키), successResponse() 헬퍼 사용, AIAssistanceRecord 타입 (timestamp, hintLevel, topicId, topicTitle, context, hintProvided, wasUsed)** | **2025-11-14** |
|
| **AI 글쓰기 도우미 시스템** | **4단계 점진적 힌트 시스템 (질문 → 방향 → 선택지 → 예시 문장), useWritingInactivityDetection 훅 (5분 작성 멈춤 감지, 타이머 리셋, 남은 시간), UI 컴포넌트 3개 (InactivityPrompt 플로팅 버튼, HintDisplay Dialog, AIAssistancePanel), writingAssistanceService.ts (Vertex AI, 주제 맥락 활용, 서버 캐싱), writingAssistance.ts 프롬프트 (4단계 × 3개 언어 ko/en/ja), 글쓰기 페이지 통합 (AI 도움 요청, 서버 에러 처리), POST /api/writing-assistance (주제 정보 전달, 팀 설정 검증), GET/PUT /api/team/[teamId]/ai-config (AI 설정 조회/업데이트), Team.aiAssistanceConfig 필드 (enabled, detectionTimeMinutes, maxHintsPerWriting, cooldownMinutes, allowedHintLevels, requireSelfEdit), DEFAULT_AI_ASSISTANCE_CONFIG 상수, 팀 관리 페이지 AI On/Off 토글 (Switch.Root v3), TeamManager AI 메서드 (getAIConfig, updateAIConfig), lib/server/team.ts AI 함수 (getTeamAIConfig, updateTeamAIConfig), 서버 검증 (enabled=false → 403, allowedHintLevels 체크), 사용 제한 (글당 5회, 3분 쿨다운), 다국어 번역 추가 (messages/*.json, aiAssist namespace 19개 키), successResponse() 헬퍼 사용, AIAssistanceRecord 타입 (timestamp, hintLevel, topicId, topicTitle, context, hintProvided, wasUsed)** | **2025-11-14** |
|
||||||
| **AI 설정 고급 UI 완성** | **AIConfigDialog 컴포넌트 (팀 관리 페이지), Slider 3개 (멈춤 감지/최대 힌트/쿨다운), 커스텀 힌트 레벨 카드 (반투명 배경 번호, 우상단 접힌 페이지 삼각형 인디케이터, CSS border trick, 직접 onClick 처리), SimpleGrid 2x2 레이아웃, 브랜드 컬러 상태 변화, Switch (AI 제안 그대로 사용 금지), 함수형 상태 업데이트 (클로저 해결), 다국어 지원 (ko/en/ja, team.manage.aiConfig namespace 28개 키)** | **2025-11-17** |
|
| **AI 설정 고급 UI 완성** | **AIConfigDialog 컴포넌트 (팀 관리 페이지), Slider 3개 (멈춤 감지/최대 힌트/쿨다운), 커스텀 힌트 레벨 카드 (반투명 배경 번호, 우상단 접힌 페이지 삼각형 인디케이터, CSS border trick, 직접 onClick 처리), SimpleGrid 2x2 레이아웃, 브랜드 컬러 상태 변화, Switch (AI 제안 그대로 사용 금지), 함수형 상태 업데이트 (클로저 해결), 다국어 지원 (ko/en/ja, team.manage.aiConfig namespace 28개 키)** | **2025-11-17** |
|
||||||
| **AI 이미지 생성 + 장면 분리 + 프롬프트 최적화** | **Vertex AI Imagen 3.0 통합, AI 장면 분리 기능 (Gemini Flash), AI 프롬프트 최적화 (Gemini Flash-Lite, 원문 → 핵심 키워드 배열 추출 → 쉼표 연결, Fallback 안전성), 4단계 플로우 (장면 추출 → 장면 선택 → 프롬프트 최적화 → 이미지 생성 → 결과 표시), Scene/SceneExtractionResponse 타입 추가, sceneExtractionService.ts (글 → 3~5개 장면 자동 추출, 장면별 프롬프트 생성), sceneExtraction.ts 프롬프트 (ko/en/ja, Response Schema), promptOptimization.ts 프롬프트 (키워드 추출, ko/en/ja), POST /api/extract-scenes (장면 추출 API), SceneSelector 컴포넌트 (RadioCard, 이모지, 원문 미리보기 80자, ItemHiddenInput 추가), GeneratedImage 타입 (url, prompt, generatedAt, modelName), imagenService.ts (글 → 어린이 친화적 프롬프트 자동 변환, optimizePromptForImage 함수, 안전 필터링), vertexAI.ts 확장 (generateImage 함수, multi-region failover 재사용), imageStorage.ts (Firebase Storage 업로드, base64 → 공개 URL 변환, toDataURL 헬퍼), POST /api/generate-image (권한 체크, AI 프롬프트 최적화, Imagen API 호출, Storage 저장, Writing.generatedImage 필드 업데이트), GenerateImageDialog 개선 (4단계 플로우, 장면 선택 UI, "다른 장면 선택" 버튼), 글쓰기 페이지 통합 ("구체화하기" 버튼, 저장 완료 후 표시, 홈 이동 제거), Firebase Storage 초기화 (fbStorage), 다국어 번역 (write.generateImage + write.extractScenes namespace, ko/en/ja 22개 키), 타입 체크 통과** | **2025-11-17** |
|
| **AI 이미지 생성 + 장면 분리 + 프롬프트 최적화** | **Vertex AI Imagen 3.0 통합, AI 장면 분리 기능 (Gemini Flash), AI 프롬프트 최적화 (Gemini Flash-Lite, 원문 → 핵심 키워드 배열 추출 → 쉼표 연결, Fallback 안전성), 4단계 플로우 (장면 추출 → 장면 선택 → 프롬프트 최적화 → 이미지 생성 → 결과 표시), Scene/SceneExtractionResponse 타입 추가, sceneExtractionService.ts (글 → 3~5개 장면 자동 추출, 장면별 프롬프트 생성), sceneExtraction.ts 프롬프트 (ko/en/ja, Response Schema), promptOptimization.ts 프롬프트 (키워드 추출, ko/en/ja), POST /api/extract-scenes (장면 추출 API), SceneSelector 컴포넌트 (RadioCard, 이모지, 원문 미리보기 80자, ItemHiddenInput 추가), GeneratedImage 타입 (url, prompt, generatedAt, modelName), imagenService.ts (글 → 어린이 친화적 프롬프트 자동 변환, optimizePromptForImage 함수, 안전 필터링), vertexAI.ts 확장 (generateImage 함수, multi-region failover 재사용), imageStorage.ts (Firebase Storage 업로드, base64 → 공개 URL 변환, toDataURL 헬퍼), POST /api/generate-image (권한 체크, AI 프롬프트 최적화, Imagen API 호출, Storage 저장, Writing.generatedImage 필드 업데이트), GenerateImageDialog 개선 (4단계 플로우, 장면 선택 UI, "다른 장면 선택" 버튼), 글쓰기 페이지 통합 ("구체화하기" 버튼, 저장 완료 후 표시, 홈 이동 제거), Firebase Storage 초기화 (fbStorage), 다국어 번역 (write.generateImage + write.extractScenes namespace, ko/en/ja 22개 키), 타입 체크 통과** | **2025-11-17** |
|
||||||
|
| **AI 이미지 생성 스타일 일관성 개선** | **Imagen 4.0 Fast로 업그레이드, 일관된 스타일 가이드 적용 (모든 이미지 동일 화풍), 애니메이션/만화 스타일로 전환 (세미 리얼리즘 제거), 한국 문화권 고려 ("Korean elementary student" 명시), 강화된 Negative Prompt (과도한 사실주의, 어두운 분위기 차단), 키워드 개수 증가 (6-12개), promptOptimization.ts 프롬프트 개선 (스타일 가이드 추가, 예시 업데이트), imagenService.ts 폴백 로직 개선 (일관된 스타일 유지), vertexAI.ts Negative Prompt 강화 (excessive realism, photorealistic, dark atmosphere 추가)** | **2025-11-20** |
|
||||||
| **내가 쓴 글 목록 + 글 수정 기능** | **WritingCard 컴포넌트 (제목, 날짜, 미리보기, 주제/점수/이미지 배지, 삭제 메뉴, framer-motion 삭제 애니메이션, layoutId), /home 페이지 최근 글 3개 표시 (SimpleGrid, "모두 보기" 버튼, AnimatePresence), /writings 전체 글 목록 페이지 (정렬 Select, empty state, AnimatePresence), 다국어 번역 추가 (writings 섹션 ko/en/ja 22개 키, home.recentActivity.viewAll), /write 페이지 글 수정 기능 (URL params ?id=xxx, useSearchParams, isEditMode 상태, getWriting으로 로드, updateWriting 호출, 수정 모드 배지), 번역 추가 (write.editMode/editModeDesc/editModeBadge/writingNotFound/loadFailed)** | **2025-11-18** |
|
| **내가 쓴 글 목록 + 글 수정 기능** | **WritingCard 컴포넌트 (제목, 날짜, 미리보기, 주제/점수/이미지 배지, 삭제 메뉴, framer-motion 삭제 애니메이션, layoutId), /home 페이지 최근 글 3개 표시 (SimpleGrid, "모두 보기" 버튼, AnimatePresence), /writings 전체 글 목록 페이지 (정렬 Select, empty state, AnimatePresence), 다국어 번역 추가 (writings 섹션 ko/en/ja 22개 키, home.recentActivity.viewAll), /write 페이지 글 수정 기능 (URL params ?id=xxx, useSearchParams, isEditMode 상태, getWriting으로 로드, updateWriting 호출, 수정 모드 배지), 번역 추가 (write.editMode/editModeDesc/editModeBadge/writingNotFound/loadFailed)** | **2025-11-18** |
|
||||||
| **주제별 학생 분석 API** | **GET /api/topic/[topicId]/writers 구현 (팀 주제로 글 쓴 학생 목록 + 글 개수), TopicWriter 타입 추가 (uid, name, email, writingCount), getTopicWriters 서버 함수 (writings 쿼리, userId 그룹화, Firebase Auth 사용자 정보 결합, 글 개수 내림차순 정렬), TopicManager.getTopicWriters 메서드 (2분 캐싱), TopicMemberAnalysisSection UI 완성 (Accordion, 주제별 학생 목록, "이 주제 분석" 버튼, by-topic 분석 연동), 권한 체크 (팀 소유자만 접근), 다국어 번역 추가 (team.manage.topicAnalysis namespace, ko/en/ja 8개 키), 안내 메시지 제거** | **2025-11-18** |
|
| **주제별 학생 분석 API** | **GET /api/topic/[topicId]/writers 구현 (팀 주제로 글 쓴 학생 목록 + 글 개수), TopicWriter 타입 추가 (uid, name, email, writingCount), getTopicWriters 서버 함수 (writings 쿼리, userId 그룹화, Firebase Auth 사용자 정보 결합, 글 개수 내림차순 정렬), TopicManager.getTopicWriters 메서드 (2분 캐싱), TopicMemberAnalysisSection UI 완성 (Accordion, 주제별 학생 목록, "이 주제 분석" 버튼, by-topic 분석 연동), 권한 체크 (팀 소유자만 접근), 다국어 번역 추가 (team.manage.topicAnalysis namespace, ko/en/ja 8개 키), 안내 메시지 제거** | **2025-11-18** |
|
||||||
| **팀 관리 컴포넌트 다국어 완성** | **TeamTopicManager 다국어 처리 (team.manage.teamTopics, 18개 키), LiveWritingMonitor 다국어 처리 (team.manage.liveMonitor, 27개 키), team/[teamId]/page.tsx 다국어 처리 (기존 키 활용), StudentLoginFlow 일본어 번역 (61개 키), team.create 일본어 번역 (21개 키), team.detail/manage 일본어 번역 (45개 키), securitySelector 일본어 번역 (13개 키)** | **2025-11-18** |
|
| **팀 관리 컴포넌트 다국어 완성** | **TeamTopicManager 다국어 처리 (team.manage.teamTopics, 18개 키), LiveWritingMonitor 다국어 처리 (team.manage.liveMonitor, 27개 키), team/[teamId]/page.tsx 다국어 처리 (기존 키 활용), StudentLoginFlow 일본어 번역 (61개 키), team.create 일본어 번역 (21개 키), team.detail/manage 일본어 번역 (45개 키), securitySelector 일본어 번역 (13개 키)** | **2025-11-18** |
|
||||||
@ -97,6 +98,9 @@
|
|||||||
| **Level 1 중복 체크 로직 (UID 기반)** | **loginAsUser() 함수 수정 (currentUid 파라미터 추가), Level 1 닉네임 중복 체크 (team.members 검색), 4가지 케이스 처리 (비로그인/로그인 × 중복 유무), Custom Token API 생성 (POST /api/team/get-custom-token, 익명 계정만 발급), 비로그인 상태 중복 시 기존 계정으로 자동 로그인, 로그인 상태 중복 시 에러 (UID 일치 체크), 정식 계정 탈취 방지 (providerData 체크), authStore.loginAsUser에서 currentUid 전달, StudentLoginFlow 에러 메시지 처리, 번역 추가 (errors.team namespace, alreadyJoinedTeam/nicknameInUse 등 6개 키, ko/en/ja)** | **2025-11-18** |
|
| **Level 1 중복 체크 로직 (UID 기반)** | **loginAsUser() 함수 수정 (currentUid 파라미터 추가), Level 1 닉네임 중복 체크 (team.members 검색), 4가지 케이스 처리 (비로그인/로그인 × 중복 유무), Custom Token API 생성 (POST /api/team/get-custom-token, 익명 계정만 발급), 비로그인 상태 중복 시 기존 계정으로 자동 로그인, 로그인 상태 중복 시 에러 (UID 일치 체크), 정식 계정 탈취 방지 (providerData 체크), authStore.loginAsUser에서 currentUid 전달, StudentLoginFlow 에러 메시지 처리, 번역 추가 (errors.team namespace, alreadyJoinedTeam/nicknameInUse 등 6개 키, ko/en/ja)** | **2025-11-18** |
|
||||||
| **서비스 레이어 i18n 유틸리티** | **src/utils/i18n.ts 생성 (React 훅 없이 번역 사용), detectLocale() 함수 (URL path 우선 → navigator.language fallback), t() 함수 (nested key 지원, 파라미터 치환), messages/*.json import, firebaseAuth.ts 전체 에러 메시지 다국어 처리 (getErrorMessage, loginAsUser, linkEmailPassword, linkGoogleAccount), convertFirebaseUser 기본 이름 다국어, 번역 추가 (errors.auth namespace 11개 + errors.team namespace 6개, ko/en/ja)** | **2025-11-18** |
|
| **서비스 레이어 i18n 유틸리티** | **src/utils/i18n.ts 생성 (React 훅 없이 번역 사용), detectLocale() 함수 (URL path 우선 → navigator.language fallback), t() 함수 (nested key 지원, 파라미터 치환), messages/*.json import, firebaseAuth.ts 전체 에러 메시지 다국어 처리 (getErrorMessage, loginAsUser, linkEmailPassword, linkGoogleAccount), convertFirebaseUser 기본 이름 다국어, 번역 추가 (errors.auth namespace 11개 + errors.team namespace 6개, ko/en/ja)** | **2025-11-18** |
|
||||||
| **AI Delta 전송 로직 개선** | **diff-match-patch 라이브러리 도입, 정확한 diff 계산 (앞/중간/뒤 수정 모두 감지), 5자 미만 변경 누적 (previousText 유지), 완화된 기준 (80% 미만, 200자 미만), 9개 테스트 케이스 통과 (뒷부분 추가, 중간 수정, 앞부분 추가, 삭제, 대량 변경, 누적 변경), skipped 응답 처리 (클라이언트에서 prev 유지), analyze-text API 수정** | **2025-11-19** |
|
| **AI Delta 전송 로직 개선** | **diff-match-patch 라이브러리 도입, 정확한 diff 계산 (앞/중간/뒤 수정 모두 감지), 5자 미만 변경 누적 (previousText 유지), 완화된 기준 (80% 미만, 200자 미만), 9개 테스트 케이스 통과 (뒷부분 추가, 중간 수정, 앞부분 추가, 삭제, 대량 변경, 누적 변경), skipped 응답 처리 (클라이언트에서 prev 유지), analyze-text API 수정** | **2025-11-19** |
|
||||||
|
| **수정 모드 주제 변경 차단** | **TopicSelector `readonly` prop 추가, 수정 모드에서 Select 드롭다운 완전 숨김, "현재 주제" 라벨만 표시, 주제 생성 Dialog 숨김, 데이터 무결성 보장 (템플릿 덮어쓰기 방지, AI 설정 혼선 방지, 실시간 모니터링 충돌 방지), 다국어 지원 (readonlyNote/currentTopic 키 추가, ko/en/ja)** | **2025-11-21** |
|
||||||
|
| **수정 모드 UX 대폭 개선** | **Sticky 헤더바 추가 (오렌지/앰버 그라데이션 배경, 상단 고정 z-index:100, blur backdrop, Writing ID 표시), 강조된 테두리 (주제 선택 + 글쓰기 영역 2px solid 오렌지), 섀도우 효과 (글쓰기 영역 오렌지 글로우, 라이트/다크 모드 대응), 색상 시스템 정립 (Light: #FFB366/#FF9800/#E65100, Dark: #8B6B47/#C4A572), 기존 단순 배지 제거, 전체 UI 테마 일관성, globals.css에 pulse/shimmer 애니메이션 추가 (후에 제거됨)** | **2025-11-21** |
|
||||||
|
| **글쓰기 페이지 UI 정리** | **"새 글쓰기" 버튼 제거 (불필요한 기능, 실수 방지, handleNewDraft 함수 제거, LuFilePlus import 제거), 상단 버튼 영역 단순화 ("저장된 글조각" 버튼만 유지), 미사용 i18n 키 정리 (newWriting/discardConfirm 제거, ko/en/ja)** | **2025-11-21** |
|
||||||
| **Draft 클라우드 동기화** | **localStorage + Realtime DB 하이브리드 저장, syncStatus 필드 추가 ('local'\|'synced'\|'syncing'), DraftManager 확장 (syncToCloud, loadDraftsFromCloud, mergeDrafts, deleteDraftFromCloud), SavedDraftsDialog 배지 표시 (🟢동기화됨/🟡동기화 중/⚪기기만), write/page.tsx mergeDrafts 호출 (로그인 시), database.rules.json drafts 규칙 추가 (본인만 읽기/쓰기), 기기 간 동기화 (학교 ↔ 집), updatedAt 비교로 최신 버전 선택** | **2025-11-19** |
|
| **Draft 클라우드 동기화** | **localStorage + Realtime DB 하이브리드 저장, syncStatus 필드 추가 ('local'\|'synced'\|'syncing'), DraftManager 확장 (syncToCloud, loadDraftsFromCloud, mergeDrafts, deleteDraftFromCloud), SavedDraftsDialog 배지 표시 (🟢동기화됨/🟡동기화 중/⚪기기만), write/page.tsx mergeDrafts 호출 (로그인 시), database.rules.json drafts 규칙 추가 (본인만 읽기/쓰기), 기기 간 동기화 (학교 ↔ 집), updatedAt 비교로 최신 버전 선택** | **2025-11-19** |
|
||||||
| **팀 코드 예약 반환 로직** | **generate-code API 수정 (previousCode 파라미터 추가), 새 코드 받기 시 이전 예약 자동 해제, team/create page 중복 호출 방지 (isGeneratingCode 체크), 팀 생성 실패 시에도 예약 해제 (catch 블록), GenerateTeamCodeRequest 타입 확장, TeamManager.generateUniqueTeamCode previousCode 파라미터** | **2025-11-19** |
|
| **팀 코드 예약 반환 로직** | **generate-code API 수정 (previousCode 파라미터 추가), 새 코드 받기 시 이전 예약 자동 해제, team/create page 중복 호출 방지 (isGeneratingCode 체크), 팀 생성 실패 시에도 예약 해제 (catch 블록), GenerateTeamCodeRequest 타입 확장, TeamManager.generateUniqueTeamCode previousCode 파라미터** | **2025-11-19** |
|
||||||
| **Firebase Cloud Functions Phase 1** | **functions/ 프로젝트 초기화 (Node.js 22, v2 API), 파일 분리 구조 (index.ts export만, 로직 별도 파일), cleanupExpiredReservations (매 시간, 팀 코드 예약 정리), cleanupExpiredDrafts (매일 새벽 3시, 180일 이상 drafts 정리), onTeamDeleted (Firestore Trigger, cascade 삭제), onWritingCreated (Firestore Trigger, 추후 자동 분석), 한글 로그, asia-northeast1 리전, firebase.json predeploy 수정 (lint 제거), 4개 함수 배포 완료** | **2025-11-19** |
|
| **Firebase Cloud Functions Phase 1** | **functions/ 프로젝트 초기화 (Node.js 22, v2 API), 파일 분리 구조 (index.ts export만, 로직 별도 파일), cleanupExpiredReservations (매 시간, 팀 코드 예약 정리), cleanupExpiredDrafts (매일 새벽 3시, 180일 이상 drafts 정리), onTeamDeleted (Firestore Trigger, cascade 삭제), onWritingCreated (Firestore Trigger, 추후 자동 분석), 한글 로그, asia-northeast1 리전, firebase.json predeploy 수정 (lint 제거), 4개 함수 배포 완료** | **2025-11-19** |
|
||||||
|
|||||||
205
TECH_STACK.md
205
TECH_STACK.md
@ -1,6 +1,6 @@
|
|||||||
# 라온누리 - 기술 스택 및 개발 환경
|
# 라온누리 - 기술 스택 및 개발 환경
|
||||||
|
|
||||||
> 최종 업데이트: 2025-11-17 (AI 설정 고급 UI 완성)
|
> 최종 업데이트: 2025-11-20 (AI 이미지 생성 스타일 개선)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ export const fbRealtimeDb = getDatabase(fbApp); // 🆕
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 사이트 URL (프로덕션)
|
# 사이트 URL (프로덕션)
|
||||||
NEXT_PUBLIC_URL=https://raonnuri.com
|
NEXT_PUBLIC_URL=https://raonnuri.life
|
||||||
|
|
||||||
# API Base URL (선택적, 기본값: /api)
|
# API Base URL (선택적, 기본값: /api)
|
||||||
NEXT_PUBLIC_API_URL=/api
|
NEXT_PUBLIC_API_URL=/api
|
||||||
@ -1603,7 +1603,206 @@ const improvementRate = calculateImprovementRate(spellingErrorsHistory);
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 10. AI 글쓰기 도우미 시스템
|
### 10. AI 이미지 생성 시스템 (Vertex AI Imagen 4.0)
|
||||||
|
|
||||||
|
#### 핵심 개념
|
||||||
|
|
||||||
|
**목적**: 학생이 작성한 글의 장면을 자동으로 추출하여 일관된 스타일의 삽화 이미지 생성
|
||||||
|
|
||||||
|
**기술 스택**:
|
||||||
|
- **Vertex AI Imagen 4.0 Fast**: Google 최신 이미지 생성 모델
|
||||||
|
- **Gemini 2.5 Flash**: 장면 추출 및 프롬프트 최적화
|
||||||
|
- **Multi-region Failover**: us-east5 → us-south1 → us-central1
|
||||||
|
|
||||||
|
#### 일관된 스타일 가이드 (2025-11-20 개선)
|
||||||
|
|
||||||
|
**화풍**: 따뜻한 디지털 일러스트, 애니메이션/만화 스타일
|
||||||
|
**색감**: 부드럽고 따뜻한 톤, 자연스러운 채도
|
||||||
|
**분위기**: 친근하고 밝은, 초등학생 눈높이에 맞는
|
||||||
|
**피해야 할 요소**:
|
||||||
|
- ❌ 지나치게 귀여운 데포르메
|
||||||
|
- ❌ 과도한 사실주의 (semi-realistic, photorealistic)
|
||||||
|
- ❌ 어두운 분위기, 미국식 스타일
|
||||||
|
|
||||||
|
**Negative Prompt** (강화):
|
||||||
|
```
|
||||||
|
text, words, letters, watermark, signature,
|
||||||
|
overly cute, chibi style,
|
||||||
|
excessive realism, photorealistic, semi-realistic,
|
||||||
|
dark atmosphere, gloomy, oversaturated colors,
|
||||||
|
low quality, blurry, distorted, poorly drawn
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 아키텍처 플로우
|
||||||
|
|
||||||
|
```
|
||||||
|
1️⃣ 글 작성 완료
|
||||||
|
↓
|
||||||
|
저장된 글 상세 페이지
|
||||||
|
├─> "이미지 생성" 버튼 클릭
|
||||||
|
└─> GenerateImageDialog 열기
|
||||||
|
|
||||||
|
2️⃣ 장면 추출 (Step 1: Extracting)
|
||||||
|
↓
|
||||||
|
POST /api/extract-scenes
|
||||||
|
├─> body: { title, content, locale }
|
||||||
|
├─> sceneExtractionService.extractScenes()
|
||||||
|
│ ├─> Gemini 2.5 Flash로 장면 분석
|
||||||
|
│ ├─> 2-5개 주요 장면 추출
|
||||||
|
│ └─> Response Schema (Scene[])
|
||||||
|
│
|
||||||
|
└─> { scenes, totalScenes }
|
||||||
|
|
||||||
|
3️⃣ 장면 선택 (Step 2: Selecting)
|
||||||
|
↓
|
||||||
|
SceneSelector 컴포넌트
|
||||||
|
├─> RadioCard.Root로 장면 카드 표시
|
||||||
|
├─> 각 장면: 제목 + 내용 미리보기
|
||||||
|
└─> 사용자 선택 → selectedSceneId 저장
|
||||||
|
|
||||||
|
4️⃣ 이미지 생성 (Step 3: Generating)
|
||||||
|
↓
|
||||||
|
POST /api/generate-image
|
||||||
|
├─> body: { writingId, title (scene), content (scene), locale }
|
||||||
|
├─> Authorization: Bearer {idToken}
|
||||||
|
│
|
||||||
|
├─> 🔒 인증 & 권한 확인
|
||||||
|
│ ├─> verifyIdToken()
|
||||||
|
│ └─> writing.userId === userId 체크
|
||||||
|
│
|
||||||
|
├─> 🎨 프롬프트 최적화
|
||||||
|
│ └─> optimizePromptForImage(title, content, locale)
|
||||||
|
│ ├─> Gemini Flash로 키워드 추출 (6-12개)
|
||||||
|
│ │ - 주요 피사체, 행동, 배경, 시각적 디테일, 분위기
|
||||||
|
│ │ - "Korean elementary student" 국적 명시
|
||||||
|
│ │ - 일관된 스타일 키워드 자동 추가
|
||||||
|
│ │
|
||||||
|
│ └─> keywords.join(", ")
|
||||||
|
│ 예: "Korean elementary student with bright smile,
|
||||||
|
│ catching red dodgeball,
|
||||||
|
│ sunny school playground in Korea,
|
||||||
|
│ warm natural lighting,
|
||||||
|
│ friendly digital illustration,
|
||||||
|
│ anime-inspired art style"
|
||||||
|
│
|
||||||
|
├─> 🖼️ Imagen API 호출
|
||||||
|
│ └─> generateImage(optimizedPrompt, config)
|
||||||
|
│ ├─> model: imagen-4.0-fast-generate-001
|
||||||
|
│ ├─> aspectRatio: 16:9
|
||||||
|
│ ├─> numberOfImages: 1
|
||||||
|
│ └─> negativePrompt (강화됨)
|
||||||
|
│
|
||||||
|
├─> 💾 Firebase Storage 업로드
|
||||||
|
│ └─> uploadGeneratedImage(writingId, dataUrl, 'png')
|
||||||
|
│ ├─> 경로: generated-images/{writingId}/{timestamp}.png
|
||||||
|
│ └─> 공개 URL 반환
|
||||||
|
│
|
||||||
|
└─> 📝 Firestore 업데이트
|
||||||
|
└─> writings/{writingId}.generatedImage = {
|
||||||
|
url, prompt, generatedAt, modelName
|
||||||
|
}
|
||||||
|
|
||||||
|
5️⃣ 결과 표시 (Step 4: Done)
|
||||||
|
↓
|
||||||
|
<HintDisplay>
|
||||||
|
├─> 생성된 이미지 미리보기
|
||||||
|
├─> 사용된 프롬프트 표시
|
||||||
|
└─> "장면 변경" / "닫기" 버튼
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 프롬프트 최적화 시스템
|
||||||
|
|
||||||
|
**2단계 프로세스**:
|
||||||
|
|
||||||
|
1. **AI 키워드 추출** (Gemini Flash):
|
||||||
|
```typescript
|
||||||
|
// promptOptimization.ts
|
||||||
|
input: {
|
||||||
|
sceneTitle: "막판 역전",
|
||||||
|
sceneContent: "지훈이를 아웃시켰다...",
|
||||||
|
locale: "ko"
|
||||||
|
}
|
||||||
|
|
||||||
|
output: {
|
||||||
|
keywords: [
|
||||||
|
"Korean elementary student with confident expression",
|
||||||
|
"catching red dodgeball mid-air",
|
||||||
|
"elementary school playground during golden hour",
|
||||||
|
"classmates running excitedly",
|
||||||
|
"dynamic joyful pose",
|
||||||
|
"warm natural lighting",
|
||||||
|
"friendly digital illustration",
|
||||||
|
"anime-inspired art style",
|
||||||
|
"warm gentle colors",
|
||||||
|
"clean composition"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **폴백 프롬프트** (AI 실패 시):
|
||||||
|
```typescript
|
||||||
|
// imagenService.ts
|
||||||
|
const prompt = [
|
||||||
|
"friendly digital illustration",
|
||||||
|
"anime-inspired art style",
|
||||||
|
"warm gentle colors",
|
||||||
|
title,
|
||||||
|
summary,
|
||||||
|
"soft warm lighting",
|
||||||
|
"cheerful atmosphere"
|
||||||
|
].join(", ");
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 주요 특징
|
||||||
|
|
||||||
|
1. **일관된 스타일** 🎨:
|
||||||
|
- 모든 이미지에 동일한 스타일 가이드 적용
|
||||||
|
- AI 프롬프트에 스타일 키워드 자동 포함
|
||||||
|
- Negative prompt로 원하지 않는 스타일 차단
|
||||||
|
|
||||||
|
2. **한국 문화권 고려** 🇰🇷:
|
||||||
|
- "Korean elementary student" 명시
|
||||||
|
- "school playground in Korea" 등 한국 배경
|
||||||
|
- 아시아권 얼굴 특징 반영
|
||||||
|
|
||||||
|
3. **장면 자동 추출** ✂️:
|
||||||
|
- Gemini가 글에서 시각화하기 좋은 장면 2-5개 추출
|
||||||
|
- 사용자가 원하는 장면 선택
|
||||||
|
- 다시 생성 가능 (장면 변경 버튼)
|
||||||
|
|
||||||
|
4. **비용 최적화** 💰:
|
||||||
|
- 프롬프트 최적화로 토큰 절감
|
||||||
|
- Multi-region failover로 Rate Limit 회피
|
||||||
|
- 이미지당 평균 $0.04
|
||||||
|
|
||||||
|
5. **다국어 지원** 🌏:
|
||||||
|
- 한국어/영어/일본어 프롬프트 생성
|
||||||
|
- locale에 따라 다른 스타일 가이드
|
||||||
|
|
||||||
|
#### 참고 파일
|
||||||
|
|
||||||
|
**프롬프트**:
|
||||||
|
- `src/prompts/promptOptimization.ts` - AI 키워드 추출 프롬프트 (3개 언어)
|
||||||
|
|
||||||
|
**서비스**:
|
||||||
|
- `src/services/vertexAI.ts` - Imagen API 래퍼 (multi-region failover)
|
||||||
|
- `src/services/imagenService.ts` - 이미지 생성 비즈니스 로직
|
||||||
|
- `src/services/sceneExtractionService.ts` - 장면 추출 로직
|
||||||
|
|
||||||
|
**API**:
|
||||||
|
- `src/app/api/extract-scenes/route.ts` - 장면 추출 API
|
||||||
|
- `src/app/api/generate-image/route.ts` - 이미지 생성 API
|
||||||
|
|
||||||
|
**컴포넌트**:
|
||||||
|
- `src/components/writing/GenerateImageDialog.tsx` - 4단계 플로우 다이얼로그
|
||||||
|
- `src/components/writing/SceneSelector.tsx` - 장면 선택 UI
|
||||||
|
|
||||||
|
**유틸**:
|
||||||
|
- `src/utils/imageStorage.ts` - Firebase Storage 업로드
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 11. AI 글쓰기 도우미 시스템
|
||||||
|
|
||||||
#### 개요
|
#### 개요
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user