프로그래밍/ReactJS

React 애플리케이션 최적화의 비밀: `React.memo` 완벽 활용 가이드

shimdh 2025. 10. 1. 09:08
728x90

React 애플리케이션의 성능은 사용자 경험에 직접적인 영향을 미칩니다. 특히 애플리케이션이 복잡해지고 규모가 커질수록, 불필요한 렌더링은 성능 저하의 주범이 됩니다. 이러한 문제를 해결하기 위한 효과적인 도구 중 하나가 바로 React의 내장 함수인 React.memo입니다.

오늘은 React.memo가 무엇인지, 어떻게 작동하는지, 그리고 언제 사용해야 하고 언제 피해야 하는지에 대해 심층적으로 알아보겠습니다. 🚀


728x90

1. React.memo란 무엇인가요?

React.memo는 함수형 컴포넌트를 위한 고차 컴포넌트(Higher-Order Component, HOC) 입니다. 이 함수는 컴포넌트의 props를 기반으로 렌더링된 출력을 "메모이제이션(memoize)" 합니다.

쉽게 말해, 부모 컴포넌트가 리렌더링될 때 자식 컴포넌트의 props가 변경되지 않았다면, React는 해당 자식 컴포넌트의 렌더링을 건너뛰어 시간과 계산 자원을 절약합니다.

이러한 최적화 기법은 다음과 같은 상황에서 특히 유용합니다:

  • 자주 렌더링되는 컴포넌트
  • 복잡한 계산 또는 대규모 데이터 세트를 처리하여 렌더링 비용이 많이 드는 컴포넌트

불필요한 렌더링을 줄임으로써 애플리케이션의 반응성을 높이고, 전반적인 사용자 경험을 크게 개선할 수 있습니다.


2. React.memo는 어떻게 작동하나요?

React.memo로 함수형 컴포넌트를 감싸면, React는 이전 props와 새로운 props를 "얕게 비교(shallow comparison)" 합니다.

  • props가 동일하다면: React는 렌더링을 건너뛰고 이전 렌더링 결과를 재사용하여 성능을 최적화합니다.
  • props가 다르다면: 컴포넌트의 리렌더링을 트리거하여 새로운 props에 맞춰 컴포넌트를 다시 렌더링합니다.

이러한 동작 방식을 이해하는 것은 React.memo를 언제 적용해야 할지 결정하는 데 매우 중요합니다. 불필요한 메모이제이션은 오히려 오버헤드를 발생시킬 수 있으므로 신중한 적용이 필요합니다.


3. 실제 예시: Counter와 Display 컴포넌트

다음 예시를 통해 React.memo가 어떻게 성능을 최적화하는지 살펴보겠습니다. Counter (부모) 컴포넌트와 Display (자식) 컴포넌트를 사용합니다.

import React, { useState } from 'react';

// 자식 컴포넌트: React.memo로 감싸서 최적화
const Display = React.memo(({ count }) => {
  console.log("Rendering Display");
  return <h1>{count}</h1>;
});

// 부모 컴포넌트
const Counter = () => {
  const [count, setCount] = useState(0);
  const [otherState, setOtherState] = useState(false); // Display에 전달되지 않는 상태

  return (
    <div>
      <Display count={count} />
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setOtherState(!otherState)}>
        Toggle Other State
      </button>
    </div>
  );
};

export default Counter;

이 예시의 핵심은 다음과 같습니다:

  • Display 컴포넌트는 count라는 prop을 받습니다.
  • "Increment" 버튼을 클릭하면 count 상태가 변경되고 Display 컴포넌트가 리렌더링됩니다.
  • "Toggle Other State" 버튼을 클릭하면 otherState만 변경되고 count 값은 변하지 않습니다.

Display 컴포넌트를 React.memo로 감싸기 전에는 "Toggle Other State" 버튼을 클릭할 때 CounterDisplay 두 컴포넌트 모두 리렌더링됩니다.

하지만 DisplayReact.memo로 감싸면, count prop이 변경될 때만 Display가 렌더링되도록 보장합니다. 이제 "Toggle Other State"를 클릭하면 부모 컴포넌트(Counter)만 리렌더링되고, 이미 메모이제이션된 자식 컴포넌트(Display)의 렌더링은 건너뛰는 것을 확인할 수 있습니다. console.log("Rendering Display") 메시지가 필요한 경우에만 출력되는 것을 통해 불필요한 작업이 줄어들어 성능이 향상되었음을 알 수 있습니다. 👍


4. 언제 React.memo를 사용하지 말아야 할까요?

React.memo는 강력한 도구지만, 무분별하게 과용해서는 안 됩니다. 다음은 React.memo 사용을 재고해야 할 몇 가지 상황입니다:

1. 간단한 컴포넌트

컴포넌트가 매우 빠르게 렌더링되거나 최소한의 로직만 포함하는 경우, 메모이제이션은 오히려 불필요한 오버헤드를 추가할 수 있습니다. 작은 컴포넌트의 리렌더링 비용은 매우 낮기 때문에, React.memoprops 비교 과정에서 발생하는 비용이 얻는 이점보다 클 수 있습니다.

2. 잦은 Prop 변경 (객체 및 함수)

동적인 객체함수를 props로 전달하여 자주 변경되는 경우, React.memo는 큰 이점을 제공하지 못합니다. JavaScript에서 객체와 함수는 참조 비교를 하기 때문에, 내용이 같더라도 참조가 다르면 항상 리렌더링을 유발할 수 있습니다.

이럴 때는 useCallback이나 useMemo와 같은 다른 React 훅을 함께 사용하여 props의 안정성을 확보하는 것이 중요합니다.

3. 개발 초기 단계

애플리케이션의 구조나 기능이 빈번하게 변경되는 개발 초기 단계에서는 메모이제이션 전략을 구현하기 전에 다른 최적화(예: 코드 분할, 이미지 최적화)에 집중하는 것이 더 효과적일 수 있습니다. 초기 단계에서 너무 많은 최적화를 시도하면 개발 속도를 저하시키고 코드의 복잡성을 증가시킬 수 있습니다.


결론

React.memo는 props 기반으로 함수형 컴포넌트의 불필요한 렌더링을 줄여 React 애플리케이션의 성능을 최적화하는 데 매우 유용한 도구입니다.

이 기능을 프로젝트 내에서 언제, 어떻게 적절하게 구현해야 하는지 이해하고 다른 최적화 전략(useCallback, useMemo 등)과 함께 활용한다면, 더 반응적이고 효율적이며 대규모 데이터 세트를 처리할 수 있는 애플리케이션을 만들 수 있을 것입니다.

적절한 위치에 React.memo를 적용함으로써, 여러분의 React 애플리케이션의 전반적인 성능과 사용자 경험을 크게 향상시킬 수 있을 것입니다. 현명하게 활용하여 최적화된 React 애플리케이션을 구축하세요!

728x90