-
useMemo는 React에서 제공하는 훅으로, 값을 메모이제이션(Memoization) 하여 불필요한 계산을 방지하고 성능을 최적화하는 데 사용됩니다. 특정 값이나 계산이 의존성(dependencies)이 변경되지 않는 한 재계산되지 않도록 보장합니다.
기본 개념
useMemo는 복잡한 계산이나 무거운 연산을 수행해야 하는 값이 컴포넌트 렌더링 때마다 재계산되는 것을 방지합니다. 이를 통해 성능을 최적화할 수 있습니다.
const memoizedValue = useMemo(() => { return computeExpensiveValue(a, b); }, [a, b]);
- computeExpensiveValue(a, b): 계산을 수행하는 함수.
- [a, b]: 의존성 배열로, 이 값들이 변경될 때만 computeExpensiveValue가 다시 실행됩니다.
- memoizedValue: useMemo가 반환하는 메모이제이션된 값.
사용 목적
- 성능 최적화:
- 연산 비용이 높은 함수가 매번 실행되지 않도록 방지.
- 렌더링이 잦은 컴포넌트에서 불필요한 연산을 줄임.
- 불필요한 렌더링 방지:
- 메모이제이션된 값이 바뀌지 않으면 의존하는 하위 컴포넌트의 렌더링을 방지.
주요 특징
- 의존성 배열:
- 배열 안의 값이 변경될 때만 재계산이 이루어짐.
- 의존성 배열이 없을 경우, useMemo는 항상 재계산됩니다.
- 렌더링과의 관계:
- useMemo는 렌더링 도중 실행됩니다. 따라서 값이 캐싱된다는 점 외에 동작은 일반 함수 호출과 동일합니다.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), []);
예제 1: 복잡한 계산 최적화
import React, { useState, useMemo } from "react"; const Example = () => { const [count, setCount] = useState(0); const [text, setText] = useState(""); // 비싼 연산을 useMemo로 최적화 const expensiveCalculation = useMemo(() => { console.log("Expensive calculation running..."); return count ** 2; }, [count]); return ( <div> <h1>Expensive Calculation: {expensiveCalculation}</h1> <button onClick={() => setCount(count + 1)}>Increment Count</button> <input value={text} onChange={(e) => setText(e.target.value)} /> </div> ); };
- 렌더링 최적화:
- count가 변경될 때만 expensiveCalculation이 재실행됨.
- text가 변경되더라도 expensiveCalculation은 실행되지 않음.
예제 2: 컴포넌트 리스트 렌더링 최적화
import React, { useMemo } from "react"; const List = ({ items }) => { const sortedItems = useMemo(() => { console.log("Sorting items..."); return items.sort((a, b) => a - b); }, [items]); return ( <ul> {sortedItems.map((item) => ( <li key={item}>{item}</li> ))} </ul> ); };
- 목적:
- items 배열이 변경되지 않으면 sortedItems는 재계산되지 않음.
- 정렬 연산은 연산 비용이 크므로, 불필요한 연산을 방지.
useMemo vs useCallback
특징useMemouseCallback
반환값 계산된 값을 반환 메모이제이션된 함수를 반환 주요 사용 목적 값 계산의 성능 최적화 함수 재생성 방지로 콜백 전달 시 불필요한 렌더링 방지 사용 예 계산된 값의 캐싱 이벤트 핸들러 또는 콜백 함수의 캐싱 문법 useMemo(() => computeValue, [deps]) useCallback(() => computeValue, [deps])
실제 프로젝트에서의 활용
페이지네이션 예제
const startPage = useMemo( () => (currentGroup - 1) * pagesPerGroup + 1, [currentGroup] ); const endPage = useMemo( () => Math.min(currentGroup * pagesPerGroup, totalPages), [currentGroup, totalPages] );
- startPage와 endPage 메모이제이션:
- currentGroup 또는 totalPages가 변경될 때만 재계산.
- currentGroup이 변경되지 않으면 불필요한 계산 방지.
대규모 데이터 필터링
const filteredData = useMemo(() => { return data.filter((item) => item.isActive); }, [data]);
- 필터링 성능 최적화:
- data가 변경되지 않으면 필터링 작업이 재실행되지 않음.
주의사항
- 불필요한 사용 지양:
- 가벼운 연산에 useMemo를 사용하는 것은 오히려 오버헤드가 될 수 있음.
- "비용이 높은 연산"에만 사용하는 것이 적합.
- 의존성 배열 관리:
- 의존성 배열을 정확히 설정하지 않으면 예기치 않은 동작이 발생할 수 있음.
- 의존성을 놓치면 최신 데이터와 불일치 가능.
- 렌더링 주기 최적화:
- 메모이제이션된 값이 컴포넌트의 재렌더링 주기를 불필요하게 늘리지 않도록 유의.
'웹 프로그래밍' 카테고리의 다른 글
[React] NavLink (1) 2025.01.01 [Vue.js] Computed Properties (0) 2024.11.06 [Vue.js] 시작하기 (0) 2024.11.05 useRef (scrollIntoView) (0) 2024.11.04 TypeScript SVG 파일 (0) 2024.09.20