import type { DependencyList } from "react";
import { shallowEquals } from "../equals";
import { useRef } from "./useRef";
export function useMemo<T>(factory: () => T, _deps: DependencyList, _equals = shallowEquals): T {
// 단 한 번만 초기화
const memoizatedRef = useRef<{ deps: DependencyList; result: T } | null>(null);
if (memoizatedRef.current === null || !_equals(memoizatedRef.current.deps, _deps)) {
// 새로운 값으로 업데이트 (랜더링을 유발하지 않는 방식)
memoizatedRef.current = { deps: _deps, result: factory() };
}
// 저장된 result 반환
return memoizatedRef.current.result;
}

useMemo는 다음과 같은 4가지의 뚜렷한 성격을 가지고 있습니다.
useMemo의 가장 핵심적인 성격입니다. 이 함수는 계산(factory 함수 실행)을 최대한 피하려고 합니다.
꼭 필요할 때만, 단 한 번만 계산합니다.
1 if (/* 조건 */) {
2 // 조건에 합당 해야지만 factory 실행
3 memoizatedRef.current = { deps: _deps, result: factory() };
4 }
if 조건(처음이거나, 의존성이 바뀌었을 때)이 충족되지 않으면, factory()는 실행 되지 않음.
이는 비싼 계산을 건너뛰어 애플리케이션의 성능을 높여주는 useMemo의 존재 이유
useMemo는 factory 함수를 실행한 결과값은 간직하지만, 그 결과를 만들어낸 과정(factory 함수 자체)은 기억하지 않습니다.
1 // 저장하는 것: deps와 result
2 useRef<{ deps: DependencyList; result: T } | null>(null);
3
4 // ...
5
6 // 저장소에 factory 함수 자체를 넣는 코드는 없음.
7 memoizatedRef.current = { deps: _deps, result: factory() };
useRef 상자 안에는 deps와 result만 저장됩니다. 이 때문에 useMemo를 호출할 때마다 매번 factory 함수를 인자로 넘겨줘야 하는 것입니다.
"factory 써볼까... 뭐야.. 전이랑 지금이랑 달라진게 없네? 그럼 그냥 있던 거 쓰자" 라고 알려주는 것.
기본적으로 useMemo는 의존성 배열에 들어있는 객체나 배열의 속까지 들여다보지 않습니다.
겉모습(참조값)만 보고 "어? 다른 값이네!"라고 섣불리 판단하는 경향이 있습니다.
1 export function useMemo<T>(..., _equals =
shallowEquals): T { ... }
shallowEquals는 객체나 배열의 내용이 같더라도, 메모리 주소가 다르면 다르다고 판단합니다.
그래서 useMemo(() => {...}, [{}]) 와 같은 코드가 매번 재실행되는 것입니다.
이 "얕은 기억력"은 useMemo를 사용할 때 가장 주의해야 할 특징 중 하나입니다.
useMemo는 기본적으로 얕은 기억력을 가졌지만, 사용자가 원한다면 "판단 기준"을 바꿀 수 있는 유연함도 갖추고 있습니다.
1 export function useMemo<T>(..., _equals = shallowEquals): T {
2 // ...
3 if (... || !_equals(memoizatedRef.current.deps, _deps)) { ... }
4 // ...
5 }
useMemo는 자기가 가진 shallowEquals만 고집하지 않습니다.
사용자가 deepEquals나 다른 커스텀 비교 함수를 _equals 인자로 넣어주면, 그 함수를 사용해 의존성을 비교 합니다.
이는 useMemo를 더 강력하고 다양한 상황에 대처할 수 있게 만들어주는 매우 실용적인 성격입니다.