본문 바로가기

WEB개발/REACT

[hook] useCallback

 

1. React.memo로 감싼 자식에게 함수를 내려줄 때

const Child = React.memo(({ onClick }: { onClick: () => void }) => {
  console.log("Child render");
  return <button onClick={onClick}>클릭</button>;
});

function Parent() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    console.log("click");
  }, []);

  return (
    <>
      <button onClick={() => setCount(c => c + 1)}>+</button>
      <Child onClick={handleClick} />
    </>
  );
}

 

useCallback 없으면
→ 부모 리렌더 → 매번 새로운 함수 생성 → Child도 리렌더

 

 useCallback 있으면
→ 함수 참조 유지 → Child 리렌더 방지

 

 

2. useEffect / useMemo 의존성으로 “함수”가 들어갈 때

const fetchData = useCallback(() => {
  api.get("/data");
}, []);

useEffect(() => {
  fetchData();
}, [fetchData]); // 안정적인 참조 필요

 

❌ useCallback 없으면
→ 렌더마다 함수 변경 → effect 매번 실행

 

이건 린트 때문에 억지로 쓰는 경우도 많음
(실무에서 제일 흔한 useCallback 사용 이유)

 

3. 자식 컴포넌트가 렌더 비용이 클 때

<HeavyChart onChange={handleChange} />

 

 

 



함수 재생성은 왜 문제가 아닌가?

 

이게 렌더마다 다시 만들어지는 비용은:
👉 JS 엔진 기준으로 거의 공짜 수준

반면 React 렌더링에서 진짜 비싼 건:

 

  • 컴포넌트 호출
  • reconciliation : 이전 렌더 결과와 새 렌더 결과를 비교해서 실제 DOM을 어떻게 바꿀지 계산하는 과정
  • 비싼 건 리렌더 + diff + 자식 트리


👉 함수 재생성 자체는 병목이 아님

 

그럼 useCallback은 “공짜”냐? ❌
아님. 숨겨진 비용이 있음.

 

useCallback 내부에서 실제로 하는 일 => useCallback(fn, deps)  // ≈ useMemo(() => fn, deps)
즉 매 렌더마다: deps 배열 비교

'WEB개발 > REACT' 카테고리의 다른 글

pull to refresh  (0) 2026.01.12
react router (navigate)  (0) 2025.12.17
[hook] useEffect  (0) 2025.12.16
[hook] useQuery  (0) 2025.12.12
VITE  (0) 2025.03.17