동일한 값을 반환하는 함수를 계속 호출해야 한다면 필요없는 랜더링이 계속 반복되게 될 것이다. 이럴 때, 가장 처음 해당 값을 반환할 때 그 값을 메모리에 저장하게 된다. 이렇게 하면 랜더링 될때마다 컴포넌트가 그려지면서 함수를 호출하고 계산을 하는 것이 아니라, 이미 저장한 값을 꺼내와서 반환할 수 있게 된다. 이러한 기법을 캐싱을 한다고 표현한다.
// as-is
const value = 반환할_함수();
// to-be
const value = useMemo(()=> {
return 반환할_함수()
}, [dependencyArray]);
이렇게하면 의존성 배열에 저장된 값의 변동이 있을 때만 연산을 수행하고 그 외에는 메모이제이션 해둔 값을 꺼내와서 쓰기만 한다.
ex)
const heavyWork = () => {
for (let i = 0; i < 1000000000; i++) {}
return 100;
};
// CASE 1 : useMemo를 사용하지 않았을 때
const value = heavyWork();
// CASE 2 : useMemo를 사용했을 때
// const value = useMemo(() => heavyWork(), []);
useMemo를 사용하지 않으면 컴포넌트가 리랜더링 될때마다 10억번의 반복문을 순회하면서 같은 값을 반환하게 된다. 하지만 useMemo를 사용하면 100이라는 반환값을 메모리에 저장해뒀다가 의존성 배열에 저장된 값에 변동이 있을 때만 연산을 수행하게 된다.
useMemo를 남발하게 되면 별도의 메모리 확보를 너무나 많이 하게 되기 때문에 오히려 성능이 악화될 수 있다.