FE develop/React

useCallback에 대해 알아보자

hoj0806 2025. 4. 18. 15:57

🧠 useCallback에 대해 알아보자

 

useCallback 훅은 useMemo와 마찬가지로 컴포넌트를 최적화하기 위해 사용하는 memoization 기법 중 하나입니다. 두 훅은 모두 첫 번째 인자로 콜백 함수, 두 번째 인자로 의존성 배열을 받습니다. 하지만 중요한 차이점이 하나 있습니다

 

✅ useMemo는 값을 memoization하고,
✅ useCallback은 함수 자체를 memoization합니다.

왜 함수도 memoization이 필요할까?

 

자바스크립트에서 함수는 객체입니다. 따라서 컴포넌트가 재렌더링될 때마다 함수는 새로 생성됩니다. 이렇게 매 렌더링마다 동일한 로직을 가진 함수가 새로 만들어지면, 해당 함수가 의존성으로 연결된 useEffect나 React.memo 등에서 불필요하게 재실행되는 문제가 생길 수 있습니다.

 

이럴 때 useCallback을 사용하면, 의존성 배열의 값이 변경되지 않는 한 이전에 생성된 함수를 재사용하게 되어 렌더링 성능을 향상시킬 수 있습니다.

 

 

 

예제 1️⃣: useCallback 없이 작성한 코드

 
import { useEffect, useState } from "react";

function App() {
  const [number, setNumber] = useState(0);
  const [toggle, setToggle] = useState(true);

  const someFunction = () => {
    console.log(`someFunc : number : ${number}`);
  };

  useEffect(() => {
    console.log("someFunction 변경!");
  }, [someFunction]);

  return (
    <div>
      <input
        type='number'
        value={number}
        onChange={(e) => setNumber(e.target.value)}
      />
      <button onClick={() => setToggle(!toggle)}>{toggle.toString()}</button>
      <button onClick={someFunction}>Call someFunc</button>
    </div>
  );
}

export default App;

 

❗ 문제점

위 코드에서 toggle 버튼을 클릭하면 number 값은 변하지 않지만, 컴포넌트는 재렌더링됩니다. 이때 someFunction 함수는 렌더링마다 새로 생성되므로, useEffect 내부의 console.log("someFunction 변경!")가 매번 실행됩니다.

 

 

예제 2️⃣: useCallback으로 최적화한 코드

import { useCallback, useEffect, useState } from "react";

function App() {
  const [number, setNumber] = useState(0);
  const [toggle, setToggle] = useState(true);

  const someFunction = useCallback(() => {
    console.log(`someFunc : number : ${number}`);
  }, [number]);

  useEffect(() => {
    console.log("someFunction 변경!");
  }, [someFunction]);

  return (
    <div>
      <input
        type='number'
        value={number}
        onChange={(e) => setNumber(e.target.value)}
      />
      <button onClick={() => setToggle(!toggle)}>{toggle.toString()}</button>
      <button onClick={someFunction}>Call someFunc</button>
    </div>
  );
}

export default App;

 

✅ 최적화된 점

  • useCallback을 사용해 someFunction을 memoization했기 때문에, number 값이 바뀌지 않는 한 해당 함수는 새로 생성되지 않습니다.
  • 따라서 toggle 버튼을 눌러 컴포넌트가 재렌더링되더라도 someFunction의 참조는 유지되어 useEffect가 불필요하게 실행되지 않습니다.

🔎 정리

  • useCallback은 함수의 재생성을 방지하기 위해 사용됩니다.
  • 의존성 배열의 값이 바뀔 때만 함수가 새로 생성됩니다.
  • 불필요한 useEffect 호출, React.memo의 재렌더링 등을 막아 성능을 향상시킬 수 있습니다.
  • 하지만 너무 남발하면 오히려 코드 가독성을 해치고 성능에 부정적인 영향을 줄 수 있으므로, 정말 필요한 경우에만 사용하는 것이 좋습니다.