관리 메뉴

꿈꾸는 개발자

React useCallback 사용법 본문

React.js

React useCallback 사용법

rickysin 2023. 5. 5. 21:48

의의

useCallback의 경우 함수를 메모제이션을 하기 위해 사용되는 hook으로 알려져 있다.공식문서에 따르면 re-render를 할 때 함수를 cache한다고 나와있다. 결국 위 두 말을 합쳐보면, 함수를 기억해 re-render 과정을 통해 동일한 함수를 사용하도록 최적화하는 기법이라고 보면 된다.

 

const cachedFn = useCallback(fn, dependencies)

 

코드 구조는 위와 같다. 


parameter를 살펴보면 

  • fn: cache 즉 기억/저장하고 싶은 함수를 의미한다. 공식문서에 따르면첫 render 때 fn은 호출되는 것이 아닌 반환이 되는 것이다. 그 다음 렌더링부터 만약 dependencies의 값이 변경되지 않는다면, react는 계속 같은 함수를 반환해줄 것이다. 변경된 경우는 새롭게 전달된 함수를 저장하고 그 다음부터는 갱신(?)된 함수를 반환하게 된다. 
  • dependencies:  [depen1,depen2] 처럼 배열의 형태를 가진다. useEffect, useMemo를 사용해보았다면 알 수 있듯이 의존값이 변경되면 그 변경된 값이 적용된 함수가 새롭게 추가되는 것이다. 공식문서에 따르면 react는 Object.is 비교 알고리즘을 사용해서 이전 값과 변경된 것이 있는 확인한다고 한다. 

사용하는 경우

사용법을 익혔으면 언제 사용하면 좋을 알아보자, 리액트의 경우 부모의 re-rendering이 발생하게 되면, 자식 컴포넌트까지 재귀적으로 re-render하게 된다.

function ProductPage({ productId, referrer, theme }) {
  // ...
  return (
    <div className={theme}>
      <ShippingForm onSubmit={handleSubmit} />
    </div>
  );

공식문서에 있는 코드를 살펴보면, theme이 변경되면 ProductPage가 re-reneder되게 되고, 자연스럽게 <ShippingForm/> 컴포넌트도 re-render되게 된다. 만약 내부의 컴포넌트+함수가 비교적으로 간단해 전반적으로 re-rendering이 발생하더라도 성능적으로 문제가 없다면 괜찮지만, 만약 성능 이슈가 있다면 이 때  props가 동일할 경우 re-rendering을 skip하게 하면좋다. 

import { memo } from 'react';

const ShippingForm = memo(function ShippingForm({ onSubmit }) {
  // ...
});

위 처럼 memo로 컴포넌트를 감싸준 경우를 생각해보자! 

 

자바스크립트 함수의 동등성

아시다 시피 자바스크립트 함수는 객체이다. 객체는 말 그래도 reference 값을 참조하기 때문에 겉 보기에 같은 값처럼 보여도 참조값이 다르면 다른 객체로 인식이 된다. 이러한 논리는 함수에게도 그대로 적용된다. 따라서 위와 같이 useCallback이 없는 상태에서 단순히 "memo"를 사용했을 때 caching의 의미가 퇴색된다.  

 

function ProductPage({ productId, referrer, theme }) {
  // Tell React to cache your function between re-renders...
  const handleSubmit = useCallback((orderDetails) => {
    post('/product/' + productId + '/buy', {
      referrer,
      orderDetails,
    });
  }, [productId, referrer]); // ...so as long as these dependencies don't change...

  return (
    <div className={theme}>
      {/* ...ShippingForm will receive the same props and can skip re-rendering */}
      <ShippingForm onSubmit={handleSubmit} />
    </div>
  );
}

 

위처럼 handleSubmit을 useCallback으로 감싸줌으로 인해 re-render 때마다 동일한 함수임을 확증할 수 있다. 그러면 memo를 사용한 의미가 다시 살아난다. 이것은 공식문서에 나온 useCallback을 사용하는 많은 이유 중 한 가지로 memo를 통한 re-render의 본연의 의미를 가능하게 하고자 useCallback이 사용된 것이다. 추가적인 용법은 공식문서를 참고하길 바란다. 


참고 자료

https://react.dev/reference/react/useCallback#usage

 

useCallback – React

The library for web and native user interfaces

react.dev

https://www.daleseo.com/react-hooks-use-callback/

 

React Hooks: useCallback 사용법

Engineering Blog by Dale Seo

www.daleseo.com