7ed94a25df
사용자 가설 적중: "ㄱ을 그릴때 ㄱ이 다 그려질때까지 다음 입력이 안되는거 아니야?" =
R3 (redraw 누적 frame budget 초과 → main thread block → 입력 적체).
매 RAF frame 마다 모든 stroke 의 perfect-freehand outline + new Path2D 를 재계산.
stroke 73 × 평균 30 점 ≈ 2200 점 outline 매 frame. iPad CPU 에서 16ms frame budget
초과 → next pointermove/down 이벤트가 main thread queue 에 적체 → 사용자 인식상
"ㄱ 다 그려지기 전엔 ㅏ 입력 안 됨".
Fix:
- Stroke 타입에 _path2d / _size 런타임 캐시 추가. 완료 stroke 는 첫 draw 시점에
outline + Path2D 생성 후 캐시. 이후 redraw 는 ctx.fill(cachedPath) 만 (GPU 가속).
- inflight 만 매 frame 재계산 (점 추가됨).
- effectiveSize (가늘게/보통/굵게 토글) 변경 시 _size mismatch 로 자동 캐시 무효화.
직렬화 안전:
- _path2d / _size 는 `_` prefix 가 marker. backup()/flushSave() 가 serializableStrokes()
로 {id, points} 만 추출. 서버/localStorage 에 cruft 안 들어감.
기대 효과:
- redraw 비용: O(strokes × points) → O(strokes × 1 ctx.fill) → O(1 GPU fill ×N).
- main thread block 해소 → pointer 이벤트 큐 적체 사라짐 → 다음 stroke 즉시 진입.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>