# InsuWiki 문서 삭제 흐름 (Soft Delete 시스템)

> 최종 수정: 2026-02-24  
> 관련 파일: `DocumentClient.tsx`, `api/admin/purge/route.ts`, `types/firestore.ts`

---

## 개요

InsuWiki는 **소프트 삭제(Soft Delete)** 방식을 사용합니다.  
문서를 삭제해도 Firestore에서 실제 데이터는 지워지지 않습니다.  
`isDeleted: true` 필드를 설정해서 목록에서 숨기는 방식입니다.

---

## Firestore 삭제 관련 필드

```
documents/{docId}
  ├── isDeleted: boolean      // true이면 목록에서 숨겨짐
  ├── deletedAt: Timestamp?   // 삭제된 시각
  └── deletedBy: string?      // 삭제한 사람의 uid
```

레거시 문서는 `isDeleted` 필드 자체가 없을 수 있습니다.  
→ 이 경우 앱은 **존재하지 않으면 false로 간주**합니다.

---

## 삭제 단계 (3단계)

### 1단계 — 소프트 삭제 (휴지통 이동)

**트리거**: 문서 편집 화면의 🗑️ 삭제 버튼

```
문서 삭제 버튼 클릭
  → confirm("문서를 휴지통으로 이동하시겠습니까? (복구 가능)")
  → Firestore update:
      isDeleted: true
      deletedAt: serverTimestamp()
      deletedBy: user.uid
  → 메인 목록으로 이동
```

**권한 조건**:
| 문서 유형 | 삭제 가능 |
|----------|---------|
| 공개(public) 문서 | 관리자만 가능 |
| 비공개(private) / Daily 문서 | 작성자 본인 |

**결과**: 데이터는 Firestore에 그대로 존재함. 목록에서만 안 보임.

---

### 2단계 — 복원 (Restore)

**트리거**: 삭제된 문서 뷰어 화면의 "복원" 버튼

> 삭제된 문서 URL을 직접 접근하면 문서 내용 위에 삭제 상태 배너가 표시됩니다.

```
복원 버튼 클릭
  → confirm("문서를 복원하시겠습니까?")
  → Firestore update:
      isDeleted: false
      deletedAt: null
      deletedBy: null
  → 문서 정상 복원
```

**권한 조건**: 작성자 본인 또는 관리자

---

### 3단계 — 완전 삭제 (Purge)

**트리거**: 삭제된 문서 뷰어 화면의 "영구 삭제" 버튼 (**관리자 전용**)

```
영구 삭제 버튼 클릭
  → confirm("이 작업은 변경 이력을 포함한 모든 데이터를 삭제하며 되돌릴 수 없습니다.")
  → API 호출: DELETE /api/admin/purge?docId={docId}
      Authorization: Bearer {idToken}
```

**서버(purge API) 처리 흐름**:
1. Firebase ID Token 검증
2. `isDeleted === true` 여부 확인 (반드시 소프트 삭제 상태여야 함)
3. 권한 확인: Admin 이메일 or 작성자 or Daily 문서 UID 포함 여부
4. `adminDb.recursiveDelete(docRef)` — 문서 + 하위 컬렉션(`revisions` 등) 전체 삭제

**결과**: Firestore에서 완전히 제거됨. 복구 불가능.

---

## 화면별 버튼 표시 조건

```
[문서 뷰어 화면]
  ├── isDeleted === false
  │   ├── 편집 버튼: 로그인 사용자
  │   ├── 삭제 버튼: 작성자(비공개) 또는 관리자(공개)
  │   └── 공개/비공개 토글: 작성자 본인
  │
  └── isDeleted === true  (삭제된 문서)
      ├── 복원 버튼: 작성자 또는 관리자
      └── 영구 삭제 버튼: 관리자만
```

---

## 목록/검색에서 필터링되는 위치

| 위치 | 처리 방식 |
|-----|---------|
| `page.tsx` (메인 목록) | `if (data.isDeleted) return;` (클라이언트 필터) |
| `useWikiMap.ts` (위키 맵) | `if (data.isDeleted === true) return;` (클라이언트 필터) |
| `SearchModal.tsx` (검색) | `!doc.isDeleted` 조건으로 필터 |
| `BacklinksPanel.tsx` (백링크) | `where('isDeleted', '==', false)` (Firestore 쿼리) |
| `share-target` API | `where('isDeleted', '==', false)` (Firestore 쿼리) |

> **주의**: `useWikiMap`과 `page.tsx`는 Firestore 쿼리에서 `isDeleted == false` 조건을 넣지 않고,  
> 클라이언트 단에서 필터링합니다. 이는 `isDeleted` 필드가 없는 레거시 문서가  
> Firestore 쿼리에서 누락되는 문제를 방지하기 위한 의도적인 설계입니다.

---

## 개정 이력(Revisions) 보존

소프트 삭제 상태에서 `revisions` 서브컬렉션(`documents/{docId}/revisions/*`)은  
**완전 삭제 전까지 그대로 보존**됩니다.  
Purge 실행 시 `recursiveDelete`로 함께 삭제됩니다.

---

## 요약 플로우

```
삭제 버튼
    ↓
isDeleted: true  ←─────────────────────────────┐
    ↓                                          │
목록에서 숨겨짐                                 │
    ↓                                   복원 버튼 클릭
URL 직접 접근 → 삭제 상태 배너 표시             │
    ↓                                          │
[복원] ──────────────────────────────────────→ ┘
    ↓
[영구 삭제(관리자)]
    ↓
/api/admin/purge → recursiveDelete
    ↓
Firestore에서 완전 제거 (복구 불가)
```
