# task-2204: InsuRo 이미지 편집기 fabric.js + React DOM 충돌 근본 해결

## 상태: DONE

## 변경 파일
- `src/pages/ImageEditor.tsx`

## 근본 원인
fabric.js `new Canvas()`가 React JSX 트리 내의 `<canvas>` 엘리먼트를 전달받으면, wrapper div 생성/canvas 복제 등 DOM을 직접 조작하여 React의 virtual DOM reconciliation과 충돌. `insertBefore` 에러 → 흰 화면 크래시 발생.

이전 시도(task-2201, task-2203)에서 `requestAnimationFrame`/`setTimeout`으로 React 상태 업데이트 타이밍을 지연시키는 방식을 시도했으나, DOM 소유권 충돌 자체가 해결되지 않아 실패.

## 해결 방법: React DOM 밖에서 Canvas 마운트

### 핵심 변경 3가지

1. **canvas 엘리먼트 동적 생성** (React JSX 제거)
   - 기존: `<canvas ref={canvasElRef} className="block" />` (React가 DOM 관리)
   - 변경: `<div ref={canvasContainerRef} className="block" />` (빈 div만 React가 관리)
   - `useEffect` 내에서 `document.createElement('canvas')`로 canvas를 동적 생성 후 div에 삽입
   - fabric.js가 이 canvas를 자유롭게 조작해도 React와 충돌 없음

2. **cleanup에서 동적 DOM 정리**
   - `useEffect` return에서 `canvas.dispose()` 후 `while (container.firstChild)` 루프로 동적 생성 엘리먼트 정리

3. **requestAnimationFrame 래핑 제거**
   - `loadImageToCanvas`에서 React 상태 업데이트를 `requestAnimationFrame`으로 감싸던 워크어라운드 제거
   - 동적 canvas 방식에서는 DOM 충돌이 없으므로 불필요

### 변경 전/후 비교

```tsx
// 변경 전 — React가 canvas를 관리
const canvasElRef = useRef<HTMLCanvasElement>(null);
// JSX: <canvas ref={canvasElRef} className="block" />
// fabric: new fabric.Canvas(canvasElRef.current, {...})

// 변경 후 — canvas를 JS로 동적 생성, React 밖
const canvasContainerRef = useRef<HTMLDivElement>(null);
// JSX: <div ref={canvasContainerRef} className="block" />
// useEffect 내: const canvasEl = document.createElement('canvas');
//               container.appendChild(canvasEl);
//               new fabric.Canvas(canvasEl, {...})
```

## 검증 결과
- `npm run build`: 성공 (12.31s, TypeScript 에러 없음)
- 기존 기능(크롭/필터/오버레이/AI/콜라주/일괄처리) 코드 영향 없음 — `fabricRef.current` 인터페이스 동일

## 브라우저 테스트 필요 항목
- [ ] /tools/image-editor 접근 → UI 정상 표시
- [ ] 이미지 파일 업로드 → Canvas에 이미지 정상 표시
- [ ] 크롭 도구 동작
- [ ] 필터 적용 동작
- [ ] 다운로드 동작
