React.memo

Jaeseok Han·2023년 11월 10일
0

React Basic

목록 보기
26/30

React.memo()

React.memo는 React에서 제공하는 고차 컴포넌트(Higher-Order Component)로 컴포넌트를 메모이제이션할 수 있게 해준다. 이는 컴포넌트에 전달된 입력 속성(props)이 변경되지 않았다면, 메모이제이션된 컴포넌트는 이전 렌더링에서의 결과를 재사용하고 리렌더링되지 않는다. 이를 통해 불필요한 렌더 사이클을 방지하고 성능을 향상시킬 수 있다.

React.memo함수는 함수 컴포넌트를 인자로받아 해당 컴포넌트와 동일한 동작을 하는 새로운 컴포넌트를 반환한다. 다만 추가로 속성(props)이 변경되었는지를 확인는 optimization이 포함되어있다. 속성이 변경되지 않았다면 메모이제이셔된 컴포넌트는 이전 렌더링에서의 결과를 반환한다.

💡 Memoization이란

이전에 계산된 결과를 저장하고,같은 입력 값이 다시 들어오면 이전에 저장한 결과를 재사용하는 기술이다. 이를 통해 계산 비용을 줄이고 성능을 향상시킬 수 있다.

React에서의 메모이제이션은 주로 함수나 컴포넌트의 결과를 캐싱하여 동일한 입력 값이 들어왔을 때 이전에 계산한 결과재사용한다.

React.memo는 함수 컴포넌트의 메모이제이션을 담당한다. 기본적으로 이 컴포넌트를 렌더링할 때마다 함수 컴포넌트가 새로 생성되는데, React.memo를 사용하면 컴포넌트의 속성(props)이 변경되지 않으면, 이전에 생성된 결과를 재사용하여 렌더링 성능을 향상시킨다.

메모이제이션은 동일한 계산을 반복하지 않고 캐싱된 결과를 활용하여 성능을 최적화하는데 사용한다.

List.jsx

import Item from './Person';
import { memo } from 'react';

const List = ({ people }) => {
  return (
    <div>
      {people.map((person) => {
        return <Item key={person.id} {...person} />;
      })}
    </div>
  );
};
export default memo(List);

이런식으로 memo를 export 구문에 컴포넌트에 씌우면 설정되어
List 컴포넌트에 들어오는 props의 값이 이전과 동일하다면 이전 결과값을 렌더링해준다.

Funcaiont "Gotcha"

import { useState } from 'react';
import { data } from '../../../../data';
import List from './List';
const LowerState = () => {
  const [people, setPeople] = useState(data);
  const [count, setCount] = useState(0);

  const removePerson = (id) => {
    const newPeople = people.filter((person) => person.id !== id);
    setPeople(newPeople);
  };

  return (
    <section>
      <button
        className='btn'
        onClick={() => setCount(count + 1)}
        style={{ marginBottom: '1rem' }}
      >
        count {count}
      </button>
      <List people={people} removePerson={removePerson}/>
    </section>
  );
};
export default LowerState;

import Item from './Person';
import { memo } from 'react';

const List = ({ people, removePerson }) => {
  return (
    <div>
      {people.map((person) => {
        return <Item key={person.id} {...person} removePerson={removePerson}/>;
      })}
    </div>
  );
};
export default memo(List);

const Person = ({ name, removePerson, id }) => {
  console.log('render')
  return (
    <div>
      <h4>{name}</h4>
      <button onClick={() => removePerson(id)}>
        remove
      </button>
    </div>
  );
};
export default Person;

이 경우 removePerson함수가 실행되면 count 상태값이 변경되어 LowState의 컴포넌트가 리렌더링되고 선언된 함수(removePerson)와 상태값(people)이 재생성 때문에 List 컴포넌트가 메모이제이션이되어 있어도 List 컴포넌트에 전달되는 people과 removePerson props가 변경되면 List컴포넌트는 다시 렌더링된다.

List 컴포넌트가 부모 컴포넌트로부터 받은 props가 변경될 때, 메모이제이션된 결과를 재사용하지 않고 리렌더링한다. 즉, List 컴포넌트의 memoizationprops의 얕은 비교(shallow comparison)에 의존하며, props가 변경되면 리렌더링된다.

이를 해결하기 위해서는 useCallback훅을 사용하여 메모이제이션을 하는것이 필요하다.

0개의 댓글