useMemo()로 최적화 하기
// useMemo 사용 전
// App.js
function App() {
const [listTitle, setListTitle] = useState('My List');
const changeTitleHandler = useCallback(() => {
setListTitle('New Title');
}, []);
return (
<div className="app">
<DemoList title={listTitle} items={[5, 3, 1, 10, 9]} />
<Button onClick={changeTitleHandler}>Change List Title</Button>
</div>
);
}
export default App;
import React from 'react';
import classes from './DemoList.module.css';
const DemoList = (props) => {
const sortedList = props.items.sort((a,b) => a-b);
console.log('DemoList RUNNING');
return (
<div className={classes.list}>
<h2>{props.title}</h2>
<ul>
{sortedList.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</div>
);
};
export default React.memo(DemoList);
위 예제에서, DemoList에 전달되는 props의 items 배열은 App 컴포넌트가 다른 이유로 리렌더링 되더라도 항상 새로운 배열이 생성되기 때문에, DemoList 컴포넌트 재실행 및 내부의 sort 함수가 동작을 한다.
하지만, 만약 items 배열의 크기가 너무 큰 경우에는 배열의 요소의 변화가 없는 상황에서 매번 items 배열의 sort를 진행하는 것은 낭비가 될 수도 있다.
이런 경우에는 useMemo를 사용할 수 있다. useCallback이 함수에 대한 것을 저장하듯 useMemo는 모든 종류의 데이터를 저장할 수 있다.
useMemo의 첫 번째 인자에는 함수가 들어가야 한다. 이 함수를 기억하는 것이 아닌 이 함수가 저장하고 싶은 것을 반환한다고 생각하면 된다.
두 번째 인자로는 의존성 배열이다. 의존성 배열을 통해 저장된 값에 변경 사항이 생길 때마다 업데이트할 수 있다.
useMemo를 사용해 데이터를 저장하면 이는 메모리를 사용하는 것이고 이런 함수 저장 또한 일정 성능을 사용하는 것이다.
따라서 useMemo는 모든 값에 사용하는 것이 아니라, 불필요한 작업을 반복할 필요가 없을 때 고려하는 것이 좋다.
//useMemo를 사용한 최적화
// App.js
function App() {
const [listTitle, setListTitle] = useState('My List');
const changeTitleHandler = useCallback(() => {
setListTitle('New Title');
}, []);
// useMemo를 사용하지 않으면, 항상 새로운 배열로 취급된다. 따라서, listItems를 useMemo를 사용하지 않는 경우에는 DemoList 컴포넌트에 useMemo를 사용하더라도 sort가 계속 실행된다.
const listItems = useMemo(() => [5, 3, 1, 10, 9], []);
return (
<div className="app">
<DemoList title={listTitle} items={listItems} />
<Button onClick={changeTitleHandler}>Change List Title</Button>
</div>
);
}
export default App;
// DemoList.js
import React, { useMemo } from 'react';
import classes from './DemoList.module.css';
const DemoList = (props) => {
const { items } = props;
const sortedList = useMemo(() => {
console.log('Items sorted');
return items.sort((a, b) => a - b);
}, [items]);
// items가 바뀔 때만 sortedList가 바뀌도록 useMemo를 사용한다.
console.log('DemoList RUNNING');
return (
<div className={classes.list}>
<h2>{props.title}</h2>
<ul>
{sortedList.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</div>
);
};
export default React.memo(DemoList);
* useMemo와 useCallback의 차이점
useMemo:
useMemo는 계산 비용이 큰 연산의 결과를 저장하고, 동일한 입력이 주어진 경우에는 이전에 계산한 결과를 재사용할 때 사용된다.
주로 계산 비용이 높은 연산을 줄이기 위해 사용된다.
예를 들어, 계산된 결과를 UI에 표시하는데 사용하는 경우나, 복잡한 계산을 할 때 활용할 수 있다.
useCallback:
useCallback은 함수를 메모이제이션하여 새로운 렌더링 시에 동일한 함수 인스턴스를 유지한다.
주로 자식 컴포넌트에 함수를 전달할 때 사용된다.
예를 들어, 자식 컴포넌트에게 이벤트 핸들러를 전달하거나, useEffect 내에서 의존성 배열에 포함되는 함수를 전달할 때 사용할 수 있다.
[Udemy] React 완벽 가이드 with Redux, Next.js, TypeScript 강의를 듣고 학습했습니다
'TIL' 카테고리의 다른 글
2023.8.23 TIL (0) | 2023.08.23 |
---|