# InsuWiki TOC 4가지 버그 수정

## 배경
InsuWiki의 목차(TOC) 기능에 4가지 문제가 보고됨. 이전에도 수정 시도했으나 여전히 미해결.

## 프로젝트 경로
- InsuWiki 루트: `/home/jay/projects/insuwiki/`
- TOC 컴포넌트: `/home/jay/projects/insuwiki/nextapp/src/components/TableOfContents.tsx`
- TOC 테스트: `/home/jay/projects/insuwiki/nextapp/src/components/__tests__/TableOfContents.test.tsx`
- DocumentClient: `/home/jay/projects/insuwiki/nextapp/src/app/docs/[id]/DocumentClient.tsx`
- CSS: `/home/jay/projects/insuwiki/nextapp/src/app/globals.css`

## 이슈 4가지

### 이슈 1: 하이라이트 점이 본문 스크롤에 따라 안 움직임
**현상**: 본문을 스크롤하면 TOC 왼쪽의 인디케이터 점이 현재 섹션에 맞춰 이동해야 하는데, 움직이지 않음.

**원인 조사 포인트**:
- View 모드: `IntersectionObserver`의 `root`가 `document.getElementById('scroll-container')`인데, DOM에 실제 존재하는지 확인
- Edit 모드: scroll 이벤트 핸들러에서 heading의 `textContent`와 TOC item의 `text` 매칭이 실패할 수 있음
- `isClickedRef.current`가 `true`로 고착되어 observer 콜백이 무시될 수 있음
- IntersectionObserver가 toc 배열 변경 시 재등록되는지 확인

**수정 방향**:
- IntersectionObserver 동작 확인 및 수정
- Edit 모드 heading 매칭 로직 강화 (텍스트 정규화, fallback 매칭)
- isClickedRef 타임아웃 안전장치 강화

### 이슈 2: TOC 목차 클릭 시 더블클릭해야 본문 이동
**현상**: TOC 항목을 싱글 클릭하면 본문이 해당 위치로 스크롤되어야 하는데, 더블클릭해야 작동함.

**이전 수정 이력**: task-535.1에서 ID 생성 일관성, scroll-mt, IntersectionObserver root 등 수정했으나 여전히 미해결.

**원인 조사 포인트**:
- Edit 모드에서 ProseMirror 에디터가 첫 번째 클릭을 포커스 이벤트로 가로챔
- `onClick` 핸들러 내 `handleEditingClick(item)`이 실행되지만, ProseMirror가 focus를 잡으면서 scrollIntoView가 취소될 수 있음
- TOC의 `<a>` 태그 href="#id"가 페이지 상단으로 이동 → onClick이 다시 목표로 이동 (두 번 필요)
- 첫 클릭: activeId 변경 → 리렌더 → 스크롤 취소 가능성

**수정 방향**:
- Edit 모드에서 클릭 시 `e.stopPropagation()` 추가하여 이벤트 버블링 방지
- `handleEditingClick` 내에서 `scrollIntoView` 전에 `requestAnimationFrame` 또는 `setTimeout(0)` 래핑으로 포커스 경합 회피
- `<a href="#">` 대신 `<button>` 또는 `<div role="button" tabIndex={0}>` 사용 검토 (앵커 태그의 기본 동작 간섭 제거)
- View 모드에서도 `e.preventDefault()`가 확실히 동작하는지 확인

### 이슈 3: 클릭 후 하이라이트 점 위치가 sync 안 맞음
**현상**: TOC 항목 클릭 후 점이 나타나지만, 실제 본문 위치와 동기화되지 않음.

**원인 조사 포인트**:
- Edit 모드에서 heading 매칭이 `textContent?.trim() === item.text`로 되어 있는데, 마크다운 파싱 후 텍스트와 ProseMirror 렌더링 텍스트가 다를 수 있음
- `setActiveId(item.id)`를 클릭 즉시 호출하므로 점은 바로 이동하지만, 실제 스크롤은 비동기적 → 스크롤 완료 후 observer가 다른 항목을 active로 설정할 수 있음

**수정 방향**:
- 클릭 후 `isClickedRef.current = true` 상태에서 observer 억제 기간을 스크롤 완료까지로 조정
- `scrollend` 이벤트 또는 `scroll` 이벤트 debounce 활용
- Edit 모드: heading ID 기반 매칭으로 전환 (텍스트 매칭 대신)

### 이슈 4: 마우스 위치에 따른 스크롤 영역 분리 안 됨
**현상**: 마우스가 TOC 영역 위에 있을 때 마우스 휠을 돌리면 TOC가 스크롤되어야 하고, 편집창 위에 있을 때는 편집창이 스크롤되어야 하는데, 현재는 클릭으로 포커스를 전환해야 함.

**원인 조사 포인트**:
- TOC `<aside>`에 `overflow-y-auto overscroll-contain`은 있지만, 부모 `scroll-container`가 스크롤을 가로챔
- CSS `overscroll-contain`만으로는 부족. wheel 이벤트가 TOC에서 발생해도 TOC 스크롤이 끝나면 부모로 전파됨

**수정 방향**:
- TOC 영역에 `onWheel` 이벤트 핸들러 추가: TOC 내 스크롤 가능할 때 `e.stopPropagation()` 호출
- 핵심 코드 패턴:
```tsx
const handleTocWheel = (e: React.WheelEvent) => {
    const el = tocRef.current;
    if (!el) return;
    const { scrollTop, scrollHeight, clientHeight } = el;
    const atTop = scrollTop === 0 && e.deltaY < 0;
    const atBottom = scrollTop + clientHeight >= scrollHeight && e.deltaY > 0;
    if (!atTop && !atBottom) {
        e.stopPropagation();
    }
};
```

## 수정 파일 목록
1. `nextapp/src/components/TableOfContents.tsx` — 4가지 이슈 전부 여기서 수정
2. `nextapp/src/app/docs/[id]/DocumentClient.tsx` — 필요 시 scroll-container 관련 수정
3. `nextapp/src/components/__tests__/TableOfContents.test.tsx` — 수정 사항 반영한 테스트 업데이트

## 검증 기준
1. View 모드: 본문 스크롤 시 하이라이트 점이 현재 보이는 섹션에 맞춰 실시간 이동
2. Edit 모드: 본문 스크롤 시 하이라이트 점이 현재 편집 중인 섹션에 맞춰 이동
3. TOC 항목 **싱글 클릭**으로 본문 해당 위치로 스크롤 (View + Edit 모드 모두)
4. 클릭 후 하이라이트 점 위치가 스크롤된 본문 위치와 정확히 동기화
5. 마우스가 TOC 영역 위: 마우스 휠 → TOC만 스크롤 (편집창 스크롤 안 됨)
6. 마우스가 편집창 영역 위: 마우스 휠 → 편집창만 스크롤
7. 기존 테스트 PASS
8. `npm run build` 성공

## 레벨
Lv.2 (기능 구현) — 파일 특정, 동작 기대치 명확
