개요
useMemo
는 컴포넌트가 리렌더링될 때 계산 결과를 캐시(저장)할 수 있게 해주는 React Hook입니다. 복잡한 계산을 반복하지 않도록 하여 성능을 최적화할 수 있습니다.
const cachedValue = useMemo(calculateValue, dependencies)
Reference
useMemo(calculateValue, dependencies)
컴포넌트의 최상위에서 useMemo
를 호출하면, 계산 결과를 리렌더링 사이에 캐시할 수 있습니다.
import { useMemo } from 'react';
function TodoList({ todos, tab }) {
const visibleTodos = useMemo(
() => filterTodos(todos, tab),
[todos, tab]
);
// ...
}
파라미터
calculateValue
: 캐시하고 싶은 값을 계산하는 함수. 인자를 받지 않고, 어떤 타입이든 반환할 수 있습니다. 순수 함수여야 하며, React가 필요할 때 호출합니다.dependencies
: calculateValue에서 참조하는 모든 반응형 값의 배열. 값이 바뀌면 calculateValue가 다시 실행되고, 그렇지 않으면 이전 값을 재사용합니다.
반환값
- 최초 렌더에서는 calculateValue의 반환값을, 이후에는 dependencies가 바뀌지 않는 한 이전 값을 반환합니다.
주의사항 및 Caveats
- 반드시 컴포넌트의 최상위(혹은 커스텀 Hook 내부)에서만 호출해야 하며, 반복문/조건문 내부에서는 사용할 수 없습니다.
- Strict Mode(개발 환경)에서는 calculateValue가 두 번 호출될 수 있습니다(순수성 검증 목적). 한 번의 결과만 사용됩니다.
- React는 캐시를 임의로 폐기할 수 있습니다(예: 컴포넌트 파일 수정, Suspense 등). useMemo는 성능 최적화 용도로만 사용하세요. 값의 보존이 정말 필요하다면 state나 ref를 사용하세요.
사용법
복잡한 계산 결과 캐싱하기
import { useMemo } from 'react';
function TodoList({ todos, tab, theme }) {
const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]);
// ...
}
- 첫 번째 인자로 계산 함수를, 두 번째 인자로 의존성 배열을 전달합니다.
- 의존성 배열의 값이 바뀌지 않으면, 이전 계산 결과를 재사용합니다.
객체/함수 반환 시 주의
// 잘못된 예시 (undefined 반환)
const searchOptions = useMemo(() => {
matchMode: 'whole-word',
text: text
}, [text]);
// 올바른 예시 (return 또는 괄호로 객체 반환)
const searchOptions = useMemo(() => ({
matchMode: 'whole-word',
text: text
}), [text]);
// 또는
const searchOptions = useMemo(() => {
return {
matchMode: 'whole-word',
text: text
};
}, [text]);
트러블슈팅
계산이 매번 실행되는 경우
- 의존성 배열을 빠뜨리면 매 렌더마다 계산이 실행됩니다.
- 의존성 배열의 값이 매번 새로 생성되는 객체/함수라면, 매번 계산이 실행됩니다. 의존성도 useMemo/useCallback 등으로 메모이제이션하세요.
useMemo를 반복문에서 사용할 수 없는 경우
- useMemo는 컴포넌트 최상위에서만 호출해야 하므로, 리스트 내에서 직접 호출할 수 없습니다. 대신 각 아이템을 별도 컴포넌트로 분리해 그 안에서 useMemo를 사용하세요.
useMemo vs useCallback
- useMemo로 함수를 반환할 수도 있지만, 함수 메모이제이션이 목적이라면 useCallback을 사용하는 것이 더 간결합니다.
반응형