docs: Sync documentation from private repository

This commit is contained in:
Documentation Bot 2025-11-26 06:37:39 +00:00
parent e8d5da3866
commit e8d98f43ff
4 changed files with 109 additions and 19 deletions

View File

@ -2,7 +2,19 @@
라온누리 서버 API 명세서
## ⚠️ 최신 변경사항 (2025-11-12)
## ⚠️ 최신 변경사항 (2025-11-26)
### 🔗 익명 계정 연결 기능
- **POST /api/auth/merge-account**: 익명 계정 데이터를 정식 계정으로 마이그레이션
- Firestore 데이터 이전 (writings, topics, comments, userReactions, teams)
- Realtime DB 데이터 이전 (drafts, monitoring, previewRequests)
- 원자성 보장 (Firestore Batch, Realtime DB Transaction)
- 병합 완료 후 통계 반환
- **서비스 레이어**: `src/services/firebaseAuth.ts` (mergeAndLoginWithEmail, mergeAndLoginWithGoogle)
- **상태 관리**: `src/store/authStore.ts` (mergeWithEmail, mergeWithGoogle 액션)
- **UI 통합**: LoginForm/SignupForm mode prop, LoginDialog link 모드
## ⚠️ 변경사항 (2025-11-12)
### ✅ Writing API 구현 완료
- **POST /api/writing**: 글 생성 (서버에서 wordCount/charCount 자동 계산)
@ -849,6 +861,65 @@ await teamManager.removeMember(teamId, currentUser.uid);
---
## Auth API
### POST `/auth/merge-account` - 익명 계정 데이터 병합
실제 URL: `POST /api/auth/merge-account`
**인증**: 필수 (정식 계정으로 로그인된 상태)
**Request**:
```typescript
{
anonymousUid: string; // 병합할 익명 계정의 UID
}
```
**Response**:
```typescript
{
success: true,
data: {
mergedCounts: {
writings: number; // 이전된 글 개수
topics: number; // 이전된 주제 개수
comments: number; // 이전된 댓글 개수
userReactions: number; // 이전된 반응 개수
teamMemberships: number; // 이전된 팀 멤버십 개수
drafts: number; // 이전된 초안 개수
monitoring: number; // 이전된 모니터링 세션 개수
previewRequests: number; // 이전된 미리보기 요청 개수
}
}
}
```
**동작**:
1. **Firestore 데이터 마이그레이션** (Batch 사용):
- `writings` 컬렉션: userId 업데이트
- `topics` 컬렉션: ownerId 업데이트 (개인 주제만)
- `comments` 컬렉션: authorId 업데이트
- `userReactions` 컬렉션: userId 업데이트
- `teams` 컬렉션: members 키 변경 (anonymousUid → targetUid)
2. **Realtime DB 데이터 마이그레이션** (Transaction 사용):
- `drafts/{anonymousUid}``drafts/{targetUid}` 이동
- `monitoring/{topicId}/{anonymousUid}``monitoring/{topicId}/{targetUid}` 이동
- `previewRequests/{topicId}/{anonymousUid}``previewRequests/{topicId}/{targetUid}` 이동
**제약사항**:
- 익명 계정과 정식 계정은 다른 UID여야 함
- 익명 계정 데이터는 병합 후 자동 삭제되지 않음 (수동 정리 필요)
**에러 코드**:
- `400`: anonymousUid 누락
- `401`: 인증되지 않은 요청
- `500`: 마이그레이션 실패
**캐싱**: 없음 (일회성 작업)
---
## User API
**중요**: User vs FirestoreUser 구분

View File

@ -275,10 +275,10 @@
| 컴포넌트 | 파일명 | 설명 | 상태 |
|---------|--------|------|------|
| **AuthInitializer** | `AuthInitializer.tsx` | Firebase 인증 상태 초기화 | ✅ 완료 |
| **LoginDialog** | `LoginDialog.tsx` | 로그인/회원가입 다이얼로그 (일반/팀 코드 모드 전환) | ✅ 완료 |
| **LoginDialog** | `LoginDialog.tsx` | 로그인/회원가입 다이얼로그 (auth/team/link 모드 지원) | ✅ 완료 |
| **StudentLoginFlow** | `StudentLoginFlow.tsx` | 팀 코드 학생 로그인 플로우 (3단계) | ✅ 완료 |
| **LoginForm** | `LoginForm.tsx` | 로그인 폼 컴포넌트 | ✅ 완료 |
| **SignupForm** | `SignupForm.tsx` | 회원가입 폼 컴포넌트 | ✅ 완료 |
| **LoginForm** | `LoginForm.tsx` | 로그인 폼 컴포넌트 (mode: auth\|link) | ✅ 완료 |
| **SignupForm** | `SignupForm.tsx` | 회원가입 폼 컴포넌트 (mode: auth\|link) | ✅ 완료 |
| **SocialLoginButton** | `SocialLoginButton.tsx` | 소셜 로그인 버튼 | ✅ 완료 |
| **UserProfileButton** | `UserProfileButton.tsx` | 사용자 프로필/메뉴 버튼 | ✅ 완료 |
@ -290,6 +290,12 @@
- ✅ HIBP API 연동 (유출된 비밀번호 차단)
- ✅ 폼 검증 및 에러 애니메이션
- ✅ Google OAuth 로그인
- ✅ 익명 계정 연결 기능
- ✅ 기존 폼 재사용 (LoginForm/SignupForm mode prop)
- ✅ 신규 계정 생성 (linkWithCredential)
- ✅ 기존 계정 병합 (API 데이터 마이그레이션)
- ✅ 3개 소셜 로그인 버튼 표시 (Naver/Kakao/Google)
- ✅ 용어 통일 ("병합" → "연결", "익명" → "임시")
- ✅ 팀 코드 기반 사용자 로그인 (Anonymous Auth - 단순화됨)
- ✅ 한글 팀 코드 ("춤추는 파란 사자" 형식)
- ✅ 사용자 이름 입력 (2단계)
@ -756,6 +762,7 @@ firebase functions:log --only cleanupExpiredReservations
| **AI 이미지 생성** | `/api/generate-image` | POST | 🆕 **장면 기반 이미지 생성** (🆕 **AI 프롬프트 최적화**, Imagen 3.0, Firebase Storage 저장, Writing 업데이트) | ✅ 완료 |
| **주제 CRUD** | `/api/topic` | GET, POST, PUT, DELETE | 주제 생성/조회/수정/삭제 (9개 엔드포인트) | ✅ 완료 |
| **주제별 작성자** | `/api/topic/[topicId]/writers` | GET | 🆕 **주제로 글 쓴 학생 목록** (글 개수, Firebase Auth 결합, 글 개수 내림차순) | ✅ 완료 |
| **계정 병합** | `/api/auth/merge-account` | POST | 🆕 **익명 계정 데이터 병합** (Firestore + Realtime DB 마이그레이션, Batch/Transaction, 통계 반환) | ✅ 완료 |
| **사용자 관리** | `/api/user` | GET, POST, PUT | 사용자 조회/생성/업데이트 | ✅ 완료 |
**서버 레이어** (`src/lib/server/`):
@ -783,8 +790,10 @@ firebase functions:log --only cleanupExpiredReservations
- ✅ **isAuthenticated** - 로그인 여부 (익명 포함)
- ✅ **user.isAnonymous** - 익명/정식 계정 구분
- ✅ **loginAsUser()** - 팀 코드 로그인 (PIN 제거)
- ✅ **linkWithEmail()** - 이메일 계정 연결
- ✅ **linkWithGoogle()** - Google 계정 연결
- ✅ **linkWithEmail()** - 이메일 계정 연결 (신규 계정 생성)
- ✅ **linkWithGoogle()** - Google 계정 연결 (신규 계정 생성)
- ✅ **mergeWithEmail()** - 기존 이메일 계정과 병합 (데이터 마이그레이션)
- ✅ **mergeWithGoogle()** - 기존 Google 계정과 병합 (데이터 마이그레이션)
- ❌ ~~currentStudent~~, ~~ownedStudents~~, ~~switchStudent()~~ 제거 (복잡도 감소)
---

View File

@ -115,6 +115,7 @@
| **글 상세 페이지 댓글 기능 연결** | **CommentList 컴포넌트를 writing/[writingId]/page.tsx에 연결, 댓글 보기/작성/답글/삭제 기능 활성화** | **2025-11-26** |
| **미사용 코드 정리** | **koreanWordList.ts 삭제 (AI 분석으로 대체), InteractiveImage.tsx 삭제 (InteractiveImageViewer로 대체), AllowListManager.tsx 삭제 (미통합), 관련 문서 업데이트** | **2025-11-26** |
| **팀 페이지 리팩토링** | **useTeamData 훅 생성 (팀 + 멤버 로딩, 권한 체크, refreshMembers), 팀 페이지 중복 코드 제거 (~200줄 절감), 각 하위 컴포넌트 자체 로딩 스켈레톤 활용** | **2025-11-26** |
| **익명 계정 연결 기능** | **POST /api/auth/merge-account API (Firestore + Realtime DB 데이터 마이그레이션), mergeAndLoginWithEmail/mergeAndLoginWithGoogle 함수 (firebaseAuth.ts), mergeWithEmail/mergeWithGoogle 액션 (authStore.ts), LoginForm/SignupForm mode prop 추가 ('auth'\|'link'), LoginDialog link 모드 지원 (3개 소셜 버튼 표시), LinkAccountFlow 삭제 (기존 폼 재사용), 용어 변경 ("병합" → "연결", "익명" → "임시"), 다국어 지원 (linkAccountDescription, naverMerge/kakaoMerge/googleMerge, mergeButton/linkButton, ko/en/ja 15개 키)** | **2025-11-26** |
### 🚧 진행 중

View File

@ -422,10 +422,11 @@ const nickname = teamManager.getMemberNickname(team, uid, user?.name);
├─> isLoading
└─> 액션:
├─> login/signup/loginWithGoogle (기존)
├─> **loginAsStudent(classCode, name, pin?)** - 팀 코드 로그인
├─> **switchStudent(student)** - 학생 전환
├─> **linkCurrentStudentWithEmail()** - 계정 연결
└─> **linkCurrentStudentWithGoogle()** - Google 계정 연결
├─> **loginAsUser(teamCode, name)** - 팀 코드 로그인 (익명 계정 생성)
├─> **linkWithEmail(email, password)** - 신규 이메일 계정 생성 (linkWithCredential)
├─> **linkWithGoogle()** - 신규 Google 계정 생성 (linkWithCredential)
├─> **mergeWithEmail(email, password)** - 기존 이메일 계정과 병합 (API 데이터 마이그레이션)
└─> **mergeWithGoogle()** - 기존 Google 계정과 병합 (API 데이터 마이그레이션)
3. 인증 기반 라우팅
├─> 랜딩 페이지 (/)
@ -786,15 +787,23 @@ const [selectedPartIndex, setSelectedPartIndex] = useState<number | null>(null);
├─> authStore.currentStudent 설정
└─> /team/[teamId] 멤버 페이지로 이동
2. 정식 계정 연결 (선택적, 학부모/고학년)
├─> 설정 → "내 계정 만들기"
├─> 이메일 회원가입 또는 Google 로그인
├─> linkWithCredential() 호출
│ └─ Anonymous(anon123) → Email(user456) 전환
├─> Firestore 연결:
│ ├─ students/studentDoc.linkedUserId = user456
│ └─ users/user456.ownedStudentIds = [studentDoc]
└─> 이후 user456으로 로그인 가능 (currentStudent 자동 설정)
2. 정식 계정 연결 (선택적)
├─> UserProfileButton → "계정 연결하기"
├─> LoginDialog (link 모드)
├─> 2가지 시나리오:
│ ├─ **신규 계정 생성** (linkWithCredential):
│ │ ├─ 이메일 회원가입 또는 Google 로그인
│ │ ├─ linkWithCredential() 호출
│ │ └─ Anonymous(anon123) → Email(user456) 전환 (UID 유지)
│ │
│ └─ **기존 계정 병합** (API 데이터 마이그레이션):
│ ├─ 이메일 로그인 또는 Google 로그인
│ ├─ POST /api/auth/merge-account 호출
│ ├─ Firestore 데이터 이전 (writings, topics, comments, teams)
│ ├─ Realtime DB 데이터 이전 (drafts, monitoring)
│ └─ 익명 계정(anon123) → 정식 계정(user456)으로 데이터 이전
└─> 이후 user456으로 로그인 가능 (모든 데이터 통합)
3. 정식 계정 로그인 (학생 자동 선택)
├─> user456으로 로그인