
리액트에서 컴포넌트는 상태나 props가 변경될 때마다 리렌더링된다.
불필요한 계산이 반복되면 당연히 성능 저하가 발생한다.
useMemo는 이러한 문제를 해결하기 위해 제공되는 React의 Hook이다. 비용이 큰 계산을 메모이제이션(Memoization) 하여 성능을 최적화하는 것이다.
const userLocale = useMemo(
() => session.get(sessionCxt, "locale") || defaultLocale,
[sessionCxt]
);
useMemo를 사용하지 않은 경우와 사용한 경우의 차이를 보자
function Example({ a, b }) {
const computeExpensiveValue = (a, b) => {
console.log("비용이 큰 계산 실행");
return a + b;
};
const result = computeExpensiveValue(a, b);
return <div>결과: {result}</div>;
}
Example Component가 리렌더링 될 때마다 계산하는 함수가 실행 -> 비효율적!
import React, { useMemo } from "react";
function Example({ a, b }) {
const computeExpensiveValue = (a, b) => {
console.log("비용이 큰 계산 실행");
return a + b;
};
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
return <div>결과: {memoizedValue}</div>;
}
첫번째 인자는 콜백함수이고, 이 함수에서 리턴하는 값이 메모된다.
두번째 인자는 의존성 배열임
memoizedValue에 할당함으로써 a나 b가 변경되지 않는 한, computeExpensiveValue는 다시 실행되지 않음
큰 배열을 필터링 할 때 useMemo를 활용
import React, { useMemo } from "react";
function FilteredList({ items, searchTerm }) {
const filteredItems = useMemo(() => {
console.log("필터링 작업 실행");
return items.filter(item => item.includes(searchTerm));
}, [items, searchTerm]);
return (
<ul>
{filteredItems.map(item => (
<li key={item}>{item}</li>
))}
</ul>
);
}
function ExpensiveCalculation({ number }) {
const factorial = useMemo(() => {
console.log("팩토리얼 계산 실행");
const computeFactorial = n => (n <= 1 ? 1 : n * computeFactorial(n - 1));
return computeFactorial(number);
}, [number]);
return <div>팩토리얼: {factorial}</div>;
}
function SortedTable({ data, sortKey }) {
const sortedData = useMemo(() => {
console.log("데이터 정렬 실행");
return [...data].sort((a, b) => a[sortKey].localeCompare(b[sortKey]));
}, [data, sortKey]);
return (
<table>
<tbody>
{sortedData.map(row => (
<tr key={row.id}>
<td>{row.name}</td>
</tr>
))}
</tbody>
</table>
);
}
최적화 시켜준다고 무작정 사용해서는 안됨! 정말 자주 변경이 이루어지는 처리에서만 활용하면 효율이 좋다.
반복문이나 조건문 내부에서는 호출할 수 없다.
새로운 데이터를 만들 때 그다지 복잡하지 않다면 메모이제이션 하는 비용보다 그냥 새로운 값을 만들어주는게 나을 수 있다.