# InsuWiki 프로젝트 전체 구조 파악 및 개선점 도출 보고서

**작업 ID**: task-68.1
**작업일**: 2026-03-02
**수행팀**: 개발1팀 (헤르메스 팀장, 불칸/이리스/아테나/아르고스)
**프로젝트 경로**: `/home/jay/projects/insuwiki/`
**기술 스택**: Next.js 16 + React 19 + TypeScript + Tailwind CSS 4 + Firebase + Vercel

---

## 1. 프로젝트 구조 개요

### 디렉토리 구조
```
insuwiki/
├── nextapp/                    # Next.js 16 App Router (프론트엔드+API)
│   ├── src/app/               # 라우팅 (/, /docs/[id], /admin/*, /login, /new, /trash)
│   │   └── api/               # 14개 API 엔드포인트 (admin/ai/drive-image/share-target/upload)
│   ├── src/components/        # UI 컴포넌트 27개
│   ├── src/hooks/             # 커스텀 훅 (useWikiMap, useDocumentLock, useSemanticSearch 등)
│   ├── src/contexts/          # AuthContext, VoiceCommandContext
│   ├── src/lib/               # 유틸리티 (firebase, ai, tiptap, utils)
│   ├── src/types/             # TypeScript 타입 정의
│   └── src/utils/             # 암호화, 잠금 유틸
├── functions/                  # Firebase Cloud Functions (6개 함수)
│   └── src/                   # aggregateBacklinks, backup, cleanupLocks, crawlYoutubeChannels, pdfIndexing, ragQuery
├── scripts/                    # 관리 스크립트 (백링크 재집계, 시딩 등)
├── docs/                       # 프로젝트 문서 (specs, reports, plans, decisions 등)
├── firestore.rules            # Firestore 보안 규칙 (11개 컬렉션)
├── firestore.indexes.json     # Firestore 인덱스 (3개만 정의)
└── firebase.json              # Firebase 설정
```

### 규모
- 커밋 수: 159개
- 소스 파일: ~85개 (nextapp/src)
- 코드 라인: ~13,663줄
- Firestore 컬렉션: 18개+ (규칙 정의는 11개만)
- API 엔드포인트: 14개
- Cloud Functions: 6개

### 프로젝트 현재 상태
- 코어 기능 완성도: ~70-75%
- 배포 환경: Vercel(프론트) + Firebase(인증/DB) + GCP Cloud Functions(AI)
- Production URL: https://insuwiki.vercel.app
- 핵심 완성 기능: Auth, 에디터(TipTap), 검색(3모드), AI 어시스턴트, RAG 파이프라인, PWA/음성녹음, 관리자 대시보드
- 미구현: Query Router(3-way AI 분기), Vandalism Protection, E2E 테스트

---

## 2. 치명적 이슈 (즉시 수정 필요)

### [CRITICAL-1] AI API 라우트 Bearer 토큰 미검증 (보안)
- **파일**: `api/ai/query`, `api/ai/status`, `api/ai/summarize`, `api/ai/settings`, `api/ai/feedback`
- **내용**: Firebase ID Token을 검증하지 않고 `Authorization: Bearer {uid}` 값을 그대로 UID로 신뢰
- **위험**: 임의의 UID를 Bearer 토큰으로 보내면 다른 사용자의 설정 조회/수정, AI 기능 무단 사용 가능
- **수정**: `getAuth().verifyIdToken(token)`으로 교체 필요

### [CRITICAL-2] share-target UID 쿼리파라미터 무검증 (보안)
- **파일**: `api/share-target/route.ts`
- **내용**: UID를 URL 파라미터로 받아 검증 없이 사용. 다른 사용자의 Daily Note에 무단 삽입 가능

### [CRITICAL-3] 암호화 기본값 폴백 키 하드코딩 (보안)
- **파일**: `nextapp/src/utils/encryption.ts`
- **내용**: `AI_ENCRYPTION_KEY` 환경변수 미설정 시 `'default-secret-key-32-chars-long'` 사용 → 소스코드 공개 키로 모든 사용자의 Gemini API 키 복호화 가능

### [CRITICAL-4] pdfIndexing Batch 재사용 버그 (기능)
- **파일**: `functions/src/pdfIndexing.ts:190-225`
- **내용**: Firestore WriteBatch `commit()` 후 동일 객체 재사용 → 400개 이상 청크에서 오류 또는 데이터 손실

### [CRITICAL-5] 공개 문서 무제한 수정 (보안)
- **파일**: `firestore.rules:64-68`
- **내용**: `isPublic()` 조건으로 인증된 누구나 공개 문서 수정 가능

---

## 3. 높은 우선순위 이슈

### 백엔드/인프라

| # | 이슈 | 파일 | 설명 |
|---|------|------|------|
| H-1 | Firestore 복합 인덱스 누락 | `firestore.indexes.json` | `insurance_metadata`, `gemini_file_cache`, `query_logs` 등 복합 쿼리가 인덱스 없이 실행 → FAILED_PRECONDITION 오류 가능 |
| H-2 | 주요 컬렉션 Firestore 규칙 누락 | `firestore.rules` | `insurance_chunks`, `query_logs`, `youtube_*`, `whitelist`, `apiKeys` 등 규칙 미정의 |
| H-3 | search-wiki 전체 풀스캔 | `api/ai/search-wiki/route.ts` | 모든 embeddings를 메모리에 올려 cosine similarity 계산 (MVP 주석 존재) |
| H-4 | Functions SDK v1/v2 혼재 | `functions/src/` | v1(3개)과 v2(3개) 혼재, 리전/메모리 설정 불일치 |
| H-5 | 임시 파일 오류 시 누수 | `ragQuery.ts`, `pdfIndexing.ts` | finally 블록 없어 /tmp 파티션 누적 위험 |
| H-6 | versions/revisions 과잉 권한 | `firestore.rules:80-89` | 비공개 문서 히스토리도 인증된 누구나 접근 가능 |

### 프론트엔드

| # | 이슈 | 파일 | 설명 |
|---|------|------|------|
| H-7 | DocumentClient.tsx 1724줄 갓 컴포넌트 | `docs/[id]/DocumentClient.tsx` | 10개 이상 책임 혼재, 테스트/유지보수 불가 |
| H-8 | useWikiMap 중복 인스턴스화 | `hooks/useWikiMap.ts` | DocumentClient와 ReflectEditor에서 각각 호출 → Firestore 중복 쿼리 |
| H-9 | 클라이언트 번들에 AI SDK 포함 | `hooks/useSemanticSearch.ts` | `@google/generative-ai`가 클라이언트에서 직접 import → API 키 노출 |
| H-10 | 잠금 타임아웃 상수 불일치 | `utils/documentLock.ts` vs `hooks/useDocumentLock.ts` | 30분 vs 5분으로 다른 값 |
| H-11 | UserRole 타입 이중 정의 | `types/firestore.ts` vs `contexts/AuthContext.tsx` | 'admin/editor/viewer' vs 'guest/member/admin' |
| H-12 | Admin 미들웨어 부재 | `middleware.ts` 미존재 | 서버 레벨 인증 없음, 클라이언트 측 역할 체크만 존재 |
| H-13 | next.config.ts serverExternalPackages 미설정 | `next.config.ts` | firebase-admin, googleapis가 번들에 포함될 위험 |

### 테스트/품질

| # | 이슈 | 파일 | 설명 |
|---|------|------|------|
| H-14 | 테스트 코드 전무 | 전체 | 85개 파일, 13,663줄 코드에 테스트 0건 |
| H-15 | CI/CD 빌드 검증 없음 | `.github/workflows/` | 백업 워크플로우만 존재, PR 검증 파이프라인 없음 |
| H-16 | [DEBUG] console.log 120건 | 전체 코드베이스 | UID 등 민감 정보 브라우저 콘솔 노출 |
| H-17 | `any` 타입 114건 | 30+ 파일 | TypeScript 타입 안전성 무력화 |

---

## 4. 중간 우선순위 이슈

### 코드 품질/구조

| # | 이슈 | 설명 |
|---|------|------|
| M-1 | ADMIN_EMAILS 하드코딩 4곳 중복 | `DocumentClient`, `TrashClient`, `admin/purge`, `admin/drive-upload` |
| M-2 | 작성자 이름 하드코딩 5곳 | `'jonghyuk.jeon' ? '전종혁'` 변환 로직 반복 |
| M-3 | 한글 초성 함수 3중 중복 | `hangul.ts`(getChoseong), `korean.ts`(getChosung), `es-hangul`(라이브러리) |
| M-4 | cleanText 함수 3중 중복 | DocumentClient, TableOfContents, lib/utils/text.ts |
| M-5 | invalidate-cache 관리자 권한 미검증 | 인증된 누구나 캐시 전체 삭제 가능 |
| M-6 | Firebase Admin 초기화 불일치 | upload/route.ts, drive-image/route.ts가 자체 초기화 |
| M-7 | insurance_metadata updatedAt 타입 불일치 | ISO 문자열 vs serverTimestamp() 혼용 |
| M-8 | aggregateBacklinks O(n²) 배열 탐색 | Set 사용으로 O(n) 개선 가능 |
| M-9 | isAdmin() Firestore 읽기 비용 | Custom Claims로 전환하면 추가 읽기 불필요 |
| M-10 | node_modules가 git에 커밋됨 | `functions/node_modules/` 전체 추적 중 |
| M-11 | 불필요한 파일 git 포함 | `chrome_profile_notebooklm/`, `firestore-debug.log` 등 |

### UX/UI

| # | 이슈 | 설명 |
|---|------|------|
| M-12 | alert/confirm 60건 남용 | 사용자 흐름 중단, Toast 알림으로 교체 필요 |
| M-13 | 폰트 변수 불일치 버그 | globals.css의 `--font-geekble-malang` 참조하나 폰트 로딩 없음 |
| M-14 | 접근성(a11y) 전반 미흡 | aria-label 5건, 모달 focus trap 없음, WCAG 미준수 |
| M-15 | Admin 페이지 모바일 미대응 | 고정 `w-56` 사이드바, 모바일 레이아웃 붕괴 |
| M-16 | 즐겨찾기 localStorage 의존 | 기기 변경/캐시 삭제 시 소실 |
| M-17 | TipTap/react-markdown 동적 import 미적용 | 번들 사이즈 과다, 지연 로드 필요 |
| M-18 | `<img>` 태그 직접 사용 | Next.js `<Image>` 미활용, 최적화 부재 |
| M-19 | 다크 모드 반쪽짜리 구현 | CSS 변수는 있으나 컴포넌트에 `bg-white` 하드코딩 |

---

## 5. 낮은 우선순위 이슈

| # | 이슈 | 설명 |
|---|------|------|
| L-1 | YouTube 자막 HTML 스크래핑 | YouTube 내부 구조 변경 시 즉시 중단, TOS 위반 소지 |
| L-2 | drive-image 인증 없는 파일 프록시 | Security through Obscurity 방식 |
| L-3 | 모바일 Bottom Navigation 부재 | 엄지 접근성 낮음 |
| L-4 | `src/utils/`와 `src/lib/utils/` 혼재 | 유틸리티 경로 기준 없음 |
| L-5 | 보안 헤더 미설정 | CSP, X-Frame-Options 등 |
| L-6 | Rate Limiting 없음 | 모든 API 무제한 호출 가능 |
| L-7 | ESLint 규칙 최소화 | no-explicit-any, no-console 미적용 |
| L-8 | `hangul-js` 패키지 중복 설치 | `es-hangul`과 병행, 제거 가능 |
| L-9 | components/ 디렉토리 평면 구조 | 27개 파일 루트에 나열, 도메인별 정리 필요 |

---

## 6. 프로젝트 강점

1. **명확한 도메인 특화**: 보험 설계사를 위한 Wiki-as-a-Tool 컨셉이 일관성 있게 구현
2. **정교한 에디터**: TipTap 기반 WikiLink 자동완성, 한글 초성 검색, 5단계 계층 번호, 잠금 시스템
3. **3-색상 탭 테마**: Wiki(Indigo)/My(Violet)/Daily(Emerald) 색상 분리가 효과적
4. **AI 인프라 완성도**: Gemini 기반 하이브리드 RAG, Cloud Functions v2 배포 완료
5. **PWA + 음성 녹음**: 현장 설계사 워크플로우를 반영한 실용적 설계
6. **문서화 수준 우수**: docs/ 하위에 체계적인 스펙/보고서/결정사항 기록

---

## 7. 우선순위별 액션 플랜

### Phase 1: 긴급 보안 패치 (이번 주)
1. AI API 5개 라우트에 `verifyIdToken()` 적용 (공통 미들웨어 생성)
2. share-target UID 파라미터 → Firebase ID Token 검증 전환
3. `encryption.ts` 기본값 폴백 제거 (환경변수 미설정 시 에러 발생하도록)
4. `firestore.rules` 공개 문서 수정 권한 제한
5. `pdfIndexing.ts` WriteBatch 재사용 버그 수정

### Phase 2: 운영 안정성 (2주 이내)
1. Firestore 복합 인덱스 추가 (5개 컬렉션)
2. 누락 컬렉션 Firestore 규칙 추가
3. CI/CD 파이프라인 구축 (`next build` + `eslint` + `tsc --noEmit`)
4. 프로덕션 console.log 제거
5. `node_modules` 및 불필요 파일 git 추적 제거

### Phase 3: 코드 품질 개선 (1개월)
1. DocumentClient.tsx 분리 (편집/조회/저장/AI 패널 등 서브컴포넌트화)
2. useWikiMap Context 리프트업
3. 공통 미들웨어/유틸 통합 (ADMIN_EMAILS, cleanText, 초성 함수 등)
4. `any` 타입 제거 (114건)
5. 테스트 프레임워크 도입 (Vitest) + 핵심 비즈니스 로직 테스트

### Phase 4: UX/성능 최적화 (중장기)
1. alert/confirm → Toast 알림 전환
2. Admin 반응형 대응
3. 접근성 기본 수준 확보 (aria-label, focus trap)
4. TipTap/react-markdown 동적 import
5. `next.config.ts` 최적화 (serverExternalPackages, Image 설정 등)

---

## 8. 스코어카드 요약

| 영역 | 점수 | 비고 |
|------|------|------|
| 보안 | 3/10 | AI API 인증 우회, 시크릿 관리 취약 |
| 테스트 | 0/10 | 테스트 코드 전무 |
| CI/CD | 2/10 | 백업 워크플로우만 존재 |
| 코드 구조 | 4/10 | 갓 컴포넌트, 중복 코드, 하드코딩 |
| TypeScript | 5/10 | strict 모드 ON이나 any 남발 |
| 에러 핸들링 | 6/10 | try-catch 있으나 Error Boundary 없음 |
| UX/UI | 6/10 | 핵심 기능 잘 구현, 세부 완성도 부족 |
| 프론트 아키텍처 | 5/10 | App Router 활용 양호, 번들 최적화 부족 |
| 백엔드 아키텍처 | 5/10 | 기능 구현 양호, 보안/인덱스 미비 |
| 문서화 | 8/10 | 체계적 문서 관리, 의사결정 기록 우수 |
| **종합** | **4.4/10** | **보안 패치 후 구조 개선 필요** |

---

## 생성/수정 파일 목록
- **생성**: `/home/jay/workspace/memory/reports/task-68.1.md` (본 보고서)
- **수정**: 없음 (분석 전용 작업)

## 테스트 결과
- 분석 전용 작업으로 테스트 대상 아님
- 4개 팀원이 독립적으로 각 영역을 분석 완료

## 버그 유무
- 프로젝트 내 치명적 버그 5건 식별 (섹션 2 참조)
- 본 작업에 의한 버그 발생 없음

## 비고
- 이 프로젝트는 빠른 기능 개발로 기술 부채가 축적된 상태
- 가장 시급한 것은 AI API 인증 우회 보안 패치
- 장기적으로는 DocumentClient.tsx 분리, 테스트 도입, CI/CD 구축이 핵심
