Front-end/React

useCallback과 useMemo의 차이

mooyou 2024. 12. 4. 13:46
728x90
300x250

 

useCallback과 useMemo 훅에 대해서 알아봤다.

 

둘 다 메모이제이션 기능을 제공하고 얼핏 같은동작을 하는것 같지만 사용하는 목적과 반환값이 다르다.

구체적으로 알아보자

 

1. useCallback

  • 사용 목적 : 함수를 메모이제이션하여 동일한 함수 인스턴스를 재사용한다.
  • 주요 사용 이유 :  함수를 자식 컴포넌트에 props로 전달할 때, 매번 새로운 함수가 생성되지 않도로고 하고 불필요한 렌더링 방지

기본 문법

const memoizedCallback = useCallback(() => {
  // 함수 로직
}, [dependencies]);

 

memoizedCallback : 메모이제이션된 함수

dependencies : 이 배열의 값이 바뀔 때만 함수가 새로 생성된다.

 

예시 : useCallback 사용

아래 예시는 자식 컴포넌트가 부모로부터 전달받은 함수로 인해 불필요하게 리렌더링되는 문제를 해결한다.

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

const Child = React.memo(({ onClick }) => {
  console.log('Child rendered');
  return <button onClick={onClick}>Click Me</button>;
});

const Parent = () => {
  const [count, setCount] = useState(0);

  // 매 렌더링마다 새 함수가 생성됨 -> 자식이 불필요하게 렌더링됨
  const handleClick = useCallback(() => {
    console.log('Button clicked');
  }, []); // 의존성 배열이 없으므로 항상 같은 함수 반환

  return (
    <div>
      <button onClick={() => setCount((prev) => prev + 1)}>Increase Count</button>
      <Child onClick={handleClick} />
      <p>Count: {count}</p>
    </div>
  );
};

export default Parent;

 

React.memo: 자식 컴포넌트가 props가 바뀌지 않으면 렌더링을 방지.

useCallback : handleClick함수가 새로생성되지 않으므로, Child가 불필요하게 리렌더링되지 않음

 

 

2. useMemo

  • 사용 목적 : 을 메모이제이션하여 계산량이 많은 작업을 반복하지 않도록 한다.
  • 주요 사용 이유 : 계산량이 많은 작업의 결과를 메모이제이션하여 성능을 최적화, 컴포넌트가 재렌더링될 때 불필요한 계산을 방지

기본 문법

const memoizedValue = useMemo(() => {
  // 계산 로직
  return computedValue;
}, [dependencies]);

memoizedValue : 메모이제이션된 값

dependencies : 이 배열의 값이 바뀔 때만 값을 다시 계산

 

예시 : useMemo 사용

아래 예시는 계산량이 많은 작업을 useMemo로 최적화한 사례이다.

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

const heavyComputation = (num) => {
  console.log('Computing...');
  return num * 2;
};

const App = () => {
  const [count, setCount] = useState(0);
  const [input, setInput] = useState('');

  // count가 변경될 때만 계산 수행
  const computedValue = useMemo(() => heavyComputation(count), [count]);

  return (
    <div>
      <button onClick={() => setCount((prev) => prev + 1)}>Increase Count</button>
      <p>Computed Value: {computedValue}</p>

      <input
        type="text"
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="Type something"
      />
    </div>
  );
};

export default App;

 

havyComputation은 count가 변경될 때만 실행된다.

input값이 변경되어도 heavyComputation은 다시 호출되지 않는다.

 

 

3. useCallback vs useMemo

  useCallback useMemo
리턴값 메모이제이션된 함수 메모이제이션된 값
주요 사용 사례 - 함수를 자식 컴포넌트에 전달
- 불필요한 렌더링 방지
- 무거운 계산 작업
- 값이 재계산 최소화
의존성 배열 함수가 재생성될 조건 지정 값이 재계될 조건 지정

 

 

4. 간단한 비교 예시

같은 코드를 useCallback과 useMemo로 비교해보자

useCallback 사용

const handleClick = useCallback(() => {
  console.log('Clicked');
}, []);

 

useMemo 사용

const memoizedFunction = useMemo(() => {
  return () => console.log('Clicked');
}, []);
  • 둘 다 비슷하게 작동하지만, useCallback은 함수 자체를 메모이제이션하고, useMemo는 값을 생성해 반환한다.
  • useMemo로도 함수를 생성할 수 있지만, 함수에 특화된 작업은 useCallback을 사용하는 것이 더 명확하고 의도를 드러낸다.

 

 

 

728x90
반응형