최근에 회사에서 해외 서비스를 도입한다고 해서 사이트의 성능을 검사해 보았는데, 아래와 같이 페이지의 번들 크기가 예상보다 커진 것을 발견했다.
Route: 동적 라우트를 포함한 페이지의 경로
Size: 클라이언트 브라우저에서 페이지에 접근할 때 필요한 자바스크립트 번들의 크기
First Load JS: 각 페이지마다 필요한 자바스크립트 번들 크기 + 앱 전반에 사용되는 공용 코드, 프레임워크 코드, 웹팩 코드, CSS 등의 크기
각각의 청크 파일은 다음과 같은 역할을 합니다
chunks/framework-*: 프레임워크와 관련된 파일 (예: react-dom 및 react)
chunks/main-*: Next.js와 관련된 기능 (예: next/dist - 라우터 포함)
chunks/page/_app-*: _app 페이지와 관련된 파일
chunks/webpack-*: 웹팩 스크립트 코드 (build-manifest.json을 통해 페이지 이동 시 필요한 JS 로드)
npm run build 실행 시 생성되는 .next 디렉토리를 통해 번들 구조를 분석했다. Next.js는 기본적으로 페이지 단위로 코드 스플리팅을 하므로, 각 페이지별 청크가 chunks 폴더에 존재한다.
.next/server: 각 페이지를 pre-render할 때 사용되며, 완성된 HTML과 .next/static/chunks 파일을 통해 하이드레이션된다.
.next/static/chunks: 페이지 간 이동 시 필요한 청크 파일이 저장된다.
.next/build-manifest.json 파일을 확인하면 각 페이지에 대한 청크가 정의되어 있는데, Next.js는 이를 기반으로 페이지에 맞는 청크를 제공한다.
초기 번들에는 포함되지 않더라도 향후 App Router 마이그레이션을 고려해 정리
번들 분석 도구 설치 후 불필요한 라이브러리를 제거
npm install --save-dev @next/bundle-analyzer cross-env
yarn add -D @next/bundle-analyzer cross-env
next.config.js에 설정 추가
next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')()
module.exports = withBundleAnalyzer(configs)
npm run build 실행 시 번들 시각화 리포트가 열리며, 사이즈가 큰 라이브러리를 식별 및 제거할 수 있었다.
_app.js는 공통 컴포넌트로, 모든 페이지 진입 시 함께 로드되므로 영향도가 크다.
크기가 큰 라이브러리를 _app.js에서 import하고 있었고, 이를 실제 사용하는 컴포넌트로 이동시켰다.
토스트나 모달처럼 사용자 상호작용 이후 등장하는 컴포넌트의 경우 동적 import가 일반적인 최적화 방법이다.
하지만 이번에는 해당 컴포넌트들이 가볍고 사용자 경험에도 영향을 줄 수 있어 적용하지 않았다.
향후 무거운 컴포넌트 도입 시 동적 import를 고려할 계획이다.
2.일반 네트워크 환경에서는 체감 차이가 미미했지만, Fast 3G 환경에서는 약 1초 단축
개발서버에서 라이트 하우스도 확인을 해봤다.
비교군 서버1 : _app.js 최적화 전
비교군 서버2 : _app.js 최적화 전
서버3: _app.js 최적화 후