useRef 가 세 가지 함. 각 flavor 마다 자기 근육 기억. 셋을 혼동하는 곳에 버그 살아.
Flavor 1 — DOM node 핸들
Ref 만들고 ref attribute 로 JSX element 에 넘김, 마운트 후 ref 의 .current 가 실제 DOM node 가리킴. 이벤트 핸들러 + effect 에서 DOM 메서드 읽기/호출. 가장 흔한 케이스: 마운트 시 input focus.
Flavor 2 — render-stable mutable storage
Render 간에 살아남되 바뀌어도 re-render 트리거 안 하는 값 필요. 흔한 사용: render 간 타이머 id 캐싱, 이전 prop 값 추적, websocket 연결 저장. 모양 동일 (useRef(initial)) 인데 .current 직접 read/write — setter 없음, re-render 없음.
Flavor 3 — callback ref
가끔 ref 값만 원하는 게 아니라 node 가 attach/detach 될 때 반응 하고 싶음. Ref object 대신 함수를 ref 로 넘김. React 가 attach 시 node 와, detach 시 null 과 함께 호출. 이게 IntersectionObserver, ResizeObserver, 또는 라이프사이클 알아야 하는 서드파티 라이브러리 연결 방식.
중요한 구분
State 는 render 구동. Ref 는 안 함. 값 변경이 UI re-render 해야 하면 state. Render 안 하지만 render 간 기억 필요하면 ref. 값의 job 에 맞는 쪽 골라.
Render 중 .current 읽지 마. React 가 render 중에
.current 에 뭐 있을지 보장 안 함 — DOM ref 는 첫 render 에 null (node 아직 마운트 안 됨), render 중 mutable ref 읽기는 비결정적. 항상 이벤트 핸들러, effect, 또는 `useImperativeHandle` 안에서 읽어.