[Hook] useCallback

OlMinJe·2025년 8월 31일

React

목록 보기
3/19

리액트 공식 문서를 참고한 정리 내용 (25.08 기준)

리렌더링 간에 함수 정의를 캐싱해 준다.

const cachedFn = useCallback(fn, dependencies)

함수 정의를 캐싱하려면 컴포넌트 최상단에서 useCallback을 호출해야 한다.

import { useCallback } from 'react';

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

매개변수

fn`(캐싱할 함수)

  • React가 첫 렌더링에서 함수를 실행하지 않고, 그냥 “그 함수 자체”를 기억해뒀다가 fn 그대로를 반환해준다.
  • 다음 렌더링에서는 dependencies가 이전과 같으면 “기존 함수 그대로 반환(새로 안 만듦)”한다.
  • 만약 dependencies가 바뀌면, 새로 만든 fn을 반환하고 그걸 이후에도 재사용할 수 있게 캐싱한다.
  • 이 함수는 호출 여부와 호출 시점을 개발자가 결정할 수 있도록 반환된다.

👉 불필요하게 함수가 매번 새로 만들어지지 않도록 React가 기억해둔다.

dependencies(의존성 배열)

  • fn 안에서 쓰이는 props, state, 컴포넌트 내부 변수·함수들이 의존성에 들어가야 한다.
  • 이렇게 헤야 React가 “아, 이 값이 바뀌었네? 그럼 함수 새로 만들겡~”하고 판단할 수 있다.
  • 의존성 목록은 항목 수(배열의 길이)가 일정해야 하며, [dep1, dep2, dep3]처럼 인라인으로 작성해야 한다.
  • React는 Object.is 비교 알고리즘을 이용해 각 의존성을 이전 값과 비교해, 달라졌는지 확인한다.

👉 의존성 배열은 “이 값들이 변하면 캐싱된 함수도 새로 만들어라”라는 체크리스트


반환값

  • 최초 렌더링에서는 fn 함수를 그대로 반환한다.
  • 후속 렌더링에서는 의존성이 변하지 않은 경우에는 이전 렌더링에서 이미 저장해 두었던 fn 함수를 반환하고, 변한 경우에는 현재 렌더링 중에 전달한 fn 함수를 그대로 반환한다.

주의 사항

  • useCallback은 Hook이므로 컴포넌트의 최상위 레벨 또는 커스텀 Hook에서만 호출할 수 있다.
    반복문이나 조건문에서 호출하고 싶다면, 새로운 컴포넌트로 분리하여 state를 옮겨야 한다.
  • React는 특별한 상황이 아니면 캐시된 함수를 지우지 않는다.
    다만 개발 중 초기 마운트 중 일시 중단 같은 경우엔 캐시가 사라질 수 있으며, React가 특정 상황에서 캐시를 의도적으로 지울 수 있다.
    그러니 무조건 성능 최적화용으로만 useCallback을 의존하지 말고, 경우에 따라서는 stateref 같은 다른 방법이 더 적절할 수 있다.

useCallback과 useMemo는 어떤 연관이 있나요?

useMemouseCallback은 모두 자식 컴포넌트를 최적할 때 유용하다. 무언가를 전달할 때 memoization(다른 말로는 캐싱)을 할 수 있도록 해준다.

import { useMemo, useCallback } from 'react';

function ProductPage({ productId, referrer }) {
  const product = useData('/product/' + productId);

  const requirements = useMemo(() => { // 함수를 호출하고 그 결과를 캐싱합니다.
    return computeRequirements(product);
  }, [product]);

  const handleSubmit = useCallback((orderDetails) => { // 함수 자체를 캐싱합니다.
    post('/product/' + productId + '/buy', {
      referrer,
      orderDetails,
    });
  }, [productId, referrer]);

  return (
    <div className={theme}>
      <ShippingForm requirements={requirements} onSubmit={handleSubmit} />
    </div>
  );
}
  • useMemo는 호출한 함수의 결과값을 캐싱한다. 이는 불필요하게 컴포넌트를 리렌더링하지 않고 객체를 넘겨줄 수 있도록 해준다. 필요할 때, React는 렌더링 중에 넘겨주었던 함수를 호출하여 결과를 계산한다.
  • useCallback은 함수 자체를 캐시한다. useMemo와 달리, 전달한 함수를 호출하지 않고, 전달한 함수를 캐싱해서 배열의 값이 변하지 않으면, 함수 자체가 변하지 않도록 한다.
    이는 불필요하게 컴포넌트를 리렌더링하지 않고 함수를 전달할 수 있도록 해준다.
profile
큐트걸

0개의 댓글