본문 바로가기

Timo

CI로 성능 관리 자동화: Lighthouse CI와 번들 사이즈 분석

[번들 뭔데 신경써야될까?]

Next.js는 내가 작성한 코드의 의존성을 분석해서 브라우저가 실행할 수 있는 JS 파일들로 변환해준다.

이 과정에서 코드를 여러 개의 청크로 쪼개서 필요한 것만 그때그때 불러옴. 

이 결과물이 번들!! 

번들이 크면 유저가 페이지 처음 들어올 때 JS 파일 다운받는 시간이 길어짐. 

→ 번들 크기 모니터링 중요 ! 

 

[gzip이 뭘까]

서버가 브라우저한테 JS 파일 그냥 보내지 않음. 

gzip으로 압축해서 보내고 브라우저가 압축 풀어서 실행함. 

→ 실제로 네트워크에 전송되는 크기가 gzip 크기 

 

[webpack이랑 turbopack은 뭘까]

둘 다 번들 엔진 = Next.js가 내 코드를 브라우저용 JS로 변환할 때 쓰는 도구인 것. 

 

  • webpack: 라우트별 청크 파일을 직접 읽어서 gzip 크기를 계산한다. 
    manifest 파일이 청크 파일 경로 알려주면 그거 읽음
  • turbopack: 폴더 안에 파일들 gzip 크기를 합산한다. 
    폴더 찾아가서 읽어야

<둘 중에 뭐 쓰나?>

정해진 최적화 규칙
+ 의존성 그래프 분석
+ 코드 스플리팅 규칙

 

기반으로 어떤 번들 엔진 사용할지 결정한다. 

 

[그냥 webpack-bundle-analyzer 쓰면 되는 거 아녀?]

webpack-bundle-analyzer 얘는 빌드 결과를 시각적인 트리맵으로 제공한다. 

로컬에서 수동 실행해서 브라우저에서 볼 수 있음. 

우리가 하는 건 숫자만 뽑아서 pr 코멘트에 자동제공함. 

◇ 둘이 같이 쓰면 된다네요. 

pr 코멘트로 번들이 커짐을 감지하면 

webpack-bundle-analyzer로 왜 커졌는지 파악. 

Next.js에서 webpack-bundle-analyzer 쓰려면 @next/bundle-analyzer 패키지 사용하면 됨. 

근데 turbopack모드에서 지원이 안돼서 분석할 떄는 webpack 모드로 돌릴 것. 

 

[어떻게 작동하나..]

1. app-build-manifest.json 있으면 webpack 모드, 없으면 turbopack 모드로 자동 감지

2. webpack: manifest가 알려준 청크 파일 경로로 직접 가서 gzip 크기 계산

3. turbopack: static/chunks/app/[페이지명]/ 폴더 찾아가서 안에 있는 파일들 gzip 크기 전부 합

4. 공유 번들(React, Next.js 런타임) + 페이지 고유 JS = First Load JS

 

5. 200kB 넘으면 🟡, 350kB 넘으면 🔴

 

[워크플로우 구성]

concurrency:
  group: bundle-size-${{ github.ref }}
  cancel-in-progress: true

PR에 코멘트가 계속 새로 달리면 지저분해지니까,

기존 봇 코멘트를 찾아서 update하는 방식으로 항상 코멘트 하나만 유지되게 함.

 

[Lighthouse랑 합침]

bundle size랑 lighthouse 분석 yml 파일 두 개로 안 두고(빌드 2번 하게 되니까...)

performance.yml 하나로 합침 

1. pnpm build 한 번만 실행

2. Next.js 서버 띄우고 (next start)

3. Lighthouse CI가 실제 서버에 접속해서 성능 측정

4. performance-report.js가 결과 읽어서 PR 코멘트 하나로 게시

 

[그럼 코멘트 어떻게 생김?]

  • Bundle Size — 라우트별 gzip 크기 + First Load JS
  • Lighthouse — Performance, Accessibility 점수 + LCP/CLS/TBT
  • Image Optimization — public/ 폴더 이미지 크기·포맷 분석

다 보이지는 않지만 대강 이런식..

페이지 안에 뭐가 없어서 lighthouse 결과가 없음.


쨌든 배포 전에 pr 단계에서 번들 크기랑 성능을 확인할 수 있다는.. 장점 👍🏻