useMemo
란?useMemo
는 React Hook중 하나로, 연산 비용이 큰 계산의 불필요한 재연산을 방지하고 성능을 최적화하는데 사용됩니다.
useMemo
는 특정 값이 변경되지 않는 한 기존의 계산된 값을 재사용하여, 불필요한 연산을 줄이고 렌더링 성능을 개선합니다.
useMemo
vs 기존 게산 방식React에서는 컴포넌트가 리렌더링될 때마다 모든 계산이 다시 수행됩니다. 이는 연산량이 많거나 데이터가 많을 경우 불필요한 성능 저하를 초래할 수 있습니다.
import { useState } from "react";
function MyComponent({ numbers }) {
const [count, setCount] = useState(0);
// 배열의 합계를 계산
const total = numbers.reduce((sum, num) => sum + num, 0);
return (
<div>
<h1>합계: {total}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
❗ 불필요한 연산 발생: numbers
가 변경되지 않더라도, total
을 계산하는 연산이 컴포넌트가 리렌더링될 때마다 실행됩니다.
useMemo
로 개선된 점useMemo
를 사용하면 연산 결과를 메모이제이션하여, 컴포넌트가 리렌더링되더라도 특정 값이 변경되지 않는 한 재연산을 방지할 수 있습니다.
import { useState, useMemo } from "react";
function MyComponent({ numbers }) {
const [count, setCount] = useState(0);
// useMemo를 사용하여 불필요한 연산 방지
const total = useMemo(() => {
console.log("총합 계산 중...");
return numbers.reduce((sum, num) => sum + num, 0);
}, [numbers]);
return (
<div>
<h1>합계: {total}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
✔️ 불필요한 재연산 방지: numbers
배열이 변경되지 않는 한 total
을 다시 계산하지 않고 기존 값을 유지합니다.
✔️ 렌더링 최적화: 상태 변경(count
)으로 인한 리렌더링 시에도 total
계산이 불필요하게 실행되지 않습니다.
useMemo
사용 방법useMemo
는 함수와 의존성 배열을 인자로 받으며, 의존성 배열에 포함된 값이 변경될 때마다 새로운 값을 계산합니다.
const memoizedValue = useMemo(() => {
// 계산식
return computedValue;
}, [dependencies]);
📌 파라미터
() => { ... }
: 메모이제이션할 계산 함수[dependencies]
: 해당 연상이 의존하는 값들을 배열로 나열, 의존성 배열에 포함된 값이 변경될 때만 연산 수행📌 반환 값
memoizedValue
: 메모이제이션된 값으로, 동일한 값이 유지되며 불필요한 연산을 방지useMemo
이해하기function ExpensiveComponent({ numbers }) {
const total = useMemo(() => {
console.log("총합 계산 중...");
return numbers.reduce((sum, num) => sum + num, 0);
}, [numbers]);
return <h1>합계: {total}</h1>;
}
✔️ useMemo
를 사용하여 numbers
가 변경되지 않는 한 총합 계산을 다시 수행하지 않습니다.
✔️ 연산량이 많은 경우 불필요한 CPU 사용을 줄이고 렌더링 성능 개선됩니다.
💡 그럼 그냥 의존성 배열을 비우면 되는 거 아닌가?
[]
를 넣으면 최초 렌더링 시에만 연산이 수행되지만, 특정 값이 변경될 때 새로운 연산이 필요하면 문제가 발생할 수 있음.
function FilteredList({ items, query }) {
const filteredItems = useMemo(() => {
console.log("필터링 실행 중...");
return items.filter(item => item.includes(query));
}, [items, query]);
return (
<ul>
{filteredItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}
✔️ query
나 items
가 변경될 때만 필터링 로직이 실행됩니다.
✔️ 그렇지 않으면 이전 필터링된 결과를 그대로 재사용하여 성능 최적화합니다.