useMemo
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
용도: 계산 비용이 많이 드는 값을 메모이제이션
사용 시기:
예시:
function ProductList({ products, filterText }) {
const filteredProducts = useMemo(() => {
return products.filter(p => p.name.includes(filterText));
}, [products, filterText]);
return (
<ul>
{filteredProducts.map(product => (
<li key={product.id}>{product.name}</li>
))}
</ul>
);
}
useCallback
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
용도: 함수를 메모이제이션
사용 시기:
예시:
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []); // 의존성이 없으므로 함수가 절대 변경되지 않음
return <ChildComponent onClick={handleClick} />;
}
React.memo
const MemoizedComponent = React.memo(function MyComponent(props) {
// 컴포넌트 로직
});
용도: 컴포넌트 자체를 메모이제이션
사용 시기:
예시:
const TodoItem = React.memo(function TodoItem({ todo, onToggle }) {
return (
<li>
<input
type="checkbox"
checked={todo.completed}
onChange={() => onToggle(todo.id)}
/>
{todo.text}
</li>
);
});
성능 측정 후 사용하기
// 좋은 예
const heavyCalculation = useMemo(() => {
return expensiveOperation(props.data); // 실제로 무거운 연산
}, [props.data]);
// 불필요한 예
const simpleCalculation = useMemo(() => {
return props.number + 1; // 단순 연산은 메모이제이션이 불필요
}, [props.number]);
의존성 배열 신중하게 사용
// 좋은 예
const memoizedFn = useCallback((id) => {
console.log(`Item ${id} clicked`);
}, []); // 빈 의존성 배열 - 함수가 절대 변경되지 않음
// 주의가 필요한 예
const memoizedFn = useCallback((id) => {
console.log(`User ${user.name} clicked item ${id}`);
}, [user]); // user 객체가 자주 변경된다면 메모이제이션의 이점이 줄어들 수 있음
학교 급식 메뉴를 보여주는 앱을 만든다고 생각해볼까요?
function SchoolLunchApp() {
const [menus, setMenus] = useState([]);
const [searchText, setSearchText] = useState('');
// 메뉴 필터링 - useMemo 사용
const filteredMenus = useMemo(() => {
console.log("메뉴 필터링 중...");
return menus.filter(menu =>
menu.name.includes(searchText)
);
}, [menus, searchText]);
// 메뉴 클릭 처리 - useCallback 사용
const handleMenuClick = useCallback((menuId) => {
alert(`${menuId}번 메뉴를 선택했어요!`);
}, []);
return (
<div>
<input
type="text"
value={searchText}
onChange={e => setSearchText(e.target.value)}
placeholder="메뉴 검색하기"
/>
<MenuList
menus={filteredMenus}
onMenuClick={handleMenuClick}
/>
</div>
);
}
// React.memo를 사용한 메뉴 목록 컴포넌트
const MenuList = React.memo(function MenuList({ menus, onMenuClick }) {
return (
<ul>
{menus.map(menu => (
<li key={menu.id} onClick={() => onMenuClick(menu.id)}>
{menu.name}
</li>
))}
</ul>
);
});
이 예제에서:
useMemo
는 메뉴를 검색할 때 사용됩니다 (마치 급식 메뉴에서 원하는 음식을 찾는 것처럼!)useCallback
은 메뉴를 클릭했을 때의 동작을 기억합니다React.memo
는 메뉴 목록 전체를 기억해두었다가, 변경사항이 있을 때만 다시 그립니다이렇게 메모이제이션을 사용하면 앱이 더 빠르고 효율적으로 동작하게 됩니다! 마치 수학 문제를 풀 때 계산기를 현명하게 사용하는 것처럼요! 😊