React - useMemo

goodjam92·2023년 3월 27일
0

React

목록 보기
3/7
post-thumbnail

두 번째로 알아 볼 React hook은 바로 useMemo이다.
useCallback과 같이 사용되기도 하는 이 hook에 대해서 알아보도록 하자!

useMemo

useMemo 리렌더링 간의 계산 결과를 캐시할 수 있는 hook

  • useMemo(caculateValue, dependencies)의 두 가지 전달요
    • caculateValue : 캐시하려는 값을 계산하는 함수
    • dependencies : 코드 내부에서 참조되는 모든 반응 값의 배열

먼저 이 hook 함수에 대해 알아보기 전에 메모이제이션(memoization) 개념을 알고가자.
memoization이란 기존에 수행한 연산 결과값을 저장해두고 동일한 입력이 들어오면 재활용하는 프로그래밍 기법을 말한다. memoization을 적절히 사용하면 중복 연산을 피할 수 있어 메모리를 쓰더라도 애플리케이션의 성능을 최적화 할 수 있다.

렌더링 마다 호출되는 컴포넌트 함수

import React from "react";

function Component(props) {
 // ...로직 수행
  return; /* UI Element (JSX) */
}

위와 같은 컴포넌트 함수는 렌더링이 일어날 때마다 호출 된다. 호출이 되면 안에 로직들이 수행되고, 이를 기반으로 JSX로 마크업 된 UI가 리턴되는 기본 구조를 갖고 있다.
React에서 컴포넌트의 렌더링은 한 번이 아닌 수시로 일어날 수 있다. 컴포넌트 자신의 상태 변경(state update) 또는 부모 컴포넌트의 상태 변경으로 인하여 함께 렌더링 되는 경우도 있다. 수동으로 다시 렌더링을 해주는 API도 있고, 사용자가 새로고침 할 때도 컴포넌트의 재 렌더링은 불가피하다.

함수형 컴포넌트와 memoization

  • memoization 미사용
import React from "react";

function Component({a, b}) {
  const result = anyFunc(a, b);
  return <div>{result}</div>;
}

이 컴포넌트는 a, b값을 anyFunc함수에 인자로 넘겨서 result값을 얻은 후 결과 값을 div엘리먼트로 감싸 출력한다.
만약에 anyFunc함수가 매우 복잡한 연산을 수행해야 한다면 컴포넌트가 재 렌더링 될 때마다 사용자는 지속적으로 UI에서의 지연을 경험하게 될 것이다.

  • memoization(useMemo) 사용
import React from "react";

function Component({a, b}) {
  const result = useMemo(() => anyFunc(a, b), [a, b]);
  return <div>{result}</div>;
}

useMemo를 사용하면 인자로 받는 a, b의 값이 이전 렌더링 때와 동일한 경우 저장되어 있던 result값을 그대로 사용하게 된다.
하지만 a, b의 값이 달라진다면 anyFunc(a, b)함수를 호출하여 새로운 result값을 할당한다.

언제 사용하면 좋을까?

일반적으로 대부분의 계산이 매우 빠르기 때문에 useMemo를 사용해야하는 경우는 많지 않다고 한다. 큰 배열을 필터링 또는 변환하거나 비용이 많이 드는 계산을 수행하는 경우에 데이터가 변경되지 않았을 경우 다시 렌더링 되어 계산 수행하는 것을 건너뛸 수 있다.

  • 비용이 많이 드는 계산을 어떻게 알 수 있을까?
    • console.time()을 사용하여 시간 계산
console.time('filter array');
const visibleTodos = useMemo(() => {
  return filterTodos(todos, tab);
}, [todos, tab]);
console.timeEnd('filter array');
// filter array: 0.15ms

이와 같이 console.time()을 사용하면 로직의 시작에서 timeEnd까지의 걸린 시간을 알 수 있다. 이 때 시간이 1ms그 이상인 경우 useMemo를 사용하는 것이 합리적일 수 있다.

앱의 상호작용이 매우 많은 경우에는 일반적으로 메모가 필요하지 않다. 반면 앱이 그림 편집기에 가깝고 대부분의 상호 작용이 세분화 된 경우 메모화가 유용할 수 있다.

  • useMemo를 적게 사용할 수 있는 원칙
    • 구성 요소가 다른 구성 요소를 시각적으로 래핑할 때 JSX를 자식으로 허용하도록 한다. <div>{children}</div>
    • 로컬 상태를 선호하고 필요 이상으로 상태를 올리지 않는다.
      • 구성요소 간 상태 공유를 필요로 할 때 각자 상태를 두지 않고, 가장 가까운 공통 부모로 이동한 다음 props로 전달한다.
    • 렌더링 논리를 순수하게 유지한다.
    • state업데이트하는 불필요한 useEffect를 피한다.
    • useEffect에서 불필요한 의존성을 제거한다.

끝으로...

memoization 기법을 함수형 컴포넌트에 쉽게 사용할 수 있도록 도와주는 useMemo hook에 대해 알아보았다.
이 hook도 useCallback과 같은 주의점을 갖고 있고, 최적화에 사용되는 hook으로 먼저 최적화를 할 때의 실제 성능 이점을 생각하고 사용해야겠다 생각이든다.

.
.
.
.
.
.

참고 사이트
[daleseo] - useMemo 사용법
React 공식문서 - useMemo

profile
습관을 들이도록 노력하자!

0개의 댓글