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의 재렌더링 등을 막아 성능을 향상시킬 수 있습니다.
- 하지만 너무 남발하면 오히려 코드 가독성을 해치고 성능에 부정적인 영향을 줄 수 있으므로, 정말 필요한 경우에만 사용하는 것이 좋습니다.