# task-1696.1 완료 보고서
> InsuWiki Review 검토 대기열 연결 오류 수정

## S - Situation
InsuWiki 검토 대기열 (Review) 화면은 task-1692.1에서 대시보드 insight 미승인 리스트 연동으로 전면 교체되어 Firestore `onSnapshot` 실시간 리스너로 동작 중이다. Firestore 복합 인덱스(`sourceType + status + updatedAt`)가 `firestore.indexes.json`에 정의되어 있다.

## C - Complication
Review 아이콘 클릭 시 "연결 오류: 검토 대기열을 불러올 수 없습니다. 새로고침해 주세요." 에러 배너가 "대기 0건" 상태 요약과 동시에 표시되었다. 원인 분석 결과 2가지 코드 결함 확인:
1. `useReviewQueueListener.ts`의 `connect()` 함수가 `setError(null)`을 호출하지 않아, Firestore 인덱스 빌드 중/일시적 네트워크 오류 등으로 첫 연결 실패 시 이후 재연결(visibilitychange/pageshow) 성공해도 에러 상태가 클리어되지 않음
2. `review/page.tsx`에서 에러 배너와 정상 UI(대기 N건, 빈 상태 메시지)가 상호배제되지 않아, 에러 발생 시 "대기 0건"과 에러가 동시 노출됨. 재시도 버튼도 부재

## Q - Question
검토 대기열에서 일시적 연결 오류 후에도 정상 복구되고, 에러 시 구체적 메시지 + 재시도 버튼을 제공할 수 있는가?

## A - Answer
`connect()` 시작부에 `setError(null)` 추가로 재연결 시 stale 에러 클리어. `retry` 콜백 추가(`retryTrigger` state 활용)로 사용자 수동 재시도 지원. page.tsx에서 에러/정상 UI 상호배제 처리 + 에러 메시지 3종 분기(index/permission/기타) + 새로고침 버튼 추가. 테스트 14건 (기존 12건 + 신규 2건) 구성.

---

## 변경 사항

### useReviewQueueListener.ts
- `useCallback` import 추가
- `UseReviewQueueListenerReturn` 인터페이스에 `retry: () => void` 추가
- `retryTrigger` 상태 변수 추가 (useEffect 의존성 배열에 포함)
- `connect()` 시작부에 `setError(null)` 추가
- `retry` 콜백: error 클리어 + retryTrigger 증가로 useEffect 재실행

### review/page.tsx
- hook destructure에 `retry` 추가
- 상태 요약: `!loading && !error` 조건으로 변경 (에러 시 숨김)
- 빈 상태: `!loading && items.length === 0 && !error` 조건으로 변경 (에러 시 숨김)
- 에러 메시지: `error.message` 기반 3종 분기 (index 준비 중 / 권한 없음 / 일반 연결 오류)
- 새로고침 버튼 추가 (`retry` 호출)

### useReviewQueueListener.test.ts
- 기존 3개 테스트의 mockUseState 체인에 retryTrigger용 4번째 호출 추가
- return value 테스트에 `retry` 함수 존재 검증 추가
- 신규 테스트 2건: connect 에러 클리어 검증, retry 콜백 동작 검증

---

## 산출물 파일

- `/home/jay/projects/insuwiki/.worktrees/task-1696.1-dev1/nextapp/src/hooks/useReviewQueueListener.ts` (수정)
- `/home/jay/projects/insuwiki/.worktrees/task-1696.1-dev1/nextapp/src/app/review/page.tsx` (수정)
- `/home/jay/projects/insuwiki/.worktrees/task-1696.1-dev1/nextapp/src/hooks/__tests__/useReviewQueueListener.test.ts` (수정)

---

## 발견 이슈 및 해결

### 자체 해결 (6건)
1. **connect() 에러 미클리어** — `setError(null)` 추가로 재연결 시 stale 에러 제거 (`useReviewQueueListener.ts:62`)
2. **에러/빈상태 UI 동시 표시** — 조건을 `!loading && !error`로 변경하여 상호배제 (`page.tsx:166,201`)
3. **재시도 수단 부재** — `retry` 콜백 + 새로고침 버튼 추가 (`useReviewQueueListener.ts:47-50`, `page.tsx:189`)
4. **[마아트] permission 에러 대소문자 불일치** — `error.message.toLowerCase().includes()` 적용 (Firebase PERMISSION_DENIED 대응) (`page.tsx:184,186`)
5. **[마아트] loading+error 동시 표시** — 로딩 스피너 조건에 `!error` 추가 (`page.tsx:194`)
6. **[마아트] 테스트 검증 강화** — connect 에러 클리어 테스트 초기값을 실제 Error로 변경, retryTrigger를 `expect.any(Function)` 으로 함수형 업데이트 확인 (`test.ts:329,352`)

### 범위 외 미해결 (1건)
1. **Firestore 인덱스 미배포 가능성** — `firestore.indexes.json`에 복합 인덱스 정의되어 있으나, 프로덕션 배포(`firebase deploy --only firestore:indexes`) 여부 미확인. 인프라 배포 소관.

---

## 테스트 결과
- worktree에 node_modules 미설치로 vitest 직접 실행 불가 (pre-existing, task-1692.1과 동일)
- 테스트 파일 구조 검증: mockUseState 4회 체인 정합, retry 콜백 검증 로직 확인
- TypeScript 진단: 모든 에러가 pre-existing 모듈 해석 문제 (firebase/firestore, vitest)

---

## 머지 판단
- **머지 필요**: Yes
- **브랜치**: task/task-1696.1-dev1
- **워크트리 경로**: /home/jay/projects/insuwiki/.worktrees/task-1696.1-dev1
- **머지 의견**: 변경 범위가 작고 안전 (hook에 retry 추가 + page에서 조건 분기 개선). GlobalHeader.tsx도 같은 훅 사용하나 items만 destructure하므로 영향 없음. Firestore 인덱스 배포는 별도 확인 필요.

---

## 모델 사용 기록
- 이리스(프론트엔드): sonnet / useReviewQueueListener.ts + page.tsx 수정
- 아르고스(테스터): sonnet / 테스트 파일 업데이트 (retryTrigger mock + 신규 테스트 2건)
- 탐색 에이전트: haiku / 대시보드 server.py insight API 탐색 (단순 검색)

---

## QC 검증 결과

```json
{
  "task_id": "task-1696.1",
  "overall": "WARN",
  "checks": {
    "api_health": "SKIP (서버 작업 아님)",
    "file_check": "PASS (3 files OK, report 4997 bytes)",
    "data_integrity": "PASS",
    "test_runner": "SKIP (관련 테스트 파일 0개 — TS 파일이라 pytest 대상 아님)",
    "tdd_check": "WARN (구현 먼저 수정 → 테스트 업데이트, 버그 수정 특성)",
    "critical_gap": "PASS",
    "spec_compliance": "PASS",
    "duplicate_check": "PASS (최대 유사도 13.6%)"
  },
  "trust_summary": {
    "Tested": true,
    "Readable": true,
    "Unified": true,
    "Secured": true,
    "Trackable": true
  }
}
```

## 마아트 독립 검증

- **판정**: NEEDS WORK → 수정 후 PASS
- **발견 이슈 5건**: HIGH 1건, MEDIUM 2건, LOW 2건
- **수정 완료 3건**: permission 대소문자 (HIGH), loading+error 동시표시 (MEDIUM), 테스트 검증 강화 (MEDIUM)
- **유지 결정 1건**: retry/connect 이중 setError(null) — 즉시 UI 피드백 목적으로 의도적 유지 (LOW)
- **수용 불필요 1건**: connect 에러 클리어 테스트 초기값 — 수정 완료 (LOW)

## 세션 통계
- 총 도구 호출: 20회

### 수정 파일 목록
- /home/jay/projects/insuwiki/.worktrees/task-1696.1-dev1/nextapp/src/app/review/page.tsx: 6회 (Edit)
- /home/jay/projects/insuwiki/.worktrees/task-1696.1-dev1/nextapp/src/hooks/__tests__/useReviewQueueListener.test.ts: 5회 (Edit)
- /home/jay/workspace/memory/reports/task-1696.1.md: 4회 (Edit, Write)
- /home/jay/projects/insuwiki/.worktrees/task-1696.1-dev1/nextapp/src/hooks/useReviewQueueListener.ts: 2회 (Edit)
- bash_cmd: 2회 (Bash)
- /home/jay/workspace/memory/tasks/task-1696.1.md: 1회 (dispatch)

### 도구 사용 현황
- Edit: 16회
- Bash: 2회
- Write: 1회
- dispatch: 1회

