본문 바로가기

TIL

2023.8.24일 TIL

useMemo()로 최적화 하기

// useMemo 사용 전
// App.js
function App() {
  const [listTitle, setListTitle] = useState('My List');

  const changeTitleHandler = useCallback(() => {
    setListTitle('New Title');
  }, []);

  return (
    <div className="app">
      <DemoList title={listTitle} items={[5, 3, 1, 10, 9]} />
      <Button onClick={changeTitleHandler}>Change List Title</Button>
    </div>
  );
}

export default App;

import React from 'react';

import classes from './DemoList.module.css';

const DemoList = (props) => {

  const sortedList = props.items.sort((a,b) => a-b);
  console.log('DemoList RUNNING');

  return (
    <div className={classes.list}>
      <h2>{props.title}</h2>
      <ul>
        {sortedList.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
};

export default React.memo(DemoList);

위 예제에서, DemoList에 전달되는 props의 items 배열은 App 컴포넌트가 다른 이유로 리렌더링 되더라도 항상 새로운 배열이 생성되기 때문에, DemoList 컴포넌트 재실행 및 내부의 sort 함수가 동작을 한다.

 

하지만, 만약 items 배열의 크기가 너무 큰 경우에는 배열의 요소의 변화가 없는 상황에서 매번 items 배열의 sort를 진행하는 것은 낭비가 될 수도 있다.

 

이런 경우에는 useMemo를 사용할 수 있다. useCallback이 함수에 대한 것을 저장하듯 useMemo는 모든 종류의 데이터를 저장할 수 있다.

 

useMemo의 첫 번째 인자에는 함수가 들어가야 한다. 이 함수를 기억하는 것이 아닌 이 함수가 저장하고 싶은 것을 반환한다고 생각하면 된다.

 

두 번째 인자로는 의존성 배열이다. 의존성 배열을 통해 저장된 값에 변경 사항이 생길 때마다 업데이트할 수 있다.

 

useMemo를 사용해 데이터를 저장하면 이는 메모리를 사용하는 것이고 이런 함수 저장 또한 일정 성능을 사용하는 것이다.

 

따라서 useMemo는 모든 값에 사용하는 것이 아니라, 불필요한 작업을 반복할 필요가 없을 때 고려하는 것이 좋다.

 

//useMemo를 사용한 최적화
// App.js
function App() {
  const [listTitle, setListTitle] = useState('My List');

  const changeTitleHandler = useCallback(() => {
    setListTitle('New Title');
  }, []);

  // useMemo를 사용하지 않으면, 항상 새로운 배열로 취급된다. 따라서, listItems를 useMemo를 사용하지 않는 경우에는 DemoList 컴포넌트에 useMemo를 사용하더라도 sort가 계속 실행된다.
  const listItems = useMemo(() => [5, 3, 1, 10, 9], []);

  return (
    <div className="app">
      <DemoList title={listTitle} items={listItems} />
      <Button onClick={changeTitleHandler}>Change List Title</Button>
    </div>
  );
}

export default App;

// DemoList.js
import React, { useMemo } from 'react';

import classes from './DemoList.module.css';

const DemoList = (props) => {
  const { items } = props;

  const sortedList = useMemo(() => {
    console.log('Items sorted');
    return items.sort((a, b) => a - b);
  }, [items]);
  // items가 바뀔 때만 sortedList가 바뀌도록 useMemo를 사용한다.
  console.log('DemoList RUNNING');

  return (
    <div className={classes.list}>
      <h2>{props.title}</h2>
      <ul>
        {sortedList.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
};

export default React.memo(DemoList);

* useMemo와 useCallback의 차이점

 

useMemo:

 

useMemo는 계산 비용이 큰 연산의 결과를 저장하고, 동일한 입력이 주어진 경우에는 이전에 계산한 결과를 재사용할 때 사용된다.

주로 계산 비용이 높은 연산을 줄이기 위해 사용된다.

예를 들어, 계산된 결과를 UI에 표시하는데 사용하는 경우나, 복잡한 계산을 할 때 활용할 수 있다.

 

useCallback:

 

useCallback은 함수를 메모이제이션하여 새로운 렌더링 시에 동일한 함수 인스턴스를 유지한다.

주로 자식 컴포넌트에 함수를 전달할 때 사용된다.

예를 들어, 자식 컴포넌트에게 이벤트 핸들러를 전달하거나, useEffect 내에서 의존성 배열에 포함되는 함수를 전달할 사용할 있다.


[Udemy] React 완벽 가이드 with Redux, Next.js, TypeScript 강의를 듣고 학습했습니다

'TIL' 카테고리의 다른 글

2023.8.23 TIL  (0) 2023.08.23