SookDev
🌲

next/bundle-analyzer 로 성능 개선하기

tag
code-quality
performance
date
Nov 28, 2023
목차

1. 이글의맥락

성능 개선의 일환으로 초기 화면 렌더링 속도를 개선하는 방법을 찾아보고 있었다.
그 방식으로 Entry Point File의 크기를 줄이는 것이 있음을 알게 되었다.
Entry Point File 프로젝트를 실행하면 나오는 첫 페이지를 담당하는 파일
notion image
위 사진은 내가 개선할 초기 페이지다.
해당 화면에서 보이지 않는 라이브러리와 컴포넌트는 추후 필요할 때 불러오게 하여 성능을 개선할 수 있다.
프로덕트의 모든 초기렌더링을 이번에 개선하기에는 시간상으로 어렵기 때문에 평소 시간을 내어 더욱 해나가야 할 것 같다.
이번 시간에는 개선 방식을 알아보는 것에 집중하려고 한다.

2. 개선해가는과정

개선하는 방법으로 lazy-loading 을 사용하려고 한다.
lazy loading 필요한 데이터를 지연하여 로딩하는 방식
웹 페이지를 로드할 때 모든 데이터를 한 번에 로드하는 것이 아니라, 사용자가 필요로 하는 데이터만 로드하는 방식을 말한다.
이미지, JavaScript 파일, CSS 파일 등을 필요 한 시점에 로드하여 성능을 향상시킬 수 있다.
우리 프로젝트는 NextJS를 사용하기 때문에 이에 맞는 bundle-analyzer를 받아와 lazy-loading을 구현해보려고 한다.

2-1. 사용방법

📢
npm i -D @next/bundle-analyzer
bundle-analyzer 를 설치한다.
// next.config.js const withBundleAnalyzer = require('@next/bundle-analyzer') ({ enabled: true, openAnalyzer: true, }); const nextConfig = { // config 내용 } module.exports = withBundleAnalyzer(nextConfig)
openAnalyzer : true 를 하면 build시 무조건 analyzer가 열린다.
계속 analyzer가 열리는 것이 귀찮다면 특정 환경에서면 열리도록 하는 방법이 있다. (구글에 서치하면 나오니 이부분은 스킵한다.)
npm run build
이제 빌드를하여 analyzer를 체크해 보겠다.

2-2. 빌드결과

notion image
프로젝트 실행 후 첫 화면에 보이지 않아도 되는, 즉 lazy loading을 적용할 수 있는 라이브러리들과 컴포넌트를 표시해두었다.
빨간색 테두리들은 최초 렌더링 시 필요 없는 라이브러리들을 뜻한다.
단, 여기서 빨간색 테두리 내부의 node_modules 는 하나하나 빨간색 테두리 하는게 어려워서 대강 초록색 테두리로 표기했는데, 이 부분은 예외다.
계산을 해보니 lazy loading 할 라이브러리의 총 크기는 1951.82kb, 즉 1.9MB 정도 된다.

2-3. 그래서 무엇을 지연로딩 할까?

notion image
analyzer만 보면 잘 모를테니 lazy loading을 적용할 컴포넌트들을 표시해본다.
이 컴포넌트 및 라이브러리들은 굳이 화면에 보이지 않아도 된다.
또한 react-datetime,momentjs 등 현재 사용하지 않는 라이브러리는 삭제했다.
import dynamic from 'next/dynamic'; const Example = dynamic(() => import('@/components/Exampl e'), { ssr: false, });
lazy loading 적용을 원하는 컴포넌트에서 dynamic import 를 통해 ssr: false 처리를 해두었다.
ssr: false 는 서버 사이드 렌더링(SSR)을 비활성화하는 속성으로, 서버에서도 미리 페이지를 조립하지 않도록 하고 사용자가 필요할 때에만 불러오는 역할을 한다.

3. 분석결과

notion image
Entry Point File 의 크기를 40% 정도 축소 시킬 수 있었다.
(1002KB → 604KB) 여전히 bundle file 전체의 크기는 크다. 총 크기가 3.48MB에서 3.36MB로 줄어들은 정도 뿐이다..!
하지만 bundle의 모든 파일 크기를 줄일 수 없더라도 엔트리 포인트 파일의 크기를 줄일 수 있는 것 만으로 큰 효과라고 생각한다.
브라우저에서 Entry Point File을 다운로드하고 해석하는 데에는 시간이 소요되므로, 파일의 크기가 작을수록 다운로드 및 해석 속도가 빨라질 것이기 때문이다.
notion image
라이트 하우스 지표는 이렇게 바뀌었다.
Largest Contentful Paint(LCP) 사용자가 웹 페이지에서 가장 큰 콘텐츠 요소를 볼 수 있는 시간을 측정하는 지표 Total Blocking Time(TBT) 페이지 로딩 중에 발생하는 블로킹 시간의 총 합을 측정하는 지표. 블로킹 시간은 JavaScript 실행이 페이지 로딩을 방해하여 사용자 인터랙션에 대한 응답 시간을 늦추는 시간을 의미. Speed Index(SI) 페이지가 얼마나 빠르게 시각적으로 완전히 로드되는지
LCP는 2.5초 이하, TBT는 1000ms 이하, SI 는 1초에서 3초 사이가 좋은 지표라고 한다.
그런 측면에서 현재의 LCP와 TBT의 지표는 좋은 수준은 아니라,, 앞으로도 계속 개선해나가야 할 숙제라고 생각한다.
그래도 지표가 각각 20%, 30%, 17% 정도 개선되었으므로 의미있는 과정이었다고 생각한다.

4. 더욱개선하고싶은것들

성능 개선 방식을 연구해봤지만 아직 궁금한 점이 많다.
번들 총 크기가 3.48MB에서 3.36MB로 줄어들었는데, 더욱 줄일 수 있는 방법이 있지 않을까.
(node modules 안에 있는 번들들의 크기를 압축할 수 없을까요?)
두번째로, 이번에는 컴포넌트를 분리하지 않고 dynamic import 만 붙여 성능개선했다.
거대한 컴포넌트를 단일책임만 갖도록 분리하고 필요 없는 컴포넌트들은 lazy loading을 시키면 렌더링 속도 개선에 많은 도움이 될 것 같다.

참조
🔗 Lighthouse
🔗 next/bundle-analyzer