
React – 상태 관리와 Hooks – 기본 Hooks – 2 – useRef로 DOM 제어 및 값 보존
안녕하세요! 😊
오늘은 React에서 아주 유용하게 사용되는 useRef
에 대해 깊이 있게 알아보려 해요.
이 친구는 조금 낯설지만, 알고 보면 정말 똑똑하고 다양한 상황에서 활용할 수 있는 “비밀 무기” 같은 존재랍니다!
우리가 흔히 생각하는 “ref = DOM 제어용”이라는 인식도 맞지만, 그보다 훨~씬 많은 일을 할 수 있어요.
그럼 함께 차근차근 살펴볼까요?
1. useRef란 무엇인가요?
useRef
는 말 그대로 “참조(ref)”를 의미합니다.
React에서 DOM 요소나 특정 값을 기억하고 참조하기 위한 객체를 만들 때 사용돼요.
const myRef = useRef(초기값);
myRef.current
를 통해 실제 값을 읽거나 쓸 수 있습니다.- 이 값은 렌더링 사이에서도 유지됩니다!
- 하지만 값이 바뀌어도 리렌더링이 발생하지 않아요!
2. DOM 요소에 접근할 때
가장 기본적인 용도는 HTML DOM에 직접 접근할 때예요.
예전 class 컴포넌트의 ref
속성을 함수형 컴포넌트에서도 사용 가능하게 해줍니다.
예제: 포커스 주기
import { useRef } from 'react';
function InputFocus() {
const inputRef = useRef(null);
const handleClick = () => {
inputRef.current.focus(); // DOM 요소에 직접 접근
};
return (
<div>
<input ref={inputRef} type="text" placeholder="입력하세요" />
<button onClick={handleClick}>포커스 주기</button>
</div>
);
}
🧠 비유하자면?
useRef
는 마치 “리모컨” 같아요.
버튼 하나로 특정 요소를 직접 조작할 수 있죠!
CSS나 이벤트로 안 되는 직접적인 동작 제어에 아주 유용하답니다.
3. 값 보존용 useRef
useRef
는 꼭 DOM 요소가 아니라, 리렌더링을 막으면서 어떤 값을 기억하고 싶을 때도 사용할 수 있어요.
예제: 이전 값 기억하기
import { useState, useEffect, useRef } from 'react';
function PreviousCounter() {
const [count, setCount] = useState(0);
const prevCountRef = useRef();
useEffect(() => {
prevCountRef.current = count;
}, [count]);
return (
<div>
<p>현재 값: {count}</p>
<p>이전 값: {prevCountRef.current}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
prevCountRef.current
는 렌더 사이클이 바뀌어도 유지되므로 값 추적에 매우 유용해요.- 일반 변수로는 안 되는 일이죠!
4. useRef vs useState 차이점
항목 | useState | useRef |
---|---|---|
렌더링 유발 | 값 변경 시 리렌더링 발생 | ❌ 발생하지 않음 |
값 유지 | ✅ 가능 | ✅ 가능 |
DOM 접근 | ❌ 불가능 | ✅ 가능 |
비동기 값 저장 | ⚠️ 제한 있음 | ✅ 유용함 |
즉, 렌더링 없이 값을 저장하거나 DOM 직접 제어하고 싶을 때는 useRef
가 훨씬 적합해요!
5. 실전 예제: 딜레이 버튼 연속 클릭 방지
function PreventDoubleClick() {
const isClickedRef = useRef(false);
const handleClick = () => {
if (isClickedRef.current) {
alert('잠시 기다려주세요!');
return;
}
isClickedRef.current = true;
alert('처리 중...');
setTimeout(() => {
isClickedRef.current = false;
}, 2000);
};
return <button onClick={handleClick}>제출</button>;
}
- 렌더링 없이 내부 상태를 기억하는 데 딱 좋아요!
useState
로 하면 버튼 누를 때마다 렌더링이 발생할 거예요.
6. useRef의 자주 쓰이는 상황
상황 | 설명 |
---|---|
input 등 DOM 제어 | 포커스, 선택, 스크롤 등 직접 조작 |
이전 값 기억 | 이전 상태와 비교 |
타이머/인터벌 ID 저장 | clearTimeout 등을 위해 참조 필요 |
렌더링 없이 플래그 유지 | 비동기 요청 중 여부, 초기 렌더 여부 등 |
canvas, audio 등 직접 접근 | DOM 객체 조작에 꼭 필요함 |
7. 의외로 중요한 사용법: setInterval
과 함께 쓰기
function Timer() {
const countRef = useRef(0);
useEffect(() => {
const intervalId = setInterval(() => {
countRef.current += 1;
console.log('현재 카운트:', countRef.current);
}, 1000);
return () => clearInterval(intervalId);
}, []);
return <p>콘솔을 확인해보세요!</p>;
}
setInterval
내부는 클로저라서 기존 값만 기억해요.useRef
를 사용하면 항상 최신 값을 저장하고 접근할 수 있어요.
8. 자주 하는 실수와 주의사항
실수 | 설명 | 해결 방법 |
---|---|---|
ref.current 에 직접 값을 할당 안 함 |
ref = null 상태 유지 |
ref.current = 값 꼭 설정 |
useRef 를 useState 처럼 사용 |
값 바뀌어도 화면이 안 바뀜 | UI 갱신 필요하면 useState 사용 |
렌더링 관련 값 보존 | 리렌더링 의도인데 ref 사용 | 이럴 땐 useState 또는 useMemo 고려 |
이벤트 핸들러 안에서 ref.current 값 의존 |
초기값만 기억할 수 있음 | 최신값 유지하려면 useRef 에 계속 할당 |
마무리하며
useRef
는 초보자에게는 조금 낯설 수 있지만, 컴포넌트의 동작을 유연하게 제어하는 강력한 도구입니다.
특히 렌더링 없이 어떤 값이나 DOM을 제어하고 싶을 때, useRef
를 적극적으로 활용해보세요!
✅ 핵심 정리
useRef
는
- DOM 직접 접근,
- 값 보존 (렌더링 없음),
- 타이머, 이전 값, 상태 플래그 등 관리에 유용한 훅입니다!
앞으로 useRef
와 함께 useEffect
, useCallback
등을 조합하면 더 복잡하고 강력한 컴포넌트를 만들 수 있어요!
다음 시간에는 성능 최적화를 위한 훅들 (useMemo, useCallback) 도 소개해드릴게요.
함께 꾸준히 연습하면서 React 마스터에 한 걸음 더 다가가 봅시다! 🚀💪