icon안동민 개발노트

React.memo 소개


 React.memo는 함수형 컴포넌트의 성능을 최적화하기 위한 고차 컴포넌트(Higher-Order Component)입니다.

 이 기능을 사용하면 컴포넌트의 props가 변경되지 않았을 때 불필요한 리렌더링을 방지할 수 있습니다.

React.memo의 개념과 작동 원리

 React.memo는 컴포넌트를 메모이제이션합니다. 즉, 컴포넌트의 props가 변경되지 않았다면 마지막으로 렌더링된 결과를 재사용합니다.

 이는 특히 자주 리렌더링되는 대규모 컴포넌트 트리에서 유용합니다.

 사용법

import React from 'react';
 
const MyComponent = React.memo(function MyComponent(props) {
  // 컴포넌트 로직
});

React.memo 사용 예제

 다음은 React.memo를 사용하여 불필요한 리렌더링을 방지하는 예제입니다.

import React, { useState } from 'react';
 
const ExpensiveComponent = React.memo(function ExpensiveComponent({ data }) {
  console.log('ExpensiveComponent rendered');
  // 복잡한 계산 또는 렌더링 로직
  return <div>{/* 렌더링 결과 */}</div>;
});
 
function ParentComponent() {
  const [count, setCount] = useState(0);
  const [data] = useState({ value: 'some data' });
 
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment ({count})</button>
      <ExpensiveComponent data={data} />
    </div>
  );
}

 이 예제에서 ParentComponentcount 상태가 변경되어도 ExpensiveComponent는 리렌더링되지 않습니다.

 data prop이 변경되지 않았기 때문입니다.

customCompareFunction 구현과 활용

 React.memo의 두 번째 인자로 사용자 정의 비교 함수를 전달할 수 있습니다.

 이 함수는 이전 props와 새로운 props를 비교하여 리렌더링 여부를 결정합니다.

function areEqual(prevProps, nextProps) {
  // true를 반환하면 리렌더링을 건너뜁니다.
  // false를 반환하면 리렌더링을 수행합니다.
  return prevProps.value === nextProps.value;
}
 
const MemoizedComponent = React.memo(MyComponent, areEqual);

 이 기능은 복잡한 객체나 배열을 props로 전달할 때 유용합니다.

React.memo의 한계와 주의사항

  1.  얕은 비교의 한계 : React.memo는 기본적으로 props의 얕은 비교만 수행합니다. 객체나 배열을 props로 전달할 때 주의가 필요합니다.

  2.  함수 props 처리 : 인라인 함수를 props로 전달하면 매번 새로운 함수 참조가 생성되어 메모이제이션의 효과가 사라질 수 있습니다.

// 잘못된 사용 예
<MemoizedComponent onClick={() => console.log('Clicked')} />
 
// 올바른 사용 예 (useCallback과 함께 사용)
const handleClick = useCallback(() => console.log('Clicked'), []);
<MemoizedComponent onClick={handleClick} />
  1. 과도한 사용 : 모든 컴포넌트를 React.memo로 감싸는 것은 오히려 성능을 저하시킬 수 있습니다.

React.memo 사용 가이드라인

 사용해야 하는 경우

  1. 동일한 props로 자주 리렌더링되는 컴포넌트
  2. 렌더링 비용이 높은 컴포넌트
  3. 부모 컴포넌트가 자주 업데이트되는 경우

 사용을 피해야 하는 경우

  1. props가 자주 변경되는 컴포넌트
  2. 간단하고 렌더링 비용이 낮은 컴포넌트
  3. 항상 다른 props를 받는 컴포넌트

PureComponent와의 비교

 React.memo는 함수형 컴포넌트를 위한 것이며, PureComponent는 클래스 컴포넌트를 위한 것입니다. 둘 다 얕은 props 비교를 수행하여 불필요한 리렌더링을 방지합니다.

// 클래스 컴포넌트 (PureComponent)
class MyPureComponent extends React.PureComponent {
  render() {
    return <div>{this.props.value}</div>;
  }
}
 
// 함수형 컴포넌트 (React.memo)
const MyMemoComponent = React.memo(function MyComponent(props) {
  return <div>{props.value}</div>;
});

 주요 차이점

  1. React.memo는 props만 비교하지만, PureComponent는 state와 props 모두를 비교합니다.
  2. React.memo는 사용자 정의 비교 함수를 허용하지만, PureComponent는 그렇지 않습니다.

 React.memo는 함수형 컴포넌트의 성능을 최적화하는 강력한 도구입니다. 그러나 모든 상황에서 필요한 것은 아니며, 적절한 사용이 중요합니다. 컴포넌트의 특성과 애플리케이션의 요구사항을 고려하여 React.memo를 적용해야 합니다.

 성능 최적화는 항상 측정 가능한 문제에 대한 해결책이어야 합니다. React Developer Tools의 Profiler를 사용하여 실제 성능 병목을 식별하고, 그에 따라 React.memo를 적용하는 것이 좋습니다.

 마지막으로, React.memo는 props의 변경만을 감지합니다. 컴포넌트 내부에서 사용하는 context나 전역 상태의 변경은 감지하지 못합니다. 이러한 경우에는 추가적인 최적화 기법이 필요할 수 있습니다.

 React.memo를 효과적으로 사용하면 애플리케이션의 전반적인 성능을 크게 향상시킬 수 있습니다. 그러나 항상 실제 성능 개선이 있는지 확인하고, 코드의 복잡성과 유지보수성을 고려하여 적용해야 합니다.