[React] 3. ReactHooks - useMemo와 useCallback

현채은·2023년 8월 27일
post-thumbnail

오늘 포스팅 할 내용은 useMemo와 useCallback 입니다 !
요즘 리팩토링을 시작하면서 성능개선에 대해서도 관심을 가지게 되었는데 이 친구들이 성능 개선에 기여를 하는 친구들이네여..
바로 포스팅으로 정리해둬야겠다 생각이 들어서 작성하게 되었습니다 🫡

[1] 들어가기 전에

다들 useState와 useCallback은 많이 사용해보셨지만, useMemo와 useCallback은 생소하게 느껴지시는 분들이 많을 것이라고 생각이 듭니다. ( 저도 마찬가지.. ㅎㅎ; )

useMemouseCallback은 리액트의 렌더링 성능을 최적화 하는 hook이기 때문에 필수적으로 사용할 필요는 없습니다.

그럼에도 불구하고 포스팅을 하는 이유는 할 수 있는데 안하고 있던 제 자신을 반성하기 위해서 입니다 :)

[2] 배우기 전에 알아두면 좋은 개념들

1. 메모제이션 (Memozation)

들어가기 전에 먼저 메모제이션이라는 개념에 대해 확실히 알아둬야합니다.

메모제이션이란 기존에 수행한 연산의 결과값을 어딘가에 저장해두고 동일한 입력이 들어오면 재활용하는 프로그래밍 기법입니다.
이것을 이용하면 불필요한 리렌더링을 방지할 수 있기 때문에 애플리케이션의 성능을 최적화 할 수 있습니다.

2. 리렌더링 (re-rendering)

컴포넌트는 자신의 state가 변경되거나, 부모에게서 받는 Props가 변경될 때 마다 리렌더링 됩니다.
컴포넌트가 렌더링 된다는 것은 누군가가 그 함수를 호출하여 실행되는 것을 말하며 함수가 실행될 때 마다 내부에 선언되어 있던 표현식도 매번 다시 선언되어 사용됩니다.
( 표현식이 그대로더라도 다시 호출되어 리렌더링이 된다. )

[3] useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a,b), [a,b]);

( 출처: 리엑트 공식문서 )

  • useMemo는 메모리제이션된 값을 반환한다.
  • 여기서 a,b의 값이 변경된다면 computeExpensiveValue(a,b) 함수를 실행하고, 그 함수의 반환값을 반환해줍니다.
  • 여기서 a,b는 의존성을 뜻하며 useMemoa,b에 의존하고 있음을 나타냅니다.

아래의 예제를 한번 같이 살펴봅시다.

const Button = memo(({ text, onClick }) => {
  console.log("Button", text, "re-rendering");
  const result = useMemo(() => calculateSomething(), []);
  return (
    <button
      onClick={onClick}
      style={{
        backgroundColor: "black",
        color: "white",
        borderRadius: "20px",
        margin: "0.2rem",
      }}
    >
      {`${text} ${result}`}
    </button>
  );
});

function calculateSomething() {
  for (let i = 0; i < 10000; i++) {
    console.log("😳");
  }
  return 10;
}

Button이라는 컴포넌트는 memo로 래핑되어있으며, 컴포넌트 내부에 useMemo를 통해 calculateSomething이라는 함수를 실행하고 있습니다. 의존성배열이 빈 것을 보면 실행될 때 한번만 실행된다는 것을 알 수 있습니다.

[3] React.memo

React.memo는 컴포넌트를 렌더링하고 결과를 메모이징합니다.

  • 그리고 다음 렌더링이 일어날 때 props가 같다면 React는 메모이징된 내용을 재사용 합니다.
    ( = 변경되지 않은 props의 리렌더링을 방지할 수 있음 )
  • 위 코드에서 Button은 메모이징된 값을 반환합니다. text나 onClick와 같은 props가 변경되지 않는다면 다음 렌더링 때 메모이징 된 내용을 그대로 사용하게 될 것입니다.

[4] useMemo

useMemo는 메모이즈 된 값을 return하는 hook 입니다.

  • 인자로 함수와 의존값을 받으며, 두번째 인자로 준 의존인자 중 하나라도 변경되면 값을 재계산합니다.
    ➡️ 이를 통해 매 렌더시마다 소요되는 불필요한 계산을 피할 수 있습니다.
    ➡️ 하지만 인자로 아무것도 전달되지 않는 다면 렌더시마다 항상 값을 새롭게 계산하여 return합니다.

calculateSomething 함수와 같이 컴포넌트 내에서 무거운 일을 하는 경우, useMemo를 사용하면 해당 컴포넌트가 호출될 때 마다 실행되는 것을 방지할 수 있기 때문에 성능을 향상시킬 수 있습니다.
만약 useMemo를 사용하지 않았다면 Button 컴포넌트가 호출 될 때 마다 해당 함수가 호출되는 일이 발생합니다.

🚨 useMemo를 사용하지 않은 경우
함수를 실행할 때 마다 콘솔창에는 Button 컴포넌트 내 calculateSomething함수가 계속해서 실행 될 것 입니다.
➡️ 하지만 useMemo를 사용하여 , 처음 렌더링 될때만 해당 함수를 실행하도록 해주고, Button 컴포넌트가 실행되어도 calculateSomething함수는 실행되지 않을 것 입니다.

[5] React.memo와 useMemo의 차이점

  1. React.memo는 HOC(Higher-Order Components) vs useMemo는 hook
    (HOC: 컴포넌트를 인자로 받아 새로운 컴포넌트를 다시 return 해주는 함수)

  2. React.memo는 HOC이기 때문에 클래스형 컴포넌트, 함수형 컴포넌트 모두 사용가능하지만, useMemo는 hook이기 때문에 오직 함수형 컴포넌트 안에서만 사용 가능하다.

profile
개발 기록 공간

0개의 댓글