2 minute read

useRefuseEffect 의 의존성 진단

커스텀 훅에서만 나타나는 exhaustive-deps 경고의 기술적 배경

문제 제기

동일한 ref 객체를 사용하는 두 시나리오가 있다.

  1. 컴포넌트 내부에서 직접 useRef() 호출
  2. 커스텀 훅useRef() 결과를 반환

두 경우 모두 런타임 동작은 같지만, ESLint 규칙 react-hooks/exhaustive-deps 는 두 번째 패턴에만 “의존성 배열에 ref를 추가하라”는 경고를 띄운다. 왜 그럴까?


1. React 런타임: useRef 객체의 안정성(Stable Identity)

useRef() 는 최초 렌더에서 단 한 번 { current } 객체를 생성하며, 이후 렌더에서도 같은 객체 참조를 재사용한다. React 공식 문서는 이를 명시적으로 보장한다. (stackoverflow.com)

function Comp() {
  const boxRef = useRef<HTMLDivElement>(null); // 항상 동일한 객체
  /* … */
}

결과

  • 의존성 배열이 [][boxRef]든, 객체 참조(식별자)가 변하지 않으므로 useEffect추가 실행되지 않는다.
  • 개발용 Strict Mode 에서는 의도적으로 초기 렌더가 두 번 일어나므로, 두 번 모두 마운트·언마운트 효과가 호출된다.

2. exhaustive-deps 규칙: 정적 분석의 한계

eslint-plugin-react-hooks 는 컴파일 타임에 소스 코드를 스캔하며, 내부적으로 “안정 반환값(Stable Return Value) 화이트리스트” 를 유지한다.

SAFE_RETURNS = { useRef, useState, useReducer, … }
  • 컴포넌트 내부에서 직접 호출된 훅이 이 목록에 포함되면, 해당 변수는 자동으로 안정하다고 간주되어 의존성 배열 생략이 허용된다.
  • 커스텀 훅은 함수 본문을 열어볼 수 없는 블랙박스다. 정적 분석 도구는 해당 훅이 매번 다른 객체를 생성할 가능성을 배제할 수 없으므로, 보수적 전략을 취해 경고를 출력한다. 이 설계 원칙은 GitHub 이슈에서도 확인할 수 있다. (github.com, github.com)

즉, 문제의 근원은 런타임 보증정적 분석 힌트 간의 정보 비대칭에 있다.


3. 런타임 비교: [] vs [ref]

의존성 배열 재실행 조건 프로덕션 기준 실행 횟수*
[] 조건 없음 1회
[ref] ref 객체 참조가 바뀔 때만 객체가 불변 ⇒ 1회

* React Strict Mode(개발 환경)에서는 의도적으로 +1회

ref.current 값은 mutable 하므로 의존성에 넣어도 변경을 감지하지 않는다. 값 변화를 트래킹하려면 useState, useSyncExternalStore, 콜백 ref 등 별도 패턴을 사용해야 한다.


4. 실무 대응 전략

방법 구현 예 장점 / 고려 사항
ref를 배열에 추가 useEffect(fn, [myRef]); ref 식별자는 불변 → 실행 1회, 경고 해소
effect를 훅 내부로 이동 useFocusRef() 내부에서 useEffect 실행 컴포넌트 코드 간결, 경고 자체 제거
ESLint 무시 주석 // eslint-disable-next-line react-hooks/exhaustive-deps 최후 수단. 유지보수 리스크 존재
커스텀 훅을 ‘안정 훅’으로 등록(포크) 포크된 exhaustive-deps 플러그인 사용 공식 규칙엔 미지원; 팀 규모에 따라 검토 (reddit.com)

5. 결론

  1. React 런타임useRef 반환 객체의 식별자 불변을 보증한다.
  2. exhaustive-deps 규칙은 내장 훅만 안정 값으로 취급하고, 커스텀 훅은 잠재적 변동 값으로 가정한다.
  3. 결과적으로 [ref]를 넣든 []로 두든 실행 횟수는 동일하지만, 정적 분석 경고는 커스텀 훅에서만 노출된다.
  4. 경고를 제거하려면 ref를 배열에 추가하거나 effect를 훅 내부로 옮기는 방식이 가장 안전하고 유지보수에 우호적이다.

런타임 보증과 정적 분석 간의 시각 차이를 이해하면 “왜 나만 경고를 보는지” 혼란스러울 이유가 사라진다. 프로젝트 규칙에 맞추어 의존성 배열을 조정하거나 훅 설계를 재구성하면 깔끔하게 해결된다. Happy Hooking! 🪝


EOD

20250612

Tags:

Categories:

Updated:

Leave a comment