TLDR : CPU 자원을 많이 소비하는 연산에 useMemo를 사용한다.
사용자에게 최적의 경험을 선사하려면 60fps이상을 제공해야 한다.
(1000ms/60) = 약 16.7ms 이니, 하나의 연산이 이 시간 이상 걸리면 안된다는 것을 의미한다.
npm run build / npm run serve를 통해 해당 최적화 조건을 확인한다.
크롬 개발자 도구의 성능 탭 > CPU를 6배 느리게 (본인은 맥os + edge를 활용함을 유의)
위 화면의 문제점은 리렌더링이 발생할 때마다 300ms정도 걸리는 연산을 계속 수행한다는 것이다.
다른 상태의 변화에 의해 해당 컴포넌트가 다시 호출될 때마다 300ms가 걸린다면 끔찍하다.
자세히 살펴보면 match-sorter의 연산이 많은 시간을 잡아먹고 있다.
해당 연산은 json을 불러와, 필터에 맞게 정렬하는 연산인데, 이미 정렬된 결과를 다시 정렬할 필요가 있을까?
이때 useMemo를 사용한다.
// 🐨 wrap getItems in a call to `React.useMemo`
const allItems = React.useMemo(() => getItems(inputValue), [inputValue])
const items = allItems.slice(0, 100)
inputValue를 바꾸지 않고 forceRender를 여러번 수행해 봤다.
webWorker로 성능 조금 더 개선하기
여기서 웹워커를 사용하여 정렬 연산과 렌더링을 분리해 병렬 실행해보자.
useEffect를 통해 비동기로 cpu 연산을 패러랠하게 처리한다 (브라우저의 스레드 사용.)
workerize, workerize-loader 패키지를 사용한다.
// before : filter-cities.js
import {matchSorter} from 'match-sorter'
import cities from './us-cities.json'
const allItems = cities.map((city, index) => ({
...city,
id: String(index),
}))
// for some reason workerize doesn't like export {getItems}
// but it's fine with inline exports like this so that's what we're doing.
export function getItems(filter) {
if (!filter) {
return allItems
}
return matchSorter(allItems, filter, {
keys: ['name'],
})
}
// after : 해당 파일을 webpack을 이용해 workerlize한다 한다.
// workerized-filter-cities.js
import makeFilterCitiesWorker from 'workerize!./filter-cities'
const {getItems} = makeFilterCitiesWorker()
export {getItems}
// 사용처
import {getItems} from '../workerized-filter-cities'
import {useAsync, useForceRerender} from '../utils'
// App 컴포넌트 내부....
const {data: allItems, run} = useAsync({data: [], status: 'pending'})
React.useEffect(() => {
run(getItems(inputValue))
}, [inputValue, run])
// ...
해당 작업은 렌더링과 연산을 분리하여 패러랠하게 처리하므로, 사용자의 경험을 개선할 수 있다.
아래의 표를 참고한다.
CodeSandbox는 웹팩 설정을 건드리는 것이 불가능한 것으로 보인다.
웹팩 관련 코드는 로컬에서 테스트해보자.
참고 :
react.js 내부 알아보기
https://kentcdodds.com/blog/speed-up-your-app-with-web-workers
https://github.com/kentcdodds/react-performance.git
'FrontEnd' 카테고리의 다른 글
리액트 성능 최적화 : react-virtual (0) | 2022.06.05 |
---|---|
리액트 성능 최적화 : React.memo (0) | 2022.06.05 |
리액트 디자인 패턴 : Container pattern (컨테이너 패턴) (0) | 2022.06.04 |
리액트 디자인패턴 : Layout Component (레이아웃 컴포넌트 패턴) (0) | 2022.06.04 |
리액트 디자인패턴 : View Asset Component (VAC 패턴) (0) | 2022.06.03 |