[React - TIL] useMemo 와 useCallback ? 차이점?

Leesu·2023년 3월 22일
0
post-thumbnail

🟡 useMemo란?

함수형 컴포넌트 내에서 선언적으로 메모이제이션(memoization)을 수행하는 Hook이다.

  • useMemo를 사용하면 함수의 리턴값을 캐시(cache)하고, 해당 함수의 입력값이 변경되지 않으면 이전에 캐시된 값을 재사용할 수 있다.
    따라서 불필요한 연산을 줄이고, 애플리케이션의 성능을 최적화할 수 있다.

  • 컴포넌트의 첫 렌더링 시 실행되고, 이후 리렌더가 될 때마다 캐시된 데이터를 반환해 보여준다.

  • 동일한 값을 반환하는 함수를 반복적으로 호출해야될 때 사용한다.

❗memoization

메모이제이션(memoization)이란 무엇일까?

반복되는 결과를 메모리에 저장 해놓고 다음에 같은 결과가 나올 때 다시 계산할 필요없이 빨리 실행 하는 기법

즉, 한번 연산된 결과를 기억해두고, 다시 동일한 입력이 들어오면 기억해둔 데이터를 반환하는 방법이다.

- 사용 방법

기본문법

import { useMemo } from 'react';

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • 첫 번째 인자는 계산할 함수이고,
    두 번째 인자는 의존성 배열(dependancyArray)을 받는다.

  • 의존성 배열에는 함수를 호출할 때 매번 바뀔 수 있는 값들을 입력하면된다.
    그럼 이 값들이 바뀔 때마다 useMemo 에서는 새로운 결과를 계산하고, 값이 바뀌지 않으면 재사용한다.

  • 만약 빈 배열([])을 넘겨주면 맨 처음 컴포넌트가 마운트 되었을 때만 값을 계산하고 이후에는 항상 메모이제이션 된 값을 꺼내와서 사용한다.

예제

import React, { useState, useMemo } from 'react';

function App() {
  const [value1, setValue1] = useState(0);
  const [value2, setValue2] = useState(0);

  const sum = useMemo(() => {
    console.log('sum calculated!');
    return value1 + value2;
  }, [value1, value2]);

  return (
    <div>
      <div>
        <button onClick={() => setValue1(value1 + 1)}>Value1 + 1</button>
        <button onClick={() => setValue2(value2 + 1)}>Value2 + 1</button>
      </div>
      <div>
        Sum: {sum}
      </div>
    </div>
  );
}
  • 위 코드에서는 value1 과 value2를 더하는 sum 함수를 useMemo()로 선언했으며,
    두 번째 인자에 [value1, value2] 값을 추가하였다.

  • 이제 useMemo[value1, value2] 의 값이 바뀔 때마다 sum 함수를 새로 계산하고,
    두 값을 더한 결과를 보여주는 Sum 이라는 컴포넌트를 만들어 사용했다.

  • 이제 버튼을 클릭할 때마다 value1 또는 value2가 변경되는데,
    이때 useMemo 의 두 번째 인자 배열 [value1, value2] 를 통해 value1 과 value2가 변경될때마다 sum 함수를 재계산하게 된다.
    따라, 콘솔에 "sum calculated!"가 찍히며 Sum 컴포넌트도 매번 새로그려진다.

  • 허나, 버튼을 클릭하지 않는다면?
    useMemo 함수가 호출되지 않고 이미 나온 결과값을 메모리에서 꺼내(캐시된 값) 보여준다.
    콘솔에도 "sum calculated!"가 찍히지 않는다.


🟡 useCallback 이란?

함수를 메모이제이션(memoization)하기 위해 사용되는 Hook이다.

  • useMemo 와 비슷한 점이 있지만, useCallback은 함수를 저장하여 매 실행마다 재생성되지 않도록 하는 Hook 이다.

  • 만약, 어떤 리액트 컴포넌트 함수 안에 함수가 선언이 되어 있다면 이 함수는 해당 컴포넌트가 렌더링 될 때마다 새로운 함수가 생성될 것이다.

  • 하지만, useCallback 을 사용한다면, 해당 컴포넌트가 렌더링 되더라도 그 함수가 의존하는 값들이 바뀌지 않는 한 기존 함수를 계속해서 반환한다.(재사용) useMemo 와 유사.

  • 자바스크립트 함수의 동등성, 의존 배열로 함수를 넘길 때 사용하면 좋다. (자세한 내용은 여기)
    추가로, 자식 컴포넌트 랜더링의 불필요한 랜더링을 줄이기 위해 React.Memo 와 함께 사용할 수 있다.

- 사용방법

기본문법

useCallback(() => {...}, [dependencies])
  • 첫 번째 인자는 저장할 함수이고,
    두 번째 인자는 useCallback 호출의 의존성 배열(dependancyArray)을 받는다.

  • 두 번째 인자로 넘어온 배열 내의 값이 변경될 때까지 저장해놓고, 함수를 재사용할 수 있게 해준다.

예제

function ProductPage({ productId, referrer, theme }) {
  const handleSubmit = useCallback((orderDetails) => {
    post('/product/' + productId + '/buy', {
      referrer,
      orderDetails,
    });
  }, [productId, referrer]); 

  return (
    <div className={theme}>
      <ShippingForm onSubmit={handleSubmit} />
    </div>
  );
}
  • 위는 리액트 공홈에 나와있는 예제이다.(ㅎㅅㅎ)

  • 위의 코드에서 보았을 때 handleSubmit 함수는 의존성 배열이 변경될 때 까지 재 생성되지 않고 유지되며 캐시된다.


🟡 둘의 차이점?

  • useMemo 는 특정 결과값을 재사용 할 때 사용하는 반면,
    useCallback 은 특정 함수를 새로 만들지 않고 재사용하고 싶을 때 사용한다.

  • 함수의 연산량이 많을 때 이전 결과값을 재사용하는 목적으로 useMemo,
    함수가 재생성 되는 것을 방지하기 위한 목적으로 useCallback.


profile
기억력 안 좋은 FE 개발자의 메모장

0개의 댓글