01 · Concept

useRef

useRef는 렌더링 사이에 값을 유지하면서도 리렌더링을 트리거하지 않는 React 훅입니다.

useRef .current 속성을 가진 가변 객체를 반환합니다. DOM 요소에 직접 접근하거나, 타이머 ID, 이전 렌더링 값 등 리렌더링과 무관한 값을 저장할 때 사용합니다. useState와 달리 값을 변경해도 컴포넌트가 다시 렌더링되지 않습니다.

02 · Interactive Demo

useRef vs useState 비교

값 변경 시 리렌더링 여부와 DOM 참조, 이전 값 저장을 직접 확인하세요.

useRef는 값이 변경되어도 리렌더링을 트리거하지 않습니다.
function Counter() {
  const [stateCount, setStateCount] = useState(0);
  const refCount = useRef(0);

  const handleState = () => {
    setStateCount(c => c + 1);  // 리렌더링 O
  };

  const handleRef = () => {
    refCount.current += 1;       // 리렌더링 X
    console.log(refCount.current);
  };

  console.log('렌더링 발생!');
  return (/* ... */);
}
Value Comparison
useState
0
useRef
0
렌더링 횟수: 0
리렌더링 없음
03 · Code Example

코드 예시

실제 코드로 동작 원리를 확인하세요.

import { useRef, useEffect } from 'react';

function VideoPlayer() {
  const videoRef = useRef(null);

  const handlePlay = () => videoRef.current.play();
  const handlePause = () => videoRef.current.pause();

  return (
    <div>
      <video ref={videoRef} src="/video.mp4" />
      <button onClick={handlePlay}>재생</button>
      <button onClick={handlePause}>일시정지</button>
    </div>
  );
}

// 여러 요소에 ref 배열 사용
function ItemList({ items }) {
  const itemsRef = useRef(new Map());

  const scrollToItem = (id) => {
    itemsRef.current.get(id)?.scrollIntoView({
      behavior: 'smooth', block: 'nearest'
    });
  };

  return items.map(item => (
    <div key={item.id}
      ref={(node) => {
        if (node) itemsRef.current.set(item.id, node);
        else itemsRef.current.delete(item.id);
      }}
    >
      {item.name}
    </div>
  ));
}
04 · Interview Point

면접 핵심 질문

useRef { current: initialValue } 객체를 반환합니다. 이 객체는 컴포넌트의 전체 생명주기 동안 유지되며,.current 속성을 변경해도 리렌더링이 발생하지 않습니다. React는 매 렌더링마다 동일한 ref 객체를 반환하므로, 렌더링 사이에 값을 유지하는 데 적합합니다.
useState: 값 변경 시 리렌더링을 트리거합니다. UI에 표시되는 상태에 사용합니다. useRef: 값 변경 시 리렌더링이 발생하지 않습니다. DOM 참조, 타이머 ID, 이전 값 저장 등 렌더링과 무관한 값을 관리할 때 사용합니다.

핵심 차이: useState의 setter는 비동기적으로 상태를 업데이트하고 리렌더링을 예약하지만,useRef.current 변경은 즉시 반영되며 리렌더링하지 않습니다.
1. DOM 요소 접근 — input 포커스, 스크롤, 비디오 제어 등 2. 타이머/인터벌 ID 저장 — clearInterval/clearTimeout에 필요한 ID 3. 이전 렌더링 값 저장 — usePrevious 커스텀 훅 4. 렌더링과 무관한 가변 값 — 마운트 여부 추적, 렌더 횟수 카운팅 5. 외부 라이브러리 인스턴스 저장 — 차트, 맵 등의 인스턴스 참조