4분
리액트 앱에 대한 프로파일링
최근 웹 애플리케이션은 리액트로 만들지 않은 앱이 없을 정도로 리액트가 많이 사용됩니다.
리액트는 빠르고, 유연하고, 사용하기 쉽습니다. 그래서 더 크고 방대한 웹 애플리케이션을 만들기 편리해졌습니다.
앱이 커지고 복잡해짐에 따른 반작용으로 다양한 문제도 발생할 가능성이 커졌습니다. 개인적으로 성능 문제는 문제를 찾기 어렵고 분석하기도 복잡한 문제입니다.
Kent C.Dodds가 작성한 Profile a React App for Performance 글을 옮기면서 어떻게 리액트 앱을 분석할 수 있는지, 프로파일링하면서 주의해야 할 것은 무엇인지 확인해보았습니다.
들어가면서
리액트 팀에서 제공하는 react-devtools이 있습니다. 브라우저 Chrome, Firefox 확장 프로그램으로 이용할 수 있습니다. 리액트 앱이 있는 어디서든 사용할 수 있습니다.
React DevTools의 가장 뛰어난 기능 중 하나는 프로파일링 기능입니다. 많은 프로파일러 프로그램이 있지만 이 포스트에서는 React Profiler를 사용합니다. React Profiler를 사용하면서 흔히 겪는 문제를 피하는 방법을 보여주려합니다.
note
Profile a React App for Performance에서는 my bookshelf app을 이용해 프로파일링 하는 과정을 다룹니다.
확장 프로그램 설치
프로파일러로 선택한 React DevTools를 브라우저에 설치합니다. 저는 크롬을 사용하고 있어서 Chrome 스토어에서 설치했습니다. 설치 후에 확장 프로그램이 나타나지 않는다면 브라우저 DevTools panel을 닫았다가 다시 열어보세요.
리액트 앱 실행
리액트 앱을 실행해보겠습니다.
제 블로그 앱은 next.js를 사용하고 package manager로 pnpm을 사용합니다.
pnpm dev
명령어를 통해 next.js development server를 동작합니다.
프로파일러 실행
개발자 도구를 열어 "⚛️ Profiler" 탭을 클릭합니다. 그리고 해당 창에서 "Start profiling" 버튼(REC버튼 처럼 생긴, 실제로 녹화하는 것처럼 프로파일링 합니다.)을 클릭합니다.
그런 뒤에 앱을 사용해보면서 프로파일링을 진행합니다. 그런 다음 "Stop profiling" 버튼(빨간색으로 변한)을 클릭합니다.
프로파일링 결과 확인
리액트 앱 프로파일링 결과를 분석할 때 DevTools에서 제공하는 몇 가지 설정들이 있습니다. 기본 View는 "Flamegraph chart"입니다. 이는 프로파일링 결과를 시간 순서에 따라 표현한 것입니다. 또 하나는 "Ranked chart"가 있습니다. 이는 프로파일링 결과를 컴포넌트의 렌더링 시간에 따른 랭킹을 표현한 것입니다. 필요한 정보에 따라 두 개 View를 자유롭게 보면서 분석할 수 있습니다.
또 다른 포스트에서 위 차트에 대한 자세한 분석을 진행할 예정입니다.
함정: development mode에서의 측정
프로파일링과 같은 성능 측정을 할 때 피해야 할 함정이 있습니다.
바로 development mode에서의 측정입니다.
위에서 한 작업은 development mode에서 앱이 어떻게 작동하는지 측정했습니다.
리액트 앱을 오랫동안 사용하신 분들은 아시겠지만, development mode에서만 나타나는 많은 warning
들을 보셨을 겁니다.
이는 개발할 때 많은 도움을 주지만 비용이 듭니다.
그래서 development mode에서의 측정은 실제 앱의 성능과는 다를 수 있습니다.
따라서 앱 성능을 정확하게
측정하기 위해서 production version(최종 사용자가 사용할 코드)에서 측정해야 합니다.
production app 빌드와 측정
제 블로그 앱은 pnpm build
를 통해 next.js 앱 production version으로 빌드합니다.
그리고 pnpm start
를 통해 production version을 실행합니다.
info
react app을 사용하시는 분들 경우 로컬에서 빌드 후 서버(리액트 정적 파일 서버 용도) 실행하는 간단한
방법은 serve를 사용하는 것입니다. npx serve -s build
를
통해 빌드된 정적 파일을 서버로 실행할 수 있습니다.
이제 프로파일링을 실행해보겠습니다.
그런데 다음과 같은 문구와 함께 프로파일링을 할 수 없게 되어있습니다.
Profiling not supported.
Profiling support requires either a development or profiling build of React v16.5+.
Learn more at reactjs.org/link/profiling.
production 빌드를 할 때는 앱을 가능한 한 빠르게 만들기 위해 실제로 프로파일링을 위한 코드를 제거합니다. 즉, 리액트에는 프로파일링에 필요한 코드가 production version에는 없다는 것입니다.
기본 설정으로 빌드했을 경우 production version을 빌드하면 프로파일링을 할 수 없게 됩니다.
따라서 프로파일링을 위한 코드를 포함한 production version을 빌드해야 합니다.
프로파일링을 위한 production version 빌드
create-react-app
을 사용할 경우react-scripts@>=3.2.0
에서 간단히npx react-scripts build --profile
과 같이--profile
설정을 하면 이를 해결할 수 있습니다.next.js
를 사용할 경우도 마찬가지로--profile
설정을 하면 프로파일링을 위한 빌드가 자동으로 됩니다.vite
를 사용할 경우 찾아보았을 때 별도로 옵션이 존재하지 않아 '--mode=development'로 빌드 후 확인하는 방법을 사용했습니다.
그 외 경우 webpack
사용 시 이 gist
를 참고하여 webpack
설정을 수정하는 방법도 있습니다.
production 빌드 시에는 terser작업과 같이 compress시에 이름을 mangling하는데 이 때문에 프로파일링 결과를 알아보기 힘들 수도 있습니다.
Disable name mangling
리액트는 컴포넌트를 name
속성을 기반으로 호출할 대상을 알고 있습니다.
terser
의 경우 다음과 같이 mangling을 disable 할 수 있습니다. (https://terser.org/docs/api-reference.html#mangle-options)
swc
minification을 사용할 경우 다음과 같이 disable 할 수 있습니다.(https://swc.rs/docs/configuration/minification)
next.js에는 최근에 merge된 이 PR을 통해 --no-mangling
옵션을 사용하면 mangling을 disable 처리할 수 있습니다.
근데 저는 동작을 안하네요... 흠...
함정: 빠른 컴퓨터에서 프로파일링 측정
대부분의 개발자가 앱을 사용하는 사용자보다 훨씬 더 나은 장치로 앱을 개발하고 있습니다. 사용자가 사용하는 장치에서 앱을 사용하면서 프로파일링 하는 것이 더 정확한 결과를 얻을 수 있습니다. 즉, 실제 사용자 경험을 시뮬레이션하기 위해 여러분의 CPU를 조절하면서 프로파일링한다면 앱의 실제 성능을 훨씬 더 잘 이해할 수 있습니다.
그래서 개발자 도구의 Performance
탭에서 CPU throttling
을 이용합니다.
No Throttling | x6 Thottling |
---|---|
x6 throttling을 사용하니 꽤 느리게 보이나요? 실제 사용자가 사용하는 장치에서는 더 느리게 동작할 수도 있습니다.
결론
리액트 앱을 적절하게 프로파일링 하는 기본적인 방법에 대해서만 다루었지만 자신의 앱에서 이를 시도하고 앱의 성능을 확인할 수 있는 시간이 되었기를 바랍니다.
또한 React DevTools과 프로파일링에 대해 좀 더 자세히 알고 싶다면 리액트 블로그 글인 DevTools Profile로 컴포넌트 프로파일링 를 참고하시면 좋을 것 같습니다.
reference
마지막 업데이트
11/27/2022