useCallback은 리액트에서 함수 자체를 메모리에 저장(캐싱)해두고 재사용하기 위해 사용하는 도구임
리액트 컴포넌트는 상태가 바뀌면 함수 전체가 다시 실행된다. 이때 내부에 선언된 함수들도 매번 새로 만들어지는데, 이를 방지하는 것이 useCallback의 핵심 역할이다.
자바스크립트에서 내용은 같아도 '새로 만든 함수'는 이전 함수와 다른 주소값을 가진다. 이 미세한 차이가 리액트 성능에 큰 영향을 미친다.
❖ 함수 재생성의 문제점:
memo를 사용 중인 자식 컴포넌트에 이 함수를 전달하면, 자식은 "어? Props(함수 주소)가 바뀌었네?"라고 착각하여 불필요하게 다시 그려짐useCallback은 "이 함수는 데이터가 바뀌지 않는 한, 새로 만들지 말고 예전에 만든 거 그대로 써!"라고 리액트에게 지시하는 것이다.
const handleRemovePlace = useCallback(
async function handleRemovePlace() {
// ... 이 안에서 userPlaces 상태를 참조함
console.log(userPlaces);
},
[userPlaces, setUserPlaces] // 👈 의존성 배열
);
함수는 만들어질 당시의 변수 값들을 기억한다. 만약 의존성 배열을 잘못 관리하면 '과거의 데이터'에 갇히는 버그가 발생한다.
❖ 의존성 배열 관리 규칙:
비워둘 때([]): 컴포넌트가 처음 생길 때의 옛날 데이터만 계속 기억함 (클로저 문제 발생)
상태 포함([userPlaces]): 해당 상태가 바뀔 때마다 함수도 최신 데이터를 알 수 있게 업데이트됨
함수 내부에서 참조하는 모든 상태와 Props는 반드시 의존성 배열에 포함해야 안전함