본문 바로가기
React

[React] react 렌더링 방식 이해와 memoization

by spare8433 2025. 3. 16.

가상 DOM과 부분 렌더링 방식이해



가상 DOM의 작동 방식

  1. 가상 DOM 생성: 브라우저의 실제 DOM과 별개로 메모리에 가상 DOM 객체를 생성합니다.
  2. 상태 변화 감지: 데이터나 상태가 변경되면, 새로운 가상 DOM 트리가 생성됩니다.
  3. 차이점 계산(Diffing): 기존 가상 DOM과 새 가상 DOM을 비교하여 정확히 어떤 부분이 변경되었는지 파악합니다.
  4. 부분 업데이트(Reconciliation): 변경된 부분만 실제 DOM에 적용합니다.










랜더링 최적화의 필요성

상태가 변경됨에 따라 컴포넌트가 재렌더링되는 과정에서 하위 컴포넌트 역시 재렌더링 되어 일부 불필요한 렌더링이 발생할 수 있습니다.

예를 들어 Context APIContextstate 값이 변경되면, 해당 컴포넌트의 모든 자식 컴포넌트들도 기본적으로 재렌더링 과정을 거치게 됩니다.










React.memo

  • 컴포넌트의 불필요한 재렌더링 방지
  • props가 변경되지 않으면 해당 컴포넌트는 재렌더링하지 않습니다.
  • 자식 컴포넌트가 불필요하게 재렌더링되는 문제를 해결



// ✅ 올바른 사용법 1: 컴포넌트를 React.memo로 감싸는 방식
fuction MyComponent() {
  ...
}

or

const MyComponent = () => {
  ...
}

const MemoizedComponent = React.memo(MyComponent);

// ✅ 올바른 사용법 2: 화살표 함수와 React.memo를 함께 사용하는 방식
const MyComponent = React.memo(() => {
  ...
})

// ❌ 잘못된 사용법: 함수 선언문 안에서 React.memo 사용
React.memo(fuction MyComponent() {
  ...
})










useMemo

  • 값의 계산을 메모이제이션하여 불필요한 계산을 방지합니다.
  • 의존성 배열이 변경되지 않으면 동일한 값을 반환하여 성능을 최적화합니다.
const [name, setName] = useState('Kim');
const [age, setAge] = useState(30);

// name과 age가 변경될 때만 새 객체 생성
const userInfo = useMemo(() => {
  return { name, age, formattedAge: `${age}세` };
}, [name, age]);










useCallback

  • 컴포넌트 안에서 선언되는 함수는 재랜더링되는 과정에서 새로 선언되기 때문에 함수의 메모이제이션을 통해 불필요한 함수 재생성을 방지합니다.
  • useMemo와 유사하지만, 함수에 특화된 메모이제이션입니다.
import { useCallback, useState } from "react";

export default fuction useSwitch(defaultState: boolean): [boolean, () => void, () => void] => {
  const [isOn, setCurrentState] = useState(defaultState ?? false);

  const turnOn = useCallback(() => setCurrentState(true), []);
  const turnOff = useCallback(() => setCurrentState(false), []);

  return [isOn, turnOn, turnOff];
};










그외 알아두면 좋을만한 것

  • useState에서 setState는 React가 내부적으로 관리하는 함수이기 때문에, 함수 참조가 항상 동일하고, 리렌더링 시 상태 업데이트 함수 자체가 변경되지 않기 때문에 memoization을 고려할 필요가 없다 예를 들어 useCallback에서 setState를 사용한다고 해서 의존성 배열에 추가할 필요가 없다.
  • props 에 익명함수의 형태로 바로 전달할 경우 리렌더링 시마다 익명 함수가 새로 생성되므로, 리렌더링이 일어날 때마다 자식 컴포넌트의 리렌더링도 발생할 수 있습니다.
  • 배열이나 객체참조형 데이터이므로, 그 자체로 useState로 상태를 관리하면 참조가 유지됩니다. 따라서 해당 값이 변경되지 않는 한, 해당 참조를 사용하는 props로 전달되는 값은 불변입니다. 따라서 props 로 전달할 때 참조가 새로 적용되어 재렌더링되는 것을 걱정할 필요는 없다
  • children 역시 props의 일종으로 React.memo는 props가 변경되지 않으면 해당 컴포넌트의 리렌더링을 방지합니다. 이때 children이 변경되지 않으면, 해당 엘리먼트의 참조는 유지되고 리렌더링을 피할 수 있습니다.