All'alba vincerò

At dawn, I will win!

React

[React] useCallback(): 컴포넌트 리렌더링 시 불필요한 함수 생성 방지

나디아 Nadia 2024. 8. 21. 19:47

📌 useCallback()

: 컴포넌트가 리렌더링될 때, 함수가 불필요하게 다시 생성되는 것을 방지하기 위해 사용

  • 함수의 메모이제이션(기억화)을 위해 사용
  • 하위 컴포넌트에 전달하는 속성 타입이 함수인 경우 캐싱(caching)할 때 사용
  • 리렌더링 시 함수 참조를 유지하고 싶을 때, 특히 자식 컴포넌트에 콜백 함수를 전달할 때 유용하다.
  • 해당 함수의 종속성(dependency) 배열에 지정된 값들이 변경되지 않는 한, 리-렌더링 간에 동일한 함수임을 보장하여 동일한 함수 인스턴스를 재사용할 수 있다.
  • 불필요한 함수 재생성을 방지하여, 성능 최적화에 도움이 된다.
  • 메모이제이션 된 함수가 많아지면, 관리 비용이 오히려 커질 수 있기 때문에 반드시 필요할 때만 사용하는 것이 좋다.

 

 

⏩ useCallback 사용 이유

  • 함수 재생성 방지
  • : 컴포넌트가 리렌더링될 때마다 함수가 다시 생성되는데, 이 함수들이 불필요하게 자주 생성되면 성능에 영향을 미칠 수 있다. (하위 컴포넌트에 props로 전달되거나, 의존성 배열에 포함되는 경우 ➡︎ 문제 유발)
  • 참조 동일성 유지
  • : 함수가 props로 하위 컴포넌트에 전달될 때, 리렌더링 시마다 함수가 새로 생성되면 하위 컴포넌트 입장에서는 해당 함수가 변경된 것으로 인식 ➡︎ 하위 컴포넌트가 불필요하게 리렌더링될 수 있다.
  • useCallback을 사용하면 동일한 참조를 유지하여 이러한 불필요한 리렌더링을 방지할 수 있다.
  • 성능 최적화
  • : 대규모 애플리케이션이나 렌더링이 빈번하게 발생하는 경우, useCallback은 컴포넌트의 렌더링 성능을 최적화하는 데 도움을 준다.

 

 

⏩ useCallback 사용 상황

  • 콜백 함수가 리렌더링에 의해 자주 재생성되는 경우
    : 컴포넌트가 자주 리렌더링되거나 함수가 자식 컴포넌트에 전달되는 경우,
    useCallback을 사용하여 함수 참조를 유지하는 것이 좋다.

  • 하위(자식) 컴포넌트에 콜백 함수를 전달할 때
    : 하위 컴포넌트에 콜백 함수가 props로 전달될 때, 부모 컴포넌트가 리렌더링되면 해당 함수가 새로 생성된다. 
    • useCallback을 사용하면 부모 컴포넌트가 리렌더링되더라도 함수가 항상 새로 만들어지지 않고, 기존에 만들어둔 함수를 계속 사용할 수 있다.
      ➡︎ 리렌더링을 하지 않게 되어 불필요한 작업을 줄일 수 있다.
  • useEffect, useMemo 등의 의존성 배열에 포함될 때
    : 함수가 다른 훅(useEffect, useMemo 등)의 의존성 배열에 포함될 때, 해당 함수가 매번 새로 생성되면 의존성 배열이 변경된 것으로 인식되어 의도하지 않은 재실행이 발생할 수 있다.
    useCallback을 사용하면, 동일한 함수 참조를 유지하여 의도한 대로 동작하게 할 수 있다.

  • 특정 조건에 따라 함수 생성이 비싼 경우
    : 함수가 복잡한 로직을 포함하거나, 생성 비용이 비싼 경우(외부 API 호출 등), 해당 함수를 반복적으로 생성하는 것은 비효율적이기 때문에 useCallback을 사용하여 필요할 때만 함수를 생성하도록 할 수 있다.

 

const memoizedCallback = useCallback(
   () => {
      콜백 함수
   },
  [종속성 배열]
);
  • 매개변수
    • 콜백 함수
      : 메모이제이션 할 함수
      • 메모이제이션 된 결과를 반환한다.
      • React는 첫 렌더링에서 이 함수를 반환합니다. (호출 X)
      • 다음 렌더링에서 dependencies 값이 이전과 같다면, React는 같은 함수를 다시 반환한다.
      • 반대로 dependencies 값이 변경되었다면, 이번 렌더링에서 전달한 함수를 반환하고 나중에 재사용할 수 있도록 이를 저장한다. 
    • 종속성 배열 (dependencies)
      : 콜백 함수 내에서 참조되는 종속성 배열
      • 이 배열에 있는 값들에 변화가 있을 때만 콜백 함수가 다시 생성된다.
      • 빈 배열 []을 전달하면, 이 콜백 함수는 컴포넌트의 전체 라이프사이클 동안 한 번만 생성된다.

 

 

 

예제) useCallback 미사용 vs useCallback 사용


1. useCallback을 사용하지 않은 경우❌

  • handleClick 함수는 ParentComponent가 리렌더링될 때마다 새로 생성된다.
    ➡︎ 이 새로 생성된 함수가 ChildComponent에 전달되기 때문에 ChildComponent도 불필요하게 리렌더링 된다.
  • ChildComponent가 매번 리렌더링 되면서 콘솔에 "ChildComponent rendered" 메시지가 반복적으로 출력된다.
import React, { useState } from 'react';

// 하위 컴포넌트
function ChildComponent({ onClick }) {
  console.log('ChildComponent rendered');
  
  return <button onClick={onClick}>Increment</button>;
}


// 상위 컴포넌트
function ParentComponent() {
  const [count, setCount] = useState(0);

  // useCallback을 사용하지 않고 직접 함수 정의
  const handleClick = () => {
    setCount(count + 1);
  };

  console.log('ParentComponent rendered');


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

export default ParentComponent;

 

 

 

2. useCallback을 사용한 경우⭕

  • handleClick 함수는 useCallback을 사용해 메모이제이션 된다.
    ➡︎ ParentComponent가 리렌더링되더라도 함수가 새로 생성되지 않고, 기존의 함수를 계속 사용한다.
  • ChildComponent는 onClick으로 전달된 함수의 참조가 바뀌지 않았기 때문에, 리렌더링되지 않는다.
    ➡︎  콘솔에 "ChildComponent rendered" 메시지가 반복적으로 출력되지 않는다.
import React, { useState, useCallback } from 'react';

// 하위 컴포넌트
function ChildComponent({ onClick }) {
  console.log('ChildComponent rendered');
  
  return <button onClick={onClick}>Increment</button>;
}


// 상위 컴포넌트
function ParentComponent() {
  const [count, setCount] = useState(0);

  // useCallback을 사용하여 함수 참조를 유지
  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  console.log('ParentComponent rendered');


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

export default ParentComponent;

 
 


 

 

useCallback – React

The library for web and native user interfaces

ko.react.dev

 

 

18. useCallback 를 사용하여 함수 재사용하기 · GitBook

18. useCallback 을 사용하여 함수 재사용하기 useCallback 은 우리가 지난 시간에 배웠던 useMemo 와 비슷한 Hook 입니다. useMemo 는 특정 결과값을 재사용 할 때 사용하는 반면, useCallback 은 특정 함수를 새

react.vlpt.us