React Component 깜빡임을 없애보라.

반응형

React unexpected rerendering issue

React를 사용하여 웹페이지를 만들면서 익숙해지기 시작하면 가장 먼저 만나는 문제가 Rerendering 문제입니다. 기능이 동작하는 것 같으나 느낌상, 또는 실제로 화면이 깜빡이는 느낌이 오는 건 나만의 문제는 아닐 겁니다.

깜빡이는 하위 컴포넌트

버튼 이벤트를 사용해서 State를 업데이트할 수 있는 컴포넌트입니다.

import React, { useState } from 'react';

const ChildComponent = ({ text }) => {
  console.log('ChildComponent rendered');
  return <div>{text}</div>;
};

const ParentComponent = () => {
  const [count, setCount] = useState(0);
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <ChildComponent text="I should not blink" />
    </div>
  );
};

버튼을 클릭하면 어떤 일이 일어날까요? 콘솔창에 ChildComponent renedered 라는 문구가 계속 찍힐겁니다. 간단한 컴포넌트라서 console 로그로 표현한 것일뿐, 실제 렌더링이 느린 경우는 사람의 눈에 보일 정도로 깜빡일겁니다. 왜냐하면 ParentComponent가 rerender하면 ChildComponent도 함께 rerender되기 때문입니다. 이게 함수형 컴포넌트의 특징입니다.

그렇다면 이런 문제를 해결하기 위한 솔루션은 무엇일까요?

리액트에서 React.memoPureComponent를 사용하여 불필요한 리렌더링을 방지할 수 있습니다. 각각 함수형 컴포넌트와 클래스형 컴포넌트에서 사용됩니다.

React.memo

React.memo는 함수형 컴포넌트의 성능을 최적화하기 위해 사용됩니다. 전달된 props가 변경되지 않으면 컴포넌트를 리렌더링하지 않습니다.

import React, { memo } from 'react';

const ChildComponent = ({ name }) => {
  console.log('ChildComponent rendered');
  return <div>{name}</div>;
};

export default memo(ChildComponent);

PureComponent

PureComponent는 클래스형 컴포넌트에서 props와 state가 변하지 않으면 리렌더링을 방지합니다. shouldComponentUpdate 메서드를 간단하게 구현한 것과 동일한 역할을 합니다.

import React, { PureComponent } from 'react';

class ChildComponent extends PureComponent {
  render() {
    console.log('ChildComponent rendered');
    return <div>{this.props.name}</div>;
  }
}

export default ChildComponent;

💡정리하기

React.memo와 PureComponent 모두 props가 변경되지 않는 경우 컴포넌트가 다시 렌더링되지 않도록 합니다. 이를 통해 성능을 최적화할 수 있습니다. 정리하면 다음과 같습니다.

  • React.memo는 함수형 컴포넌트에서 사용하며, PureComponent는 클래스형 컴포넌트에서 사용됩니다.
  • React.memo는 기본적으로 얕은 비교를 수행하며, 필요에 따라 비교 함수를 제공할 수 있습니다.
  • PureComponent는 shouldComponentUpdate를 기본적으로 구현한 것과 유사하게 동작합니다.

추가예제: React.memo에 비교 함수 사용하기

이와 같이 하면 name이 변경되지 않는 한 리렌더링되지 않게 됩니다. 이를 통해 컴포넌트의 성능을 더욱 세밀하게 제어할 수 있습니다.

const MyComponent = ({ name }) => {
  console.log('Rendering MyComponent');
  return <div>{name}</div>;
};

const areEqual = (prevProps, nextProps) => {
  return prevProps.name === nextProps.name;
};

export default memo(MyComponent, areEqual);

추가 비교: React.useMemo vs React.memo 의 차이점

• React.memo: 컴포넌트 전체의 리렌더링을 방지합니다. props가 변경되지 않는 한 컴포넌트를 다시 렌더링하지 않습니다.
• useMemo: 특정 계산의 결과를 메모이제이션합니다. 의존성이 변경되지 않는 한 캐싱된 값을 반환합니다.

언제 useMemo를 사용해야 하는가?

• 복잡한 계산이 있는 경우
• 동일한 입력에 대해 반복적으로 계산하는 경우

언제 React.memo를 사용해야 하는가?

• 함수형 컴포넌트의 불필요한 리렌더링을 방지하고자 하는 경우

따라서 useMemo는 특정 계산을 최적화하는 데 유용하며, 모든 함수형 컴포넌트에서 반드시 사용해야 하는 것은 아닙니다. 반면, React.memo는 컴포넌트의 리렌더링을 방지하여 성능을 최적화하는 데 사용됩니다. 상황에 맞게 적절한 방법을 선택하여 사용하면 됩니다.

--끝--

반응형