[React] useCallback vs useMemo 언제 사용해야 할까?

srchae·2025년 2월 13일
post-thumbnail

🧐 Intro

사이드 프로젝트를 진행하며, 생각보다 메인 컴포넌트에 연산 로직이 많아지고 코드가 길어지니... 이를 하나 둘씩 리팩토링 해야했고 드디어 이들이 등장했다!🫢

useCallback이란?

useCallback은 컴포넌트가 리렌더링 될 때마다 콜백함수를 매번 새로 생성하지 않고, 재사용하여 성능 최적화에 기여하는 훅을 의미한다.

특히 해당 함수를 자식 컴포넌트의 props로 전달해야 한다면, 자식 컴포넌트의 불필요한 렌더링을 방지해주니 더욱 사용을 고려해봐도 좋다.
(props로 전달한다면 React.memo와 함께)

const cachedFn = useCallback(fn, dependencies)

사용 방법

  • 메모이제이션이 필요할 함수 앞에 useCallback을 감싼다.
  • 의존성 배열도 함께 포함한다.

의존성 배열에
값이 빈 경우 : 처음 한 번만 함수가 생성되고, 이후에는 재생성되지 않음
값이 들어간 경우 : 해당 값이 변경될 때만 새로운 함수 생성

사용 예시

import React, { useState, useCallback } from "react";
import ChildComponent from "./ChildComponent";

const ChildComponent = React.memo(({ onClick }: { onClick: () => void }) => {
  return <button onClick={onClick}>+</button>;
});

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

  // useCallback으로 함수의 참조값을 유지 (불필요한 리렌더링 방지)
  const handleClick = useCallback(() => {
    setCount((prev) => prev + 1);
  }, []);

  return (
    <div>
      <p>Count: {count}</p>
      <ChildComponent onClick={handleClick} />
    </div>
  );
};

정리

  • 해당 컴포넌트가 리렌더링될 때마다 새로운 함수가 생성되면, 해당 함수를 전달받는 자식 컴포넌트도 불필요하게 리렌더링됨
  • useCallback을 사용하면 동일한 함수 참조값을 유지하여 불필요한 리렌더링을 방지

useMemo란?

useMemo는 무거운 연산이 렌더링마다 실행되지 않도록 캐싱하여 성능 최적화에 기여하는 훅을 의미한다.

const cachedValue = useMemo(calculateValue, dependencies)

사용 방법

  • 메모이제이션이 필요할 연산 앞에 useMemo을 감싼다.
  • 의존성 배열도 함께 포함하며 이는 해당 값이 변경되지 않는 한, 기존 값을 재사용

사용 예시

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

export const Component = () => {
  const [count, setCount] = useState(0);
  const [numbers] = useState([5, 2, 8, 1, 3]);

  // useMemo를 사용하여 정렬된 배열을 캐싱
  const sortedNumbers = useMemo(() => {
    return [...numbers].sort((a, b) => a - b);
  }, [numbers]); // numbers가 변경될 때만 정렬 로직 실행

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
      <p>Sorted Numbers: {sortedNumbers.join(", ")}</p>
    </div>
  );
};

정리

  • useMemo값을 캐싱하여 불필요한 연산을 방지하는 역할
  • 렌더링 성능을 최적화하고 싶다면, 즉 비싼 연산이 발생하는 곳에 사용
  • 메모이제이션 자체도 비용이 발생하므로, 값이 자주 변경되거나 연산이 가볍다면 오히려 불필요한 오버헤드가 생길 수 있음
  • 즉, 불필요하게 남용하면 성능을 더 악화시킬 수 있음

💡 useCallback vs useMemo

무엇을 메모이제이션(기억)하여 재사용하는가?

  • useCallback함수를 메모이제이션
  • useMemo을 메모이제이션
profile
🐥집요함과 꾸준함🪽

0개의 댓글