[x] ISSUE1: 첨삭 영역을 포함한 곳 복사 > 붙여넣기 시, 첨삭 영역 늘어남 (2.24 화 오후 8:48)
[x] copy에 zero width space 제거 + 순수 텍스트만
[x] ctrl + all > copy > 맨 뒤 커서 > paste: startindex랑 endindex가 0으로 전송
근본 원인:
CoverLetterContent.tsx(242-248, 2월24일(화) 오후 2시56분)의 sendTextPatch 내부에서 getCaretPosition()을 다시 호출. 그러나 이 시점은 sendTextPatch → updateText → handleTextChange 순서로, 아직 React 상태가 업데이트되지 않아 DOM은 여전히 이전 상태.
따라서 getCaretPosition()이 반환하는 값은 삽입 이전의 커서 위치 (start)
insertTextAtCaret에서는 이미 올바른 값 start + insertStr.length를 caretOffsetRef.current에 저장해두지만, sendTextPatch가 이를 무시하고 getCaretPosition()을 다시 호출
문제 시나리오 (텍스트가 "ABCDE"일 때):
insertStr = "ABCDE")start = 5)caretOffsetRef = 5 + 5 = 10 (올바름)sendTextPatch 내부에서 getCaretPosition() 재호출 → DOM 미업데이트 상태이므로 caretAfter = 5 (틀림!)buildTextPatch("ABCDE", "ABCDEABCDE", { caretAfter: 5 }):
insertedLength = 5 = caretAfter → candidateStart = 5 - 5 = 0"" + "ABCDE" + "ABCDE" = "ABCDEABCDE" → 성립!startIdx = 0, endIdx = 0 ← 버그!수정: sendTextPatch에서 getCaretPosition() 재호출 대신 caretOffsetRef.current를 직접 사용. 이 ref는 항상 "작업 직후의 커서 위치"를 가리키도록 각 경로에서 미리 업데이트됨.
[x] ISSUE2: 텍스트 변경시에도 모달 위치 안따라감 (영상있음) (2.24 화 오후 8:48)
[x] Reviewer
[x] 기존 첨삭 모달: 따라가고는 있지만 성능이 좋지 않음.
useTextSelection에 useLayoutEffect 추가하여 selection.range 변경 시 DOM에서 modalTop/modalLeft 즉시 재계산
[x] 드래그 모달: 안따라감. 사라짐.
문제 원인:
updateSelectionForTextChange는 range/selectedText/lineEndIndex는 업데이트하지만 modalTop/modalLeft는 그대로 둠editingReview effect가 DOM에서 위치 재계산하지만, 드래그 모달은 최초 1회만 계산 후 방치됨useLayoutEffect로 selection.range가 바뀔 때마다 DOM에서 즉시 위치를 재계산하도록 수정
→ useTextSelection/index.ts 한 파일만 수정
추가된 useLayoutEffect 동작:
TEXT_UPDATE 수신
→ updateSelectionForTextChange()가 selection.range 업데이트 (modalTop/Left는 그대로)
→ React 리렌더 (DOM 갱신)
→ useLayoutEffect (브라우저 페인트 전, 동기 실행)
→ selection.range가 lastRecalcRangeRef와 다르면 실행
→ findNodeAtIndex로 DOM 노드 찾기
→ document.createRange()로 실제 DOM Range 생성
→ getClientRects()로 현재 위치 계산
→ onSelectionChange({ ...selection, modalTop, modalLeft }) 호출
→ 무한루프 방지: lastRecalcRangeRef에 {start, end} 기록
→ 다음 useLayoutEffect 실행 시 range 동일 → 조기 return
두 가지 개선 효과:
useLayoutEffect는 DOM 갱신 직후 페인트 전에 동기로 실행 → 이전처럼 한 프레임 뒤처지는 문제 해결range가 shift되면 DOM 기반으로 즉시 위치 재계산 → 드래그 모달도 텍스트 이동에 따라감Writer 입장에서 모달은 텍스트 변경과 동시에 일어날 수 없으므로 제외.
[x] ISSUE 3: 텍스트 변경이 빠르면 드래그 모달이 꺼짐 (영상 있음) (2.24 화 오후 8:48)
[x] ISSUE 4: TEXT_REPLACE_ALL 발생시, 커서가 처음으로 이동 (2.24 화 오후 8:48)
문제 원인:
TEXT_REPLACE_ALL 이벤트로 인해 DOM이 교체될 때, 브라우저가 selectionchange 이벤트를 발생시키면서 커서 위치를 0으로 초기화0 값을 커서 추적 로직이 읽어 caretOffsetRef를 덮어쓰면서, 커서 복원 시 맨 앞으로 이동하는 경쟁 상태(Race Condition)가 발생해결 방안:
selectionchange 이벤트에 대한 의존을 제거PageUp, PageDown 키에 대한 추적 로직을 추가하여 키보드 탐색 커버리지를 완성기대 효과:
TEXT_REPLACE_ALL 이벤트가 트리거되어도 커서 위치가 안정적으로 유지[x] ISSUE 5: 첨삭이 있는 영역을 포함해서 드래그 > 다른 문자로 변경 > input 입력시 removeChild error (2.25 수 오후 5:13)

[x] ⚠️⚠️⚠️⚠️⚠️ ISSUE 6: 첨삭 내부 영역에서 드래그는 전부 드래그 하거나, 하지 않거나만 가능함. (미해결) ⚠️⚠️⚠️⚠️⚠️
[x] ISSUE 7: 글씨 빠르게 칠 때, index 계산 이상함 > 첨삭 태그 내부에 글씨 입력함. (2.25 수 오후 5:13)
[x] ISSUE 8: 빠르게 텍스트를 치다보면 특정 소켓 누락 or 뒤늦게 도착하는 케이스 발생 (2.25 수 오후 5:13)

[x] ISSUE 8-2: debounce로 변경되면서 첨삭 영역 포함한 delete시에 API 요청이 텍스트 반영보다 선행되기 때문에 텍스트는 삭제되지 않고, 첨삭만 삭제되는 이슈가 생겼습니다
[x] ISSUE 9: 저장하기 API 가끔 동작 x (2.24 화 오후 8:48)
isSavingRef.current가 true로 설정된 후, 유효성 검사(문항 없음, 변경 내용 없음 등)로 인해 함수가 조기 종료(early return)되면서 false로 다시 초기화되지 않아 발생한 문제isSavingRef.current = true 설정 시점을 유효성 검사 이후, 실제 API 요청 직전으로 옮겨서 해결const saveCurrentAnswer = async (showSuccessToast = true) => {
console.log(isPending);
console.log(isSavingRef);
if (isPending || isSavingRef.current) return false;
...