둘 다 render 사이에 무언가를 캐시하여 매번 재계산/재생성되지 않도록 합니다:
- **
useMemo**는 계산된 값을 캐시합니다. - **
useCallback**은 를 캐시합니다(이는 와 같습니다).
useMemo(() => fn, deps)이들은 (a) 비용이 큰 작업의 반복을 피하고 (b) memo된 자식이 의존하는 참조 동일성이 깨지는 것을 방지하기 위해 존재합니다.
function Table({ rows, onSelect }) {
// (a) 비용이 큰 계산 — `rows`가 변경될 때만 재계산
const sorted = useMemo(() => rows.slice().sort(byName), [rows]);
// (b) 안정적인 함수 identity — React.memo 자식이 re-render되지 않고,
// 이에 의존하는 effect가 다시 실행되지 않도록 함
const handleSelect = useCallback(id => onSelect(id), [onSelect]);
return <Grid rows={sorted} onSelect={handleSelect} />;
}
useCallback이 없으면 handleSelect는 매 render마다 완전히 새로운 함수가 됩니다. React.memo(Grid)는 "새로운" prop을 보고 어쨌든 re-render하여 memoization을 무력화합니다. memo된 자식에게 전달되거나 useEffect 의존성 배열에 사용되는 객체도 마찬가지입니다.
const x = useMemo(() => a + b, [a, b]); // ❌ 무의미함 — 덧셈이 memoize보다 저렴함
useMemo/useCallback을 사용하면 노이즈가 늘고 오히려 더 느려질 수도 있습니다. (React 19의 컴파일러는 자동으로 memoize할 수 있어 그 필요성을 줄여줍니다.)주니어부터 시니어까지 상세한 답변이 포함된 IT 면접 질문 라이브러리.
후원하기