# FS — 기능 명세서 (Functional Specification)

> **FS(Functional Specification)**: PRD에서 정한 것을 "어떻게" 만들지 정의하는 설계 문서. 화면, 데이터, 기능 로직을 구체화.

---

## 1. 기술 스택

| 구분 | 선택 | 설명 |
|---|---|---|
| 개발 도구 | Google AI Studio | Gemini로 코드 생성·프로토타입 |
| 프론트엔드 | React (또는 순수 JS) | 화면 구성 |
| 인증 | Firebase Authentication | 이메일+비밀번호 |
| DB | Firebase Firestore | 회원·보고서·이미지 저장 |
| 텍스트 편집기 | CKEditor5 | 서식 있는 텍스트 → HTML 출력 |
| 이미지 리사이즈 | browser-image-compression | 브라우저에서 축소 |
| PPTX 생성 | PptxGenJS | 브라우저에서 PPTX 생성 |
| 드래그 정렬 | SortableJS (또는 dnd-kit) | 이미지 순서 변경 |

> **용어**
> - **React**: 화면을 부품(컴포넌트)으로 조립하는 웹 도구
> - **HTML**: 웹 서식을 표현하는 코드
> - **Base64**: 이미지 파일을 글자 문자열로 바꾼 형태 (Firestore에 텍스트로 저장하기 위함)

---

## 2. 데이터 구조 (Firestore)

> **컬렉션**: 문서를 담는 폴더. **문서**: 실제 데이터 한 건.

### 2.1 `users` 컬렉션
```
users/{uid}
  ├─ email: string
  ├─ name: string
  ├─ department: string        // 부서/소속
  ├─ role: "member" | "admin"  // admin은 지정 이메일에만
  └─ createdAt: timestamp
```

### 2.2 `reports` 컬렉션
```
reports/{reportId}
  ├─ ownerUid: string          // 작성자 uid (삭제되면 null → "작성자 미상")
  ├─ ownerName: string         // 작성 시점 이름 (스냅샷)
  ├─ ownerDept: string
  ├─ textTitle: string         // {{텍스트 제목}}
  ├─ textSubtitle: string      // {{텍스트 부제목}}
  ├─ period: string            // {{기간}} / {{그림_기간}}
  ├─ writeDate: timestamp      // {{작성날짜}}
  ├─ imgReportTitle: string    // {{그림보고서_제목}}
  ├─ textHtml: string          // CKEditor5 HTML (텍스트 보고서 영역)
  ├─ imageOrder: string[]      // 이미지 문서 id 순서 배열
  ├─ status: "draft" | "saved" // 임시저장 / 저장
  ├─ createdAt: timestamp
  └─ updatedAt: timestamp
```

### 2.3 `reports/{reportId}/images` 하위 컬렉션
> 이미지를 별도 문서로 분산 저장 (Firestore 1MB 문서 제한 회피)
```
reports/{reportId}/images/{imageId}
  ├─ data: string     // Base64 이미지 (800KB 이하)
  ├─ caption: string  // 간단설명 (글자 수 제한 없음)
  └─ order: number    // 정렬 순서
```

---

## 3. 화면 명세

### 3.1 로그인 / 회원가입 화면
| 요소 | 동작 |
|---|---|
| 이메일 입력 | 형식 검증 |
| 비밀번호 입력 | 6자 이상 |
| 로그인 버튼 | Firebase Auth 인증 → 역할 판별 후 분기 |
| 회원가입 링크 | 이름·부서 추가 입력 → 자동 승인 → 즉시 로그인 |
| 관리자 판별 | 로그인 이메일 == 지정 관리자 이메일 → 관리자 화면 |

### 3.2 작업자 — 보고서 목록 화면
| 요소 | 동작 |
|---|---|
| 내 보고서 목록 | 본인 것만 표시 |
| 날짜 검색·필터 | 작성일 범위로 필터 (E-1) |
| 새 보고서 버튼 | 작성 화면 이동 |
| 각 항목 | 수정 / 삭제 / 미리보기·다운로드 |

### 3.3 작업자 — 보고서 작성 화면
| 영역 | 요소 | 동작 |
|---|---|---|
| 기본정보 | 제목, 부제목, 기간, 그림보고서 제목 | 텍스트 입력 |
| 텍스트 보고서 | CKEditor5 | 서식 편집 → HTML 저장 |
| 이미지 보고서 | 파일 첨부(1~6장) | 업로드 시 자동 리사이즈 |
| 이미지 설명 | 각 이미지별 캡션 | 텍스트 입력 |
| 순서 변경 | 드래그 | order 갱신 (R-6) |
| 저장 | 임시저장 / 저장 | status 반영 |
| 미리보기 | 버튼 | 결과 모양 화면 렌더 |
| 다운로드 | 버튼 | PPTX 생성·저장 |

### 3.4 관리자 화면
| 탭 | 기능 |
|---|---|
| 회원 관리 | 목록 조회 / 삭제 (M-1, M-2) |
| 보고서 관리 | 전체 목록 / 날짜 필터 / 삭제 (M-3) |
| 개별 출력 | 보고서 1건 → PPTX (M-4) |
| 취합 출력 | 다중 선택 + 드래그 순서 → 1개 PPTX (간지 포함, M-5·M-6) |

---

## 4. PPTX 생성 로직 (PptxGenJS)

### 4.1 슬라이드 크기
- 16:9 기준 (템플릿 비율)

### 4.2 텍스트 페이지 렌더
```
1) 첫 페이지:
   - 좌상단 주황 사각형(#DD6909) + 제목(검정 #221E21)
   - 우상단 국순당 로고 이미지(PNG)
   - 부제목 · 기간 · 작성날짜
   - 본문: textHtml → PPTX 텍스트 변환 (표·색상 반영)
2) 본문 높이가 슬라이드를 초과하면:
   - 다음 슬라이드 자동 추가
   - 이어지는 슬라이드는 머리말(제목·로고·띠) 없이 본문만 (P-3)
```

> **HTML → PPTX 변환 주의**: CKEditor5 HTML을 파싱하여 문단·굵게·기울임·목록·표·글자색을 PptxGenJS 요소로 매핑. 복잡한 중첩 서식은 근사 처리(깨질 수 있음, PRD 리스크 참조).

### 4.3 이미지 페이지 렌더
```
1) 제목 + 로고
2) 파란 띠(#002060) 안에 "{{그림_기간}} 활동"
3) 이미지 개수(imageOrder.length)에 따라 레이아웃 선택
```

### 4.4 장수별 레이아웃 좌표 (슬라이드 폭 10 × 높이 5.63 inch 기준, 본문 영역 예시)

| 장수 | 배치 (열 × 행) | 이미지 크기(대략) |
|---|---|---|
| 1 | 1×1 중앙 | 6.0 × 3.4 |
| 2 | 2×1 | 4.4 × 3.0 |
| 3 | 상2 하1 | 4.0 × 1.9 |
| 4 | 2×2 | 4.4 × 1.7 |
| 5 | 상3 하2 | 2.9 × 1.7 |
| 6 | 3×2 | 2.9 × 1.7 |

- 각 이미지 아래 caption 배치
- caption 길이 > 칸 폭 → 글자 크기 자동 축소 (최소 8pt, 그 이하는 말줄임 처리, P-5)

### 4.5 취합 출력 로직 (관리자)
```
선택 보고서 배열(관리자 지정 순서) 순회:
  for 각 보고서:
    - 간지 슬라이드 1장 삽입 (제목·작성자·날짜, M-6)
    - 텍스트 페이지(들) 렌더
    - 이미지 페이지 렌더
1회 처리 개수 상한 설정 (예: 20건) → 초과 시 안내 (M-7)
```

---

## 5. 이미지 리사이즈 로직

```
파일 선택 시:
  browser-image-compression 옵션
    maxSizeMB: 0.8          // 800KB
    maxWidthOrHeight: 1600
  → 압축 결과를 Base64 변환
  → reports/{id}/images 문서로 저장
```
> 800KB로 잡는 이유: Firestore 문서 1MB 한도에서 caption·필드 여유 확보.

---

## 6. 권한 규칙 (Firestore Security Rules 개념)

| 대상 | 작업자 | 관리자 |
|---|---|---|
| 본인 user 문서 | 읽기 | 전체 읽기/삭제 |
| 본인 reports | 읽기·쓰기·삭제 | 전체 읽기·삭제 |
| 타인 reports | 불가 | 가능 |
| 관리자 판별 | 지정 이메일 상수와 일치 여부 |

---

## 7. 상태 처리 / 예외

| 상황 | 처리 |
|---|---|
| 이미지 0장 | 이미지 페이지 생략 또는 경고 |
| 이미지 6장 초과 시도 | 첨부 차단 (최대 6) |
| 텍스트 비어있음 | 저장 경고 |
| 작성자 삭제된 보고서 | ownerName "작성자 미상" 표시, 조회·출력 유지 |
| 취합 대량 초과 | 상한 안내 후 분할 요청 |
| 압축 후에도 큰 이미지 | 재압축 또는 첨부 거부 안내 |

---

## 8. 개발 순서 (권장)

1. Firebase 프로젝트 + Auth + Firestore 세팅
2. 로그인/회원가입 + 역할 분기
3. 보고서 작성 화면 (CKEditor5 + 이미지 업로드·리사이즈)
4. Firestore 저장/조회 (임시저장 포함)
5. PPTX 생성 (텍스트 페이지 → 이미지 페이지 → 미리보기)
6. 장수별 레이아웃 6종 구현
7. 관리자 화면 (목록·삭제·개별 출력)
8. 취합 출력(간지·순서·상한)
9. 검색·필터, 드래그 정렬 마감
10. 예외 처리·테스트

---

## 9. 준비물 체크리스트

- [ ] 국순당 로고 PNG (준비 완료: `국순당로고.png`)
- [ ] 관리자 지정 이메일 확정
- [ ] 브랜드 색상 (확정: #002060 / #DD6909 / #FA9F17 / #221E21)
- [ ] Firebase 프로젝트 생성 및 API 키
- [ ] 템플릿 필드 최종 확인 (`template_pdf.pdf`)
