React를 사용하다 보면 컴포넌트가 리렌더링될 때마다 불필요하게 무거운 계산이 반복 실행되어 앱 성능이 저하되는 경우가 많다.
이 문제를 해결하기 위한 최적화 기법 중 하나가 useMemo이다.
useMemo와 일반 계산을 비교하는 예제를 통해 언제 useMemo가 필요한지 알아보자.
🧩 예제 코드
import { useMemo, useState } from 'react';
const heavyCalculation = (num: number) => {
console.log('💥 무거운 계산 실행');
let result = 0;
for (let i = 0; i < 100000000; i++) {
result += i * num;
}
return result;
};
const ExpensiveCalc = () => {
const [count, setCount] = useState(0);
const [input, setInput] = useState(1);
// ❌ 매번 계산됨
// const result = heavyCalculation(input);
// ✅ useMemo로 캐싱
const result = useMemo(() => heavyCalculation(input), [input]);
return (
<div style={{ padding: 20 }}>
<h2>useMemo 무거운 연산 캐싱 실험</h2>
<input
type="number"
value={input}
onChange={e => setInput(Number(e.target.value))}
/>
<p>계산 결과: {result}</p>
<button onClick={() => setCount(c => c + 1)}>count: {count}</button>
</div>
);
};
export default ExpensiveCalc;
🧠 상태(state) 설명
상태 | 역할 |
count | 버튼 클릭으로 증가하는 숫자이며, 계산과는 무관하다. |
input | 사용자가 입력하는 숫자이며, heavyCalculation 함수의 입력값으로 사용된다. |
count 상태는 리렌더링을 유도하는 용도로 사용된다.
🧮 무거운 계산 함수
const heavyCalculation = (num: number) => {
console.log('💥 무거운 계산 실행');
let result = 0;
for (let i = 0; i < 100000000; i++) {
result += i * num;
}
return result;
};
heavyCalculation 함수는 input 숫자를 받아서 1억 번 곱셈을 수행하는 매우 무거운 연산을 실행한다.
console.log를 통해 언제 실행되는지 확인할 수 있다.
🔎 useMemo vs 일반 계산
❌ 일반 계산
const result = heavyCalculation(input);
컴포넌트가 리렌더링될 때마다 무조건 heavyCalculation이 실행된다.
input 값이 바뀌지 않았더라도 1억 번 계산이 반복되어 성능 문제가 발생한다.
콘솔 확인 결과:
- input 값을 바꾸면 💥 무거운 계산 실행 로그가 출력된다.
- count 버튼을 누르면 💥 무거운 계산 실행 로그가 출력된다.
✅ useMemo 사용
const result = useMemo(() => heavyCalculation(input), [input]);
input 값이 바뀔 때만 heavyCalculation이 실행된다.
count 상태 변경 등 다른 리렌더링에서는 이전 계산값을 재사용한다.
콘솔 확인 결과:
- input 값을 바꾸면 💥 무거운 계산 실행 로그가 출력된다.
- count 버튼을 눌러도 로그가 출력되지 않는다 → 캐싱이 성공적으로 작동한 것이다.
🧩 전체 동작 흐름
행동 | 발생하는 일 |
페이지 최초 렌더링 | heavyCalculation 실행 |
input 값 변경 | heavyCalculation 실행 |
count 버튼 클릭 | 컴포넌트 리렌더링 → useMemo 캐싱값 사용 → heavyCalculation 실행 안 됨 |
💡 useMemo가 필요한 이유
리렌더링은 React 앱에서 자주 발생하는 자연스러운 현상이다.
하지만 렌더링될 때마다 무거운 계산이 반복되면 앱 성능이 급격히 저하될 수 있다.
useMemo를 사용하면 계산값을 기억(메모이제이션)하여 불필요한 재계산을 방지할 수 있다.
❓ 계산이 가벼운 경우에도 useMemo를 써야 할까?
계산이 가벼운 경우에는 useMemo를 사용하는 것이 오히려 성능을 저하시킬 수 있다.
useMemo 자체도 내부적으로 메모리와 비교 작업(비용)이 발생하기 때문이다.
✔️ useMemo를 사용해야 하는 경우
- 계산이 무겁고 결과 재사용이 필요한 경우
- 렌더링이 자주 발생하는 경우
- 불필요한 재계산이 성능 문제를 유발하는 경우
useMemo는 불필요한 계산으로 인한 렌더링 성능 문제를 방지하는 훅이다.
하지만 항상 사용하는 것은 바람직하지 않으며, 계산 비용이 크고 렌더링이 빈번하게 발생하는 상황에서만 사용하는 것이 좋다.
'Library & Runtime > React' 카테고리의 다른 글
[React] Virtual Scroll(가상 스크롤)로 렌더링 최적화하기 (react-window) (0) | 2025.05.05 |
---|---|
[React] 계산/렌더링 최적화: useMemo + React.memo 실험 (0) | 2025.05.04 |
[React] 자식 컴포넌트 렌더링 : 일반 함수 vs useCallback (0) | 2025.05.02 |
[React] 컴포넌트 생명주기 : useEffect, 마운트, 언마운트 (0) | 2025.05.01 |