React의 useCallback Hook을 길들이는 방법 배우기

게시 됨: 2022-04-27

React.js가 최근 몇 년 동안 널리 보급되었다는 것은 비밀이 아닙니다. 이제 Facebook 및 WhatsApp을 포함하여 인터넷에서 가장 저명한 플레이어가 선택한 JavaScript 라이브러리입니다.

상승의 주요 이유 중 하나는 버전 16.8에 후크가 도입되었기 때문입니다. React 후크를 사용하면 클래스 구성 요소를 작성하지 않고도 React 기능을 활용할 수 있습니다. 이제 후크가 있는 기능적 구성 요소는 개발자가 React 작업을 위한 필수 구조가 되었습니다.

이 블로그 게시물에서는 메모이제이션으로 알려진 기능적 프로그래밍의 기본 부분을 다루기 때문에 하나의 특정 후크인 useCallback 에 대해 더 깊이 파고들 것입니다. useCallback 후크를 언제 어떻게 활용하고 성능 향상 기능을 최대한 활용해야 하는지 정확히 알게 될 것입니다.

준비가 된? 뛰어들자!


메모이제이션이란?

메모이제이션은 복잡한 함수가 출력을 저장하여 다음에 동일한 입력으로 호출될 때입니다. 캐싱과 유사하지만 더 로컬 수준입니다. 복잡한 계산을 건너뛰고 이미 계산된 대로 더 빠르게 출력을 반환할 수 있습니다.

이것은 메모리 할당 및 성능에 상당한 영향을 미칠 수 있으며 그 부담은 useCallback 후크가 완화하기 위한 것입니다.

React의 useCallback 대 useMemo

이 시점에서 useMemo useCallback 다른 훅과 잘 짝을 이룬다는 것을 언급할 가치가 있습니다. 우리는 둘 다 논의할 것이지만, 이 글에서는 useCallback 을 주요 주제로 집중할 것입니다.

주요 차이점은 useMemo 는 메모화된 값을 반환하는 반면 useCallback 은 메모화된 함수를 반환한다는 것입니다. 즉, useMemo 는 계산된 값을 저장하는 데 사용되는 반면 useCallback 은 나중에 호출할 수 있는 함수를 반환합니다.

이러한 후크는 종속성(예: state 또는 props) 중 하나가 변경되지 않는 한 캐시된 버전을 제공합니다.

작동 중인 두 가지 기능을 살펴보겠습니다.

 import { useMemo, useCallback } from 'react' const values = [3, 9, 6, 4, 2, 1] // This will always return the same value, a sorted array. Once the values array changes then this will recompute. const memoizedValue = useMemo(() => values.sort(), [values]) // This will give me back a function that can be called later on. It will always return the same result unless the values array is modified. const memoizedFunction = useCallback(() => values.sort(), [values])

위의 코드 스니펫은 인위적인 예이지만 두 콜백 간의 차이점을 보여줍니다.

  1. memoizedValue[1, 2, 3, 4, 6, 9] 배열이 됩니다. values ​​변수가 유지되는 한 memoizedValue 도 마찬가지이며 다시 계산되지 않습니다.
  2. memoizedFunction[1, 2, 3, 4, 6, 9] 배열을 반환하는 함수입니다.

이 두 콜백의 장점은 캐싱되어 종속성 배열이 변경될 때까지 계속 매달려 있다는 것입니다. 즉, 렌더링 시 가비지 수집이 되지 않습니다.

React.js는 이제 Facebook 및 WhatsApp을 비롯한 많은 인터넷 대기업이 선택한 JavaScript 라이브러리입니다. 이 가이드에서 자세히 알아보기 ️ 트윗하려면 클릭

렌더링 및 반응

React에서 메모이제이션이 중요한 이유는 무엇입니까?

React가 구성 요소를 렌더링하는 방법과 관련이 있습니다. React는 메모리에 저장된 가상 DOM을 사용하여 데이터를 비교하고 업데이트할 항목을 결정합니다.

가상 DOM은 React의 성능을 돕고 애플리케이션을 빠르게 유지합니다. 기본적으로 구성 요소의 값이 변경되면 전체 구성 요소가 다시 렌더링됩니다. 이렇게 하면 React가 사용자 입력에 "반응"하고 페이지를 다시 로드하지 않고도 화면을 업데이트할 수 있습니다.

변경 사항이 해당 구성 요소에 영향을 미치지 않으므로 구성 요소를 렌더링하고 싶지 않습니다. 여기에서 useCallbackuseMemo 를 통한 메모화가 편리합니다.

React가 컴포넌트를 다시 렌더링할 때 컴포넌트 내부에 선언한 함수도 다시 생성합니다.

함수의 동등성을 다른 함수와 비교할 때 항상 거짓임을 유의하십시오. 함수도 객체이기 때문에 자기 자신과만 같을 것입니다.

 // these variables contain the exact same function but they are not equal const hello = () => console.log('Hello Matt') const hello2 = () => console.log('Hello Matt') hello === hello2 // false hello === hello // true

다시 말해서, React가 구성 요소를 다시 렌더링할 때 구성 요소에 선언된 모든 기능이 새 기능으로 표시됩니다.

이것은 대부분의 경우 문제가 없으며 간단한 함수는 계산하기 쉽고 성능에 영향을 미치지 않습니다. 그러나 함수가 새 함수로 표시되는 것을 원하지 않는 다른 경우에는 useCallback 을 사용하여 도움을 받을 수 있습니다.

"언제 함수를 새로운 함수로 보지 않기를 원합니까?"라고 생각할 수 있습니다. 음, useCallback 이 더 합리적인 경우가 있습니다.

  1. 메모화되는 다른 구성 요소에 함수를 전달하고 있습니다( useMemo ).
  2. 함수에는 기억해야 하는 내부 상태가 있습니다.
  3. 함수는 예를 들어 useEffect 와 같은 다른 후크의 종속성입니다.

React useCallback의 성능 이점

useCallback 을 적절하게 사용하면 애플리케이션 속도를 높이고 필요하지 않은 경우 구성 요소가 다시 렌더링되는 것을 방지할 수 있습니다.

예를 들어 다음과 같이 많은 양의 데이터를 가져오고 해당 데이터를 차트나 그래프 형식으로 표시하는 구성 요소가 있다고 가정해 보겠습니다.

PHP, MySQL, Reddis 및 외부(기타)의 전체 트랜잭션 시간을 밀리초 단위로 비교하는 다채로운 막대 그래프.
React 컴포넌트를 사용하여 생성된 막대 그래프.

데이터 시각화 구성 요소의 상위 구성 요소가 다시 렌더링되지만 변경된 props 또는 state가 해당 구성 요소에 영향을 미치지 않는다고 가정합니다. 이 경우 데이터를 다시 렌더링하고 모든 데이터를 다시 가져오는 것을 원하지 않거나 필요하지 않을 수 있습니다. 이러한 재렌더링 및 다시 가져오기를 방지하면 사용자의 대역폭을 절약하고 더 부드러운 사용자 경험을 제공할 수 있습니다.

다운타임 및 WordPress 문제로 어려움을 겪고 계십니까? Kinsta는 시간을 절약하도록 설계된 호스팅 솔루션입니다! 우리의 기능을 확인하십시오

React useCallback의 단점

이 후크는 성능을 향상시키는 데 도움이 될 수 있지만 함정도 있습니다. useCallback (및 useMemo )을 사용하기 전에 고려해야 할 몇 가지 사항은 다음과 같습니다.

  • 가비지 컬렉션: 아직 메모화되지 않은 다른 기능은 메모리를 확보하기 위해 React에 의해 폐기됩니다.
  • 메모리 할당: 가비지 수집과 유사하게 메모화된 기능이 많을수록 더 많은 메모리가 필요합니다. 또한 이러한 콜백을 사용할 때마다 캐시된 출력을 제공하기 위해 더 많은 메모리를 사용해야 하는 React 내부에 많은 코드가 있습니다.
  • 코드 복잡성: 이러한 후크에서 함수 래핑을 시작하면 코드의 복잡성이 즉시 증가합니다. 이제 이러한 후크가 사용되는 이유와 올바르게 사용되었는지 확인하는 데 대한 더 많은 이해가 필요합니다.

위의 함정을 알고 있으면 스스로 걸려 넘어지는 두통을 줄일 수 있습니다. useCallback 사용을 고려할 때 성능상의 이점이 단점을 능가하는지 확인하십시오.

React useCallback 예제

아래는 Button 구성 요소와 Counter 구성 요소가 있는 간단한 설정입니다. Counter에는 두 가지 상태가 있으며 각각 Counter 구성 요소 상태의 별도 부분을 업데이트하는 두 개의 Button 구성 요소를 렌더링합니다.

Button 구성 요소는 handleClick 과 name이라는 두 가지 소품을 사용합니다. Button이 렌더링될 때마다 콘솔에 기록됩니다.

 import { useCallback, useState } from 'react' const Button = ({handleClick, name}) => { console.log(`${name} rendered`) return <button onClick={handleClick}>{name}</button> } const Counter = () => { console.log('counter rendered') const [countOne, setCountOne] = useState(0) const [countTwo, setCountTwo] = useState(0) return ( <> {countOne} {countTwo} <Button handleClick={() => setCountOne(countOne + 1)} name="button1" /> <Button handleClick={() => setCountTwo(countTwo + 1)} name="button1" /> </> ) }

이 예에서 두 버튼 중 하나를 클릭할 때마다 콘솔에 다음이 표시됩니다.

 // counter rendered // button1 rendered // button2 rendered

이제 useCallbackhandleClick 함수에 적용하고 Button을 React.memo 로 감싸면 useCallback 제공하는 것을 볼 수 있습니다. React.memouseMemo 와 유사하며 구성 요소를 메모할 수 있습니다.

 import { useCallback, useState } from 'react' const Button = React.memo(({handleClick, name}) => { console.log(`${name} rendered`) return <button onClick={handleClick}>{name}</button> }) const Counter = () => { console.log('counter rendered') const [countOne, setCountOne] = useState(0) const [countTwo, setCountTwo] = useState(0) const memoizedSetCountOne = useCallback(() => setCountOne(countOne + 1), [countOne) const memoizedSetCountTwo = useCallback(() => setCountTwo(countTwo + 1), [countTwo]) return ( <> {countOne} {countTwo} <Button handleClick={memoizedSetCountOne} name="button1" /> <Button handleClick={memoizedSetCountTwo} name="button1" /> </> ) }

이제 버튼 중 하나를 클릭하면 콘솔에 로그인하기 위해 클릭한 버튼만 표시됩니다.

 // counter rendered // button1 rendered // counter rendered // button2 rendered

버튼 구성 요소에 메모이제이션을 적용했으며 여기에 전달된 소품 값이 동일한 것으로 보입니다. 두 개의 handleClick 함수는 캐시되며 종속성 배열의 항목 값이 변경될 때까지 React에서 동일한 함수로 표시됩니다(예: countOne , countTwo ).

useCallback 후크를 사용하는 방법과 시기와 성능 향상 기능을 최대한 활용하는 방법을 정확히 배울 준비가 되셨습니까? 여기에서 시작하세요! 트윗하려면 클릭

요약

useCallbackuseMemo 만큼 멋진 기능이지만 특정 사용 사례가 있음을 기억하십시오. 모든 기능을 이러한 후크로 감싸서는 안 됩니다. 함수가 계산적으로 복잡한 경우 메모화된 구성 요소에 전달된 다른 후크 또는 소품의 종속성이 useCallback 에 도달하려는 좋은 지표입니다.

이 기사가 이 고급 React 기능을 이해하고 그 과정에서 함수형 프로그래밍에 대한 자신감을 높이는 데 도움이 되었기를 바랍니다!