useRef()
훅은 Reference
를 사용하기 위한 훅입니다. 리액트에서 레퍼런스란 특정 컴포넌트에 접근할 수 있는 객체를 의미합니다. useRef()
훅은 바로 이 레퍼런스 객체(ref object
)를 반환합니다. 레퍼런스 객체에는 .current
라는 속성이 들어있는데, 이것은 현재 레퍼런스하고 있는 element
를 의미한다고 보면 됩니다.
const refObject = useRef(초기값);
위와 같이 useRef()
훅을 사용하면 파라미터로 들어온 초기값(initial value
)으로 초기화 된 레퍼런스 객체를 반환합니다. 만약 초기값이 null
이라면 .current
의 값이 null
인 레퍼런스 객체가 반환되겠죠. 이렇게 반환된 레퍼런스 객체는 컴포넌트의 라이프타임 전체에 걸쳐서 유지됩니다. 즉, 컴포넌트가 마운트 해지되기 전까지는 계속 유지된다는 것이죠. 그래서 쉽게 생각하면 useRef()
훅은 변경 가능한 .current
라는 속성을 가진 하나의 상자라고 생각하면 됩니다.
아래 코드는 useRef()
훅을 사용하여 버튼 클릭시 <input>
에 포커스를 하도록 하는 코드입니다. 초기값으로 null
을 넣었고, 결과로 반환된 inputElemRef
라는 레퍼런스 객체를 <input>
태그에 넣어줬습니다. 그리고 버튼 클릭시 호출되는 함수에서 inputElemRef.current
를 통해 실제 element
에 접근하여 focus()
함수를 호출하고 있습니다.
function TextInputWithFocusButton(props) {
const inputElemRef = useRef(null);
const onButtonClick = () => {
// `current`는 마운트된 input element를 가리킴
inputElemRef.current.focus();
};
return (
<>
<input ref={inputElemRef} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
이전에 웹사이트 개발을 접해본 분들은 레퍼런스라고 하면 DOM에 접근하기 위해 사용하는 ref
속성에 익숙할 수도 있습니다. 비슷하게 리액트에서는 <input ref={inputElemRef} />
라고 코드를 작성하면, node가 변경될 때마다 inputElemRef
의 .current
속성에 현재 해당되는 DOM node
를 저장합니다.
ref
속성과 기능은 비슷하지만 useRef()
훅은 클래스의 인스턴스 필드를 사용하는 것과 유사하게 다양한 변수들을 저장할 수 있다는 장점이 있습니다. 이것이 가능한 이유는 useRef()
훅은 일반적인 자바스크립트 객체를 리턴하기 때문입니다. 그럼 '내가 직접 .current
속성이 포함된 자바스크립트 객체를 만들어서 써도 되는것 아닌가?' 라고 생각하실 수도 있습니다. 물론 그렇게 해도 목적은 달성할 수 있습니다만, useRef()
훅을 사용하는 것과 직접 { current: ... }
모양의 객체를 만들어서 사용하는 것의 차이점은 useRef()
훅은 매번 렌더링 될 때마다 항상 같은 ref 객체를 반환한다는 것입니다.
한 가지 기억해야할 점은 useRef()
훅은 내부의 데이터가 변경되었을 때 별도로 알리지 않는다는 점입니다. .current
속성을 변경하는 것은 재렌더링을 일으키지 않습니다. 그래서 ref
에 DOM node
가 attach
되거나 detach
되었을 경우에 어떤 코드를 실행하고 싶다면 대신 callback ref
를 사용해야 합니다.
NOTE. DOM node의 변화를 어떻게 캐치해야 할까요? (callback ref 사용하기)
DOM node
의 변화를 캐치하기 위한 가장 기초적인 방법으로는callback ref
를 사용하는 것이 있습니다. 리액트는ref
가 다른node
에attach
될 때마다callback
을 호출하게 됩니다. 아래 예제 코드를 한 번 보도록 하겠습니다.
function MeasureExample(props) { const [height, setHeight] = useState(0); const measuredRef = useCallback(node => { if (node !== null) { setHeight(node.getBoundingClientRect().height); } }, []); return ( <> <h1 ref={measuredRef}>안녕, 리액트</h1> <h2>위 헤더의 높이는 {Math.round(height)}px 입니다.</h2> </> ); }
위 코드에서는 레퍼런스를 위해서
useRef()
훅을 사용하지 않고useCallback()
훅을 사용하는 callback ref 방식을 사용했습니다.useRef()
훅을 사용하게 되면 레퍼런스 객체가.current
속성이 변경되었는지를 따로 알려주지 않기 때문이죠. 하지만 callback ref 방식을 사용하게 되면 자식 컴포넌트가 변경되었을 때 알림을 받을 수 있고, 이를 통해 다른 정보들을 업데이트 할 수 있습니다. 이 예제 코드에서는<h1>
태그의 높이값을 매번 업데이트 하고 있습니다.그리고
useCallback()
훅의 의존성 배열로 비어있는 배열(empty array)을 넣었는데, 이렇게 하면<h1>
태그가mount
,unmount
될 때만callback
함수가 호출되며, 재렌더링이 일어날 때는 호출되지 않습니다.
마지막 업데이트: 2025년 08월 27일 01시 55분
이 문서의 저작권은 이인제(소플)에 있습니다. 무단 전재와 무단 복제를 금합니다.
On this page