forwardRef기본 ref를 비교하며, 이들 간의 근본적인 차이를 이해하고, 이 차이로 인해 생기는 성능 이슈를 useImperativeHandle과 관련하여 설명하겠습니다.


🔍 질문의 목적

  1. forwardRef와 기본 ref(useRef 등)는 어떤 근본적 차이를 가지는가?
  2. forwardRef를 사용할 때 useImperativeHandle과 함께라면, ref의 변경이 발생했을 때 불필요한 부수효과(side-effect)가 발생할 수 있는가?
  3. 있다면, 어떤 상황에서 발생하는지 명확한 예시로 설명해 달라.

이 질문을 이해하기 위해 기본 ref vs forwardRef 의 차이를 먼저 명확하게 정리하겠습니다.


📌 기본 ref vs forwardRef (근본적 차이점 비교)

구분 기본 ref (useRef 등) forwardRef
정의 컴포넌트 내부에서 직접 DOM 엘리먼트나 변수 저장 용도로 사용됨 부모 컴포넌트에서 자식 컴포넌트의 DOM 또는 내부 메서드에 접근할 때 사용됨
역할 DOM 엘리먼트의 직접 접근 또는 상태 유지 부모로부터 전달된 ref 객체를 컴포넌트 내부에서 연결 (중계 역할)
사용위치 컴포넌트 내부에서만 정의되고 사용 자식 컴포넌트 정의 시 부모로부터 ref 객체를 전달받아 사용
사용방법 <div ref={ref}> forwardRef((props, ref) => ...)

즉, forwardRef는 부모가 자식 컴포넌트의 내부 DOM에 접근하거나, 메서드를 호출할 때 사용되며, ref를 부모로부터 전달받아 내부적으로 사용하기 위한 React의 특수 API입니다.


🧩 forwardRef와 useImperativeHandle 사용 시 성능 문제 발생 가능성

forwardRefuseImperativeHandle을 같이 쓰면 다음 상황에서 성능 이슈가 발생할 수 있습니다:

왜냐하면 useImperativeHandle은 컴포넌트가 렌더링될 때마다 ref에 할당할 객체를 새로 만들기 때문입니다. 즉, 매 렌더링마다 ref 객체의 identity(정체성)가 바뀌면 불필요한 부수효과가 발생할 수 있습니다.


🚨 불필요한 부수효과가 발생하는 예시

❌ 문제 코드 (불필요한 ref 업데이트)