본문 바로가기

React/개념

React useRef vs useState 차이점 정리 | 리렌더링과 값 유지의 원리

728x90

 

React에서 값을 저장할 때 let 변수, useState, useRef 중 무엇을 사용해야 할까?

이 글에서는 다음 세 가지를 명확히 정리한다.

  • 왜 컴포넌트 내부에 선언된 let 변수는 리렌더링 시 초기화되는가
  • useState와 useRef는 왜 값이 유지되는가
  • useState와 useRef의 근본적인 차이

1. 리렌더링과 함수 재실행

React 컴포넌트는 함수이다.

function Register() {
  let count = 0;
  return <div />;
}

 

상태가 변경되면 해당 컴포넌트 함수는 다시 실행된다.

따라서 함수 내부의 let 변수는 렌더링마다 다시 선언되고 초기화된다.

  • let count 변수 → 렌더링마다 초기화
  • 렌더링과 독립적인 저장 공간이 아님

2. useState와 useRef가 값이 유지되는 이유

const [count, setCount] = useState(0);
const countRef = useRef(0);

 

이 코드도 렌더링마다 실행된다. 하지만 값은 유지된다.

 

이유는 useState와 useRef가 React 내부 저장소(Fiber)에 연결되기 때문이다.

이건 다음 포스트에서 살펴볼 예정~

 

 

React는 컴포넌트 인스턴스마다 훅 데이터를 별도로 관리한다.

따라서:

  • 컴포넌트가 다시 실행되어도
  • React가 이전 값을 그대로 반환한다

중요한 개념:

리렌더링은 함수를 다시 실행하는 것이지, React의 훅 저장소를 초기화하는 것이 아니다.

3. 파일 전역 변수와의 차이

// 파일 전역
let count = 0;

 

예를들어서 Register 컴포넌트에서는 위에 전역 변수 count를 공유해서 사용한다고 해보자.

이 경우 값은 유지되지만 문제가 있다.

 

<Register />
<Register />

 

두 개의 Register 컴포넌트가 같은 count를 공유하게 된다. 각각의 컴포넌트 마다 독립된 그 누적 count를 사용하고자 선언했지만 예기치 못한 상황이 발생되는 것임.

 

그러나!

useState와 useRef는 컴포넌트 인스턴스별로 저장 공간이 분리된다.

 

방식 저장 위치 인스턴스 분리
파일 전역 let JS 모듈 스코프 ❌ 공유됨
useState React Fiber ✅ 분리됨
useRef React Fiber ✅ 분리됨

 


4. useState와 useRef의 근본적인 차이

useState

setCount(prev => prev + 1);
  • 값 변경 시 리렌더링 발생
  • UI 자동 업데이트
  • 화면에 반영되는 상태 관리용

상태가 무엇일까.. 말그대로 상태다.

 

상태(state)가 변하면 -> React가 감지한다. -> 해당 state의 컴포넌트(함수)를 다시 실행한다 -> 화면이 업데이트되어 다시 그려진다.

 

어디에 활용할 수 있을까?

 

function Game() {
  const [hp, setHp] = useState(100);

  return (
    <div>
      <h1>HP: {hp}</h1>
      <button onClick={() => setHp(hp - 10)}>공격 받기</button>
    </div>
  );
}

 

예를들어 버튼을 누를 때마다 체력이 깎이는 상황을 만들 수 있는데, 버튼을 누를 때 state가 변경됨으로 hp가 계속해서 줄어드는 그런 새로운 UI를 볼 수 있다.

 

간단하다. "이벤트"에 따라서 새로운 UI를 그린다.

여기서의 이벤트는 공격 받기 이벤트다.

 

function Light() {
  const [isOn, setIsOn] = useState(false);

  return (
    <div>
      <h1>{isOn ? "💡 켜짐" : "🌑 꺼짐"}</h1>
      <button onClick={() => setIsOn(!isOn)}>
        스위치 누르기
      </button>
    </div>
  );
}

 

전구에서 전등을 예로들 수 있다.

스위치를 누르면, 전구가 켜지는 UI를 보여줄 수 있고, 꺼지면 전구가 꺼진 UI를 화면에 보여줄 수 있다.

 

1. 처음에 false (꺼짐)

2. 버튼 클릭(이벤트 발생 !!!!! )

3. setIsOn(true) -> state(isOn) 는 true가 됨

4. React가 변화된 state를 감지해서 자동으로 다시 그림(리렌더링)

5. 화면이 켜짐UI로 변경

 

useRef

countRef.current += 1;
  • 값 변경 시 리렌더링 없음
  • UI 자동 반영 없음
  • 렌더와 무관한 값 저장

5. useRef의 주요 사용 사례

1) 렌더와 무관한 값 저장

  • 수정 횟수 기록
  • 이전 값 보관
  • 타이머 ID 저장
  • 스크롤 위치 저장

 

2) DOM 요소 직접 참조

const inputRef = useRef(null);

<input ref={inputRef} />

inputRef.current.focus();

 

useRef는 실제 DOM 노드를 직접 제어할 수 있는 통로를 제공한다.


결론

  • let 변수는 리렌더링 시 초기화된다.
  • useState와 useRef는 React 내부 저장소에 연결된다.
  • useState는 UI 상태를 위한 도구이다.
  • useRef는 리렌더와 무관한 값 및 DOM 제어용 도구이다.
728x90