반응형
사용자가 성능 불만 접수 전에, 성능 문제를 해결합시다.
렌더링 시간의 일부를 어떻게든 추적하고 해당 정보를 서버로 보내 모니터링할 수 있다면 좋을 것입니다.
React DevTools만큼 많은 정보를 제공하지는 않지만 유용한 정보를 제공합니다
참고 : facebook은 프로파일링 버전과 비 프로파일링 버전을 동시에 배포합니다,
즉 프로파일링 버전을 사용자의 일부에만 배포하여, 모니터링합니다.
주의 : 프로파일러는 기본적으로 프로덕션 모드에서 동작하지 않습니다.
성능 부하가 될 수도 있으니 주의합시다.
Create React App v3.2 이상 버전에서는 다음과 같은 방법을 사용하여 프로덕션에서 프로파일링을 enable할 수 있습니다.
yarn build --profile
npm run build -- --profile
기본 사용법은 아래와 같습니다.
출처 : https://ko.reactjs.org/docs/profiler.html
<App>
<Profiler id="Navigation" onRender={onRenderCallback}>
<Navigation {...props} />
</Profiler>
<Main {...props} />
</App>
function onRenderCallback(
id, // the "id" prop of the Profiler tree that has just committed
phase, // either "mount" (if the tree just mounted) or "update" (if it re-rendered)
actualDuration, // time spent rendering the committed update
baseDuration, // estimated time to render the entire subtree without memoization
startTime, // when React began rendering this update
commitTime, // when React committed this update
interactions, // the Set of interactions belonging to this update
) {
// Aggregate or log render timings...
}
DIY 해보기
1. 1. 5초마다 성능 모니터링 정보 보내기 위한 모듈 구현
서버에 http post 요청으로 성능 정보를 보낼 수 있습니다.
우리는 따로 서버가 없으므로, 로깅하는 것으로 갈음합니다.
report-profile.js
// 모든 업데이트의 대기열을 유지하고
// 대기열에 데이터가 있는 경우 10초마다 프로필 데이터를 서버로 보냅니다.
// 그런 다음 Grafana 또는 이와 유사한 데이터를 그래프로 표시합니다.
let queue = [];
// 5초마다 서버에 데이터를 보냅니다.
// 실제 시간은 앱의 요구 사항에 따라 다를 수 있습니다.
setInterval(sendProfileQueue, 5000);
function reportProfile(
id, // 방금 실제 돔에 커밋한 프로파일러 트리의 "id" props
phase, // "mount"(트리가 방금 마운트된 경우) 또는 "update"(다시 렌더링된 경우)
actualDuration, // 커밋된 업데이트를 렌더링하는 데 소요된 시간
baseDuration, // 메모이제이션 없이 전체 하위 트리를 렌더링하는 데 걸리는 예상 시간
startTime, // React가 이 업데이트를 렌더링하기 시작한 시간
commitTime // React가 이 업데이트를 커밋했을 때
// interactions 이 업데이트에 포함된 인터랙션. 리액트 17에서 trace API가 삭제되면서 사라진 속성
) {
queue.push({
id,
phase,
actualDuration,
baseDuration,
startTime,
commitTime
});
// this is a fire and forget, so we don't return anything.
}
function sendProfileQueue() {
if (!queue.length) {
return Promise.resolve();
}
const queueToSend = [...queue];
queue = [];
console.info("sending profile queue", queueToSend);
// 여기가 실제로 queueToSend 데이터를 백엔드로 보내기 위해 서버를 호출하는 곳입니다...
// 우리는 딱히 백엔드가 없으므로, return Promise.resolve()를 호출하고 끝냅니다.
return Promise.resolve();
}
export default reportProfile;
2. 사용자 이벤트 포함하기 (interactions)
App.js
// Production performance monitoring
import * as React from 'react'
// 리액트 17에서 삭제됨 ㅠㅠ
// import {unstable_trace as trace} from 'scheduler/tracing'
import reportProfile from './report-profile'
function Counter() {
const [count, setCount] = React.useState(0)
// const increment = () => 리액트 17에서 삭제됨 ㅠㅠ
// trace('click', performance.now(), () => setCount(c => c + 1))
const increment = () => setCount((c) => c + 1);
return <button onClick={increment}>{count}</button>
}
function App() {
return (
<div>
<React.Profiler id="counter" onRender={reportProfile}>
<div>
Profiled counter
<Counter />
</div>
</React.Profiler>
<div>
Unprofiled counter
<Counter />
</div>
</div>
)
}
export default App
참고
Interaction tracing with React (github.com)
https://reactjs.org/docs/profiler.html
https://kentcdodds.com/blog/react-production-performance-monitoring
https://kentcdodds.com/blog/profile-a-react-app-for-performance
반응형
'FrontEnd' 카테고리의 다른 글
프론트엔드 지식 : Javascript Critical Rendering Path (0) | 2022.06.08 |
---|---|
리액트 성능 최적화 : Death By a Thousand Cuts (천 번 베이면 죽는다.) (0) | 2022.06.05 |
리액트 성능 최적화 : Virtual DOM (0) | 2022.06.05 |
리액트 성능 최적화 :contextAPI (0) | 2022.06.05 |
리액트 성능 최적화 : react-virtual (0) | 2022.06.05 |