본문 바로가기
C.W.K.
Stream
Lesson 05 of 05 · published

callback ref로 측정해

~12 min · react, callback-ref, resize-observer

Level 0식은 재
0 XP0/33 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"waveform이 폭 0으로 렌더됐어. ref가 틀린 게 아니라 읽은 시점이 틀렸어."

버그: 폭 0인 waveform

waveform을 그리려면 컨테이너의 픽셀 폭을 알아야 해. ref와 빈 의존성 배열의 useEffect를 조합하면 컴포넌트 mount 때 한 번 폭을 읽게 돼. 하지만 타깃 노드가 트랙을 불러온 뒤 조건부로 나타난다면 그 effect는 너무 일찍 실행될 수 있어. 그때 ref.current는 null이고, effect는 빈 의존성 배열 때문에 노드가 나중에 붙어도 다시 실행되지 않아.

수정: callback ref와 대칭인 cleanup

callback ref는 노드가 실제로 붙을 때 실행되므로 조건부 DOM을 초기 측정하기에 알맞아. 이후 크기 변화까지 따라가려면 그 자리에서 ResizeObserver를 붙여. 여기서 setup만 쓰고 끝내면 또 다른 버그가 생겨. 노드가 떨어지거나 ref가 바뀔 때 observer를 끊어야 해. React 19는 ref callback이 cleanup 함수를 반환할 수 있으니 ro.disconnect()를 반환하면 attach와 detach가 대칭이 돼. Strict Mode의 추가 setup·cleanup 주기도 견딜 수 있어.

자매 레슨. 검증 이력은 우선순위를 바꿔

같은 엔진에서 세션 도중 소리가 멈춘 것처럼 보인 적도 있었어. 이미 검증한 scheduler 수학보다 transient state와 현재 신호 경로를 먼저 확인했고, 실제 원인도 reload 뒤 달라진 state였어. 여기서 얻을 규칙은 '검증된 코드는 다시 보지 마'가 아냐. 검증 이력은 의심 순위를 낮추지만 코드를 무죄로 만들지는 않아. 알려진 초기 상태에서 재현하고, 관찰 가능한 state를 확인하고, 증상이 어느 경계를 넘는지 격리한 뒤 수정해. 증거가 가리키면 검증했던 코드도 다시 보면 돼.

Code

useEffect + ref 말고 callback ref로 측정·typescript
// 틀림: mount effect가 조건부 노드보다 먼저 한 번만 돌아.
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
  setWidth(ref.current?.offsetWidth ?? 0);
}, []);

// React 19: attach 때 측정하고 detach 때 observer를 정리해.
const measureRef = useCallback((node: HTMLDivElement | null) => {
  if (!node) return;

  const measure = () => setWidth(node.offsetWidth);
  measure();

  const ro = new ResizeObserver(measure);
  ro.observe(node);

  return () => ro.disconnect();
}, []);

External links

Exercise

UI에서 mount할 때 측정하거나 초기화하지만 타깃이 아직 없을 수 있는 자리를 찾아 봐. 모달, 탭, 지연 로드 패널이 그런 예야. callback ref로 attach 때 측정하고, observer나 listener를 만들었다면 detach cleanup까지 써. Strict Mode에서 setup과 cleanup 횟수가 맞는지도 확인해.
Hint
'리사이즈나 리렌더 뒤에는 되는데 처음엔 깨진다'면 너무 일찍 읽었을 가능성이 커. 반대로 화면을 오갈수록 observer callback이 늘어난다면 cleanup이 빠진 거야. attach와 detach를 한 쌍으로 검사해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 피파warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.