본문 바로가기

dev/React

[React 성능 최적화] Children 컴포넌트의 불필요한 렌더링 방지하기

React를 최적화하는 업무를 받아 작업을 진행하며 알게 된 것들을 공유하고자 합니다.

우선 react에서 제공하는 공식 예제를 참조하면 다음과 같습니다.

const MyApp = props => {
    const [name, setName] = useState('');
    const [address, setAddress] = useState('');
    return (
    <>
      <label>
        Name{': '}
        <input value={name} onChange={e => setName(e.target.value)} />
      </label>
      <label>
        Address{': '}
        <input value={address} onChange={e => setAddress(e.target.value)} />
      </label>
      <Greeting name={name} />
    </>
    );
}

위와 같은 컴포넌트에서, MyApp의 address가 변경되어도 Greeting은 다시 렌더링됩니다. address를 props로 전달받지는 않지만, MyApp 컴포넌트가 다시 렌더링되며 Greeting 컴포넌트도 함께 렌더링되는 것입이다. 이렇게 일반적으로 react에서는 부모 컴포넌트가 리렌더링 되는 경우 자식 컴포넌트도 리렌더링 됩니다.

 

일반적으로 이는 문제가 되지 않지만, Greeting의 렌더링 비용이 매우 큰 경우에는 실제 Greeting의 props이 변화할 때에만 새로 렌더링하는 방식을 취할 수 있습니다. Greeting를 memo함수로 감싸주면 됩니다. memo함수는 부모 컴포넌트가 다시 렌더링 되더라도 자신의 props가 변경되지 않았다면 렌더링하는 대신 이미 기억해둔 컴포넌트를 사용합니다.

 

단, 부모로부터 전달되는 props에만 해당하며 context의 변경에는 여전히 반응합니다. 또한 Obejct.is를 사용한 얕은 비교를 하는 것은 동일하기 때문에 실제 전달받는 props의 변화 자체가 많은 경우에는 memo함수가 거의 의미 없게 됩니다. 이 경우 useMemo를 이용해 props의 변화를 최소화함으로써 보다 효율적인 최적화가 가능합니다. 다음은 react 공식 페이지 예시입니다.

function Page() {
  const [name, setName] = useState('Taylor');
  const [age, setAge] = useState(42);

  const person = useMemo(
    () => ({ name, age }),
    [name, age]
  );

  return <Profile person={person} />;
}

const Profile = memo(function Profile({ person }) {
  // ...
});

 

또한, 데이터를 거대한 덩어리도 전달하기 보다 필요한 만큼 잘라서 전달하는 것도 필요합니다. 얕은 비교를 하는 만큼 복잡한 오브젝트를 전달하는 것보다 명확한 값을 전달해 정확한 비교를 가능하게 하는 것이 좋습니다.

function Page() {
  const [name, setName] = useState('Taylor');
  const [age, setAge] = useState(42);
  return <Profile name={name} age={age} />;
}

const Profile = memo(function Profile({ name, age }) {
  // ...
});

 

+ memo를 꼭 사용해야 하는지에 대한 설명도 최적화에 도움이 많이 되는 것 같습니다! 다음 글도 읽어보시는 것을 추천드립니다.

https://react.dev/reference/react/memo#should-you-add-memo-everywhere

 

참조

[memo] 

https://react.dev/reference/react/memo