React의 useMemo는 언제 사용해야 하는가?

seohyun Kang·2023년 6월 9일
0

React

목록 보기
8/9

Introduction

React는 렌더링 성능 향상을 위해서 복잡한 연산에 대하여 useCallback, useMemo 등의 훅들을 사용하여 함수 혹은 변수의 값을 메모리에 캐싱하고 재사용할 수 있도록 합니다.

하지만, useMemo는 약간의 오버헤드를 가지며 비용이 높지 않은 곳에서useMemo를 사용하면 오히려 렌더링 성능 저하를 야기합니다.

다만, 문제가 몇가지 있는데 비싼 연산의 기준적절한 사용처를 특정하기 어렵습니다. 이 때문에, 관련 블로그 포스트를 바탕으로 useMemo의 남용으로 인한 성능 이슈를 확인하고 적절한 사용법에 대한 이해를 높이려고 합니다.

useMemo란?

useMemo is a React Hook that lets you cache the result of a calculation between re-renders.
-Def. of useMemo-

useMemo와 같이 렌더링 성능과 관련이 있는 훅은 React의 특징과 관련이 있습니다. 기본적으로 React는 Re-render시에 컴포넌트의 내부에 정의된 함수 및 변수를 생성 및 할당합니다. 이때, 비용이 변수를 매번 계산하는 것을 방지하기 위해 useMemo를 사용합니다.

const memoized = useMemo(() => state * 2, [state]);

위와 같은 사용으로 useMemo는 특정 State를 Dependency로 가지고 해당 State에 업데이트가 발생하면 캐싱하고 있던 변수를 재연산합니다.

useMemo는 어떻게 사용하는가?

How to use the useMemo?

리액트의 공식 문서를 확인하면 useMemo의 사용법에 대해 아래 네 가지로 정리해 두었습니다.

  • Skipping expensive recalculation
  • Skipping re-rendering of components
  • Memoizing a dependency of another hook
  • Memoizing a function

또한, 우리는 이미 많은 경험과 검색을 바탕으로 아래와 같은 방법으로 useMemo를 사용하고 있습니다.

Sample Code

function App() {
  const [memoCount, setMemoCount] = useState<number>(0);
  const [normalCount, setNormalCount] = useState<number>(0);

  const memoizeCount = useMemo(() =>  memoCount * 2 ,[memoCount]);

  return (
      <div onClick={() => setMemoCount(prev => prev + 1)}>Memo Counting</div>
      <div onClick={() => setNormalCount(prev => prev + 1)}>Normal Counting</div>
      <div>Memo Count : {memoCount}</div>
      <div>Normal Count : {normalCount}</div>
      <div>MemoCount * 2 Count : {memoizeCount}</div>
  )
}

normalCount를 변경하였을 때는 memoized변수가 연산을 수행하지 않지만 memoCount의 값이 변경되었을 때는 연산을 수행합니다.

우리는 위와 같은 테스트 코드를 통해 useMemo를 어떻게 사용해야할지 이해하고 있습니다. 이를 바탕으로 비싸거나 시간이 소요되는 연산에 대해서 적용하면 불필요한 계산 시간을 제거하고 캐시된 데이터를 가져와 빠르게 UI를 그릴 수도 있다는 것도 이해할 수 있습니다.

useMemo는 언제 사용하지 않아야 하는가?

문제는 useMemo는 약간의 오버헤드를 가지며 useMemo의 남용이 반대로 성능저하를 야기할 수 있다는 점입니다. 그러나, 리액트 공식문서 어디에서도 useMemo를 사용하지 말하야하는 부분은 찾을 수가 없습니다.

그렇다면 언제 사용하지 않아야 할까?

When Not to the useMemo 블로그에서는 아래의 경우에 useMemo를 사용하지 않도록 하고 있습니다.

  • Don’t use useMemo if your operation is inexpensive
  • Don’t use useMemo if you are memoizing a defaultState object

두 번째, 'defaultValue로 useMemo를 사용하지 말아라'라는 문구는 이해가 되지만, inexpensive 한 연산은 정확하게 어떤 의미일까?

Expensive & Time-consumimng 연산이란?

다양한 블로그를 찾아보면 useMemo는 Expensive(Complex) 하고 Time-consuming 한 연산에 대해서만 적용하라고 합니다.

문제는 비싸고 오래걸리는이란 의미는 주관의 영역입니다.

과연 얼마나 비싸고 얼마나 오래걸려야 useMemo를 통해 Cache된 값을 가져오는 것이 성능 향상에 영향을 줄 수 있을까?

Kevin Van Ryckegem은 자신의 블로그에서 가정을 통해 여러 Expensive 하고 Time-cosuming 한 연산을 useMemo로 작성하고 성능을 측정했습니다.

Expensive Operation Standard

개인적으로 변수, 시간복잡도 등을 통해 개인적인 useMemo 적용을 위한 기준점을 찾아보려고 합니다.

0개의 댓글