React 컴포넌트에서 상태를 기억하고 싶지만, 그 정보가 렌더링을 트리거하지 않기를 원할 때 사용하는 도구가 useRef다. useRef는 렌더링과 무관한 정보를 저장할 수 있는 ref 객체를 반환하며, 이 값은 ref.current를 통해 접근할 수 있다. ref는 상태처럼 정보를 저장할 수 있지만, 중요한 차이점은 ref는 변경되어도 리렌더링을 트리거하지 않는다는 점이다.
useRef의 기본 개념
useRef는 상태와 달리, 값을 읽고 쓰는 데 있어서 자유롭다. ref 객체는 mutable하므로 값을 즉시 변경할 수 있으며, 이는 React에서 추적되지 않는다. 따라서 ref는 React가 렌더링 사이클을 관리하는 것과는 별개로 작동한다. 예를 들어, ref는 숫자, 문자열, 객체, 함수 등 어떤 값이든 가리킬 수 있다.
const intervalRef = useRef(null);
위 코드는 intervalRef라는 ref를 선언하고, 그 초기값을 null로 설정한 것이다. useRef는 이 객체를 반환하며, 이 객체는 current라는 속성을 가진다. 이 속성은 원하는 대로 값을 읽고 쓸 수 있다.
useRef와 state의 차이점
useRef는 plain JavaScript object다. 이는 React가 관리하는 state와 달리, ref는 React의 렌더링 시스템과 독립적으로 동작한다는 의미다. ref의 current 값을 변경해도 리렌더링이 발생하지 않는다. 이러한 특성 덕분에 렌더링에 영향을 주지 않는 정보를 저장할 때 유용하다.
// React 내부 동작
function useRef(initialValue) {
const [ref, unused] = useState({ current: initialValue });
return ref;
}
위 코드는 useRef가 어떻게 동작하는지 보여준다. useRef는 초기값을 받아 { current: initialValue } 형태의 객체를 반환한다. 이 객체는 React가 렌더링 중에 저장하며, 다음 렌더링에서도 동일한 객체를 반환한다. state setter는 사용되지 않으며, 이는 useRef가 항상 동일한 객체를 반환하기 때문이다.
useRef의 주된 사용법
리렌더링이 필요하지 않은 정보
렌더링에 사용되는 정보는 state에 저장해야 하지만, 렌더링과 관계없이 동작하는 정보는 ref에 저장하는 것이 더 효율적이다. 예를 들어, setInterval에서 반환되는 interval ID는 렌더링과 무관하기 때문에 ref에 저장하는 것이 좋다.
const intervalIdRef = useRef(null);
// setInterval을 설정하고 ref에 interval ID 저장
useEffect(() => {
intervalIdRef.current = setInterval(() => {
console.log('Interval running...');
}, 1000);
// 컴포넌트가 언마운트될 때 interval을 정리
return () => clearInterval(intervalIdRef.current);
}, []);
위 코드에서는 intervalIdRef에 setInterval에서 반환된 ID를 저장하고, 컴포넌트가 언마운트될 때 이를 정리하는 방식으로 useRef를 사용했다. 이처럼 렌더링과 무관한 값을 관리할 때 ref를 사용하면 불필요한 리렌더링을 방지할 수 있다.
DOM 요소 접근
useRef의 가장 흔한 사용 사례는 DOM 요소에 접근하는 것이다. 예를 들어, 사용자가 입력한 값을 DOM 요소에서 직접 가져오거나, 포커스를 제어할 때 ref를 사용할 수 있다.
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus(); // 버튼 클릭 시 input에 포커스 설정
}
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleClick}>포커스 이동</button>
</div>
);
위 코드에서는 inputRef를 통해 input 요소에 접근하고, 버튼 클릭 시 inputRef.current.focus()를 호출하여 해당 요소에 포커스를 설정한다. 이처럼 DOM 요소에 직접 접근할 때 ref를 사용하는 것이 유용하다.
useRef 사용 시 주의사항
useRef를 사용할 때는 지켜야 할 몇 가지 주의사항이 있다.
- 렌더링 중에 ref를 읽거나 쓰지 말 것
useRef는 렌더링과 무관한 값을 저장하는 용도이므로, 렌더링 중에 ref.current 값을 읽거나 수정하는 것은 적절하지 않다. 렌더링 중에 필요한 값은 반드시 state에 저장해야 한다. - ref는 즉시 변경된다
ref의 current 값은 즉시 변경되며, 이는 state처럼 비동기로 처리되지 않는다. 따라서 ref의 값을 변경하면 그 값은 즉시 적용된다.
결론
useRef는 React 컴포넌트에서 리렌더링 없이 정보를 기억하거나 DOM 요소에 접근할 때 매우 유용한 도구다. ref는 렌더링 사이클과 독립적으로 동작하기 때문에, 렌더링에 영향을 주지 않는 정보를 저장하는 데 최적이다. 렌더링에 필요한 정보는 state에, 그렇지 않은 정보는 ref에 저장하는 것이 React 애플리케이션의 성능을 최적화하는 방법이다. DOM 접근, 이벤트 핸들러에서 필요한 값, 그리고 외부 API와의 상호작용에서 ref를 적절히 활용하면 코드의 효율성과 유지보수성을 높일 수 있다.
'React' 카테고리의 다른 글
React Hook을 사용할 때 실수들 (1): useState (1) | 2024.09.10 |
---|---|
React Hook 이해하기 (4): useMemo, useCallback (0) | 2024.09.10 |
React Hook 이해하기 (2): useEffect (0) | 2024.09.10 |
React Hook 이해하기 (1): useState (0) | 2024.09.10 |
React에서의 Event Handler (0) | 2024.09.10 |