> advent-calendar@0.0.0 build
> tsc -b && vite build
vite v7.2.4 building client environment for production...
[baseline-browser-mapping] The data in this module is over two months old. To ensure accurate Baseline data, please update: `npm i baseline-browser-mapping@latest -D`
✓ 1831 modules transformed.
dist/index.html 0.80 kB │ gzip: 0.40 kB
dist/assets/index-BaVaWQKe.css 38.68 kB │ gzip: 7.54 kB
dist/assets/index-CRfGvi0N.js 791.68 kB │ gzip: 249.92 kB
(!) Some chunks are larger than 500 kB after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
✓ built in 2.35s
vite에서 500kb 이상 경고가 뜨는 것 확인.
데스크톱에서는 로딩이 걸리지 않으나 모바일에서는 오래 걸리는 현상을 확인해서 혹시 해당 부분이 연관되어 있지 않을까? 고민하게 되었음.
특히나 해당 서비스는 사진을 올리는게 주된 사용인 웹이라 실질적으로 사진을 올리기 편한 모바일에서도 사용을 많이 했었음.
경고에서 index.js의 크기가 700kB 이상이라고 하니 어떤 부분이 많이 차지 하는지 확인을 위해 번들 분석이 가능한 도구를 설치하여 확인해봄.
npm install -D rollup-plugin-visualizer
// vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer';
export default defineConfig({
plugins: [
react(),
visualizer({
open: true,
filename: 'dist/stats.html',
gzipSize: true,
brotliSize: true,
})
],
})
빌드 후 dist/stats.html에서 시각적으로 번들 구성 확인 가능

0 ~ 245KiB React + react-router + date-fns + 앱 코드
245 ~ 578KiB Firebase (auth + firestore + storage) ← 약 333KiB
578 ~ 759KiB lucide-react (아이콘) ← 추정치 (불확실)
759 ~ 770KiB Radix UI + 나머지
그냥 막연히 생각했을 때 번들 크기 자체를 줄이면 되지 않을까? 라는 생각이 먼저 들었다.
그러고 나서 메시지에서 말해준대로 chunk를 찾아 보았다.
Firebase의 크기가 커서 줄일 수 있나 확인하니 경량 대체 없고 tree-shaking 정상 작동
| Firebase 서비스 | 대안 | 가능 여부 |
|---|---|---|
firebase/firestore | Firestore Lite | ❌ onSnapshot 실시간 리스너 사용 중 |
firebase/auth | 경량 대체 없음 | ❌ Google OAuth 리다이렉트 전체 플로우 필요 |
firebase/storage | 경량 대체 없음 | ❌ 이미지 업로드 필요 |
firebase/compat/*) 미사용 → 추가 최적화 여지 없음ChevronLeft, ChevronRight, UploadCloud, X (4개)sideEffects: false 설정 확인 → tree-shaking 작동JS 전체 크기 자체는 건드릴 수 없으므로 첫 화면 로드 시 필요한 것만 로드되도록 분리하여 첫 화면 진입 속도를 높이고 재사용성을 강화시키는 방향
아래 두가지를 생각했다.
요건 빌드시에 어떻게 되는지 확인하기!
얼마만큼 차이가 있는지 등등 목표 설정 및 비교를 위한 성능 측정 툴을 찾다가 Lighthouse를 알게 되었고 해당 툴로 성능을 측정하게 되었음.
App.tsx — 4개 페이지 React.lazy() + Suspense 적용vite.config.ts — manualChunks (vendor / firebase / ui) 설정처음 방문할 때 불필요한 코드를 안 받아 첫 화면 진입시 로딩 시간이 줄어드는 효과
/ 접속 시 받는 것:
Before: index.js 791KiB (모든 페이지 코드 포함)
After: index.js 226KiB + firebase 360KiB + vendor 44KiB + ui 122KiB
→ HomePage에 필요한 것만
/projects/:id 처음 진입 시 그 시점에 ProjectDetailPage-19KiB만 추가 로드배포 후 재방문자가 이미 받은 걸 또 안 받아도 됨!
앱을 수정해서 재배포하면:
Before: index.js 해시값 바뀜 → 791KiB 전부 다시 다운로드
After: index.js 해시값 바뀜 → 72KiB만 다시 다운로드
firebase / vendor / ui는 캐시 그대로 사용
Firebase 코드는 내가 손대지 않는 한 절대 안 바뀌므로 브라우저 캐시에 영구적으로 남음.
| 누가 이득 | 무엇이 개선 | |
|---|---|---|
| 코드 스플리팅 | 첫 방문자 | 초기 로딩 속도 (LCP) |
| manualChunks | 재방문자 | 배포 후 캐시 효율 |
총합은 비슷하지만 코드 스플리팅으로 index.js 자체 크기는 줄어듬
Before
index.js 791KiB gzip: 250KiB
After
firebase.js 360KiB gzip: 113KiB ← 배포마다 캐시 재사용
ui.js 122KiB gzip: 39KiB ← 배포마다 캐시 재사용
index.js 226KiB gzip: 72KiB ← 앱 코드만
vendor.js 44KiB gzip: 16KiB ← 배포마다 캐시 재사용
ProjectDetailPage 19KiB gzip: 6KiB ← 라우트 진입 시 로드
CreateProjectPage 11KiB gzip: 4KiB ← 라우트 진입 시 로드
JoinProjectPage 4KiB gzip: 1KiB ← 라우트 진입 시 로드
ProjectListPage 3KiB gzip: 1KiB ← 라우트 진입 시 로드
Before
> advent-calendar@0.0.0 build
> tsc -b && vite build
vite v7.2.4 building client environment for production...
[baseline-browser-mapping] The data in this module is over two months old. To ensure accurate Baseline data, please update: `npm i baseline-browser-mapping@latest -D`
✓ 1831 modules transformed.
dist/index.html 0.80 kB │ gzip: 0.40 kB
dist/assets/index-BaVaWQKe.css 38.68 kB │ gzip: 7.54 kB
dist/assets/index-CRfGvi0N.js 791.68 kB │ gzip: 249.92 kB
(!) Some chunks are larger than 500 kB after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
✓ built in 2.35s
After
> advent-calendar@0.0.0 build
> tsc -b && vite build
vite v7.2.4 building client environment for production...
[baseline-browser-mapping] The data in this module is over two months old. To ensure accurate Baseline data, please update: `npm i baseline-browser-mapping@latest -D`
✓ 1832 modules transformed.
dist/index.html 1.03 kB │ gzip: 0.46 kB
dist/assets/index-Bv0GhR_x.css 28.01 kB │ gzip: 5.95 kB
dist/assets/ProjectListPage-B4mZjvUp.js 3.02 kB │ gzip: 1.34 kB
dist/assets/projects-D28OFEBP.js 3.54 kB │ gzip: 2.02 kB
dist/assets/JoinProjectPage-e3c2VJBW.js 3.56 kB │ gzip: 1.30 kB
dist/assets/CreateProjectPage-scnHJhex.js 10.72 kB │ gzip: 3.62 kB
dist/assets/ProjectDetailPage-BL0Rro_F.js 18.57 kB │ gzip: 6.15 kB
dist/assets/index-BdTa1noy.js 19.76 kB │ gzip: 7.39 kB
dist/assets/ui-BEkj4lTN.js 147.39 kB │ gzip: 46.75 kB
dist/assets/vendor-D1TdEGAq.js 225.68 kB │ gzip: 72.35 kB
dist/assets/firebase-CetztI6f.js 360.45 kB │ gzip: 112.51 kB
✓ built in 3.67s
데스크탑의 점수는 3점 낮아졌으나 90점대로 유지이고, 걱정되었던 모바일의 성능 점수가 7점 상승했음
| 페이지 | Before | After | 변화 |
|---|---|---|---|
| 메인 | 76 | 83 | +7 ✅ |
| 페이지 | Before | After | 변화 |
|---|---|---|---|
| 메인 | 99 | 96 | -3 |
모바일의 LCP 시간이 0.6초 감소하여 렌더링 시간 조금 단축되어 즉, 홈화면이 조금 빨리 뜨게 됨
| 페이지 | Before | After | 변화 |
|---|---|---|---|
| 메인 | 5.1s | 4.5s | -0.6s ✅ |
| 페이지 | Before | After | 변화 |
|---|---|---|---|
| 메인 | 0.8s | 0.8s | - |
TTI의 시간은 오히려 0.2초 증가함! 다만 LCP에서 0.6초 감소하여 전반적으로는 홈화면이 뜨고 상호작용까지 0.4초 증가
| 페이지 | Before | After | 변화 |
|---|---|---|---|
| 메인 | 5.1s | 5.3s | +0.2s |
| 페이지 | Before | After | 변화 |
|---|---|---|---|
| 메인 | 0.8s | 0.8s | - |
프론트엔드의 성능을 어떻게 측정하고 증명하는지에 대해 관심이 많았었는데 이번 기회에 문제를 정의하고 어떻게 증명해내는지 직접 해보면서 경험치를 쌓을 수 있었다.
문제의 원인을 예측하고 예측이 맞는지 확인하는 과정에서 몰랐던 여러 지표와 내용들을 부딪히면서 알아가는 과정에서 많은 것을 고민하고 배웠다.
다만, 아쉬운 점은 내가 설정한 목표 지표가 타당한 목표인지에 대해서는 좀 더 서칭하고 공부해야할 것 같다.
이후에는 모바일의 performance 점수가 90점 이상으로 획기적으로 오르지 않아서 해당 점수를 더 올릴 방안을 찾아봐야하고 더불어 SEO 점수도 높일 수 있도록 추가적인 리팩토링 작업이 필요할 것 같다.
이외에도 다양한 성능 측정 내용이 있는데 해당 내용을 하나씩 파면서 측정하여 비교하여 성능을 높이는 여러가지 방안을 생각해보고 높이면서 문제 해결 역량을 차근차근 높일 예정!
관련 깃허브 레포지토리: https://github.com/meldyssey/advent-calendar/pull/6