티스토리 뷰

Frontend

React - useMemo & useCallback

hjkang 2026. 2. 11. 09:58

React로 개발하다 보면 성능 최적화를 위해 useMemo와 useCallback을 사용하게 되는데,
두 훅을 언제 어떻게 사용해야 하는지 정리해보자

 

 

useMemo

연산 결과 값을 메모이제이션

const expensiveValue = useMemo(() => {
  return heavyCalculation(data);
}, [data]);

 

useCallback

함수 자체를 메모이제이션

const handleClick = useCallback(() => {
  doSomething(id);
}, [id]);

 

 

언제 사용해야 할까?

1. 자식 컴포넌트에 props로 전달되는 함수

// 안 좋은 예
// Parent가 리렌더링될 때마다 handleClick은 새로운 참조를 가진 함수가 됨
// memo로 감싸져 있지만 props인 onClick이 매번 바뀌어 불필요하게 리렌더링 됨
function Parent() {
  const [count, setCount] = useState(0);
  
  const handleClick = () => {
    console.log('clicked');
  };
  
  return <ChildComponent onClick={handleClick} />;
}

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

// 좋은 예
// 의존성이 없으므로 한 번만 생성됨
function Parent() {
  const [count, setCount] = useState(0);
  
  const handleClick = useCallback(() => {
    console.log('clicked');
  }, []);
  
  return <ChildComponent onClick={handleClick} />;
}

 

2. 무거운 연산 결과 캐싱

function ProductList({ products, filter }) {
  // filter가 바뀌지 않으면 재계산하지 않음
  const filteredProducts = useMemo(() => {
    return products
      .filter(p => p.category === filter)
      .sort((a, b) => b.price - a.price);
  }, [products, filter]);
  
  return (
    <div>
      {filteredProducts.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
}

 

3. 의존성 배열에 들어가는 객체/배열

function SearchComponent() {
  const [query, setQuery] = useState('');
  
  // 안좋은 예
  // 매 렌더링마다 새 객체 생성
  // searchOptions가 계속 바뀌어서 무한 루프됨
  const searchOptions = {
    limit: 10,
    offset: 0
  };
  
  useEffect(() => {
    fetchResults(query, searchOptions);
  }, [query, searchOptions]);
  
  // 좋은 예
  // 객체를 메모이제이션
  const searchOptions = useMemo(() => ({
    limit: 10,
    offset: 0
  }), []);
  
  useEffect(() => {
    fetchResults(query, searchOptions);
  }, [query, searchOptions]);
}

 

 

언제 사용하지 말아야 할까?

1. 단순한 연산

// 안좋은 예
const doubled = useMemo(() => count * 2, [count]);

// 좋은 예
const doubled = count * 2;

 

2. 자식에게 전달되지 않는 함수

// 안좋은 예
function MyComponent() {
  const handleClick = useCallback(() => {
    console.log('clicked');
  }, []);
  
  return <button onClick={handleClick}>Click</button>;
}

// 좋은 예
function MyComponent() {
  const handleClick = () => {
    console.log('clicked');
  };
  
  return <button onClick={handleClick}>Click</button>;
}

'Frontend' 카테고리의 다른 글

Nuxt3 - 운영 환경에서 console.log 제거하기  (0) 2026.03.26
CSS Layout 정리  (0) 2026.02.23
Vue3, Nuxt3 - Suspense  (0) 2026.02.06
Vue3, Nuxt3 - Image Lazy Loading  (0) 2026.02.06
Vue3 - vue3-virtual-scroller  (0) 2026.02.03
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/03   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함