[G1-Sync] Manual knowledge update

This commit is contained in:
Antigravity Agent
2026-05-10 22:08:15 +09:00
parent 21ac3ed255
commit 504fd5fb42
3011 changed files with 380280 additions and 206977 deletions
@@ -2,123 +2,186 @@
id: wiki-2026-0508-bundle-size-optimization
title: Bundle Size Optimization
category: 10_Wiki/Topics
status: needs_review
status: verified
canonical_id: self
aliases: []
aliases: [JS Bundle Optimization, Web Bundle Reduction]
duplicate_of: none
source_trust_level: A
confidence_score: 0.92
tags: [uncategorized]
confidence_score: 0.9
verification_status: applied
tags: [bundle, performance, webpack, vite, tree-shaking]
raw_sources: []
last_reinforced: 2026-05-08
last_reinforced: 2026-05-10
github_commit: pending
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
tech_stack:
language: unspecified
framework: unspecified
language: JavaScript/TypeScript
framework: Vite/Rollup/Webpack
---
## 📌 한 줄 통찰 (The Karpathy Summary)
Bundle Size Optimization(번들 크기 최적화)은 클라이언트로 전송되는 자바스크립트 자산의 물리적 용량을 최소화하여 초기 로딩 성능(LCP)과 런타임 반응성(TBT/INP)을 개선하는 기술적 공정이다. 코드 분할(Code Splitting), 지연 로딩(Lazy Loading), 트리 쉐이킹 등을 통해 브라우저의 파싱 및 실행 오버헤드를 근본적으로 줄이는 것을 목표로 한다.
# Bundle Size Optimization
## 📖 구조화된 지식 (Synthesized Content)
1. **번들 팽창의 원인 진단**
- 단일 엔트리 포인트(`index.js`)에 모든 종속성(React, heavy libraries)이 결합된 구조.
- 무분별한 Eager Import와 거대한 전이적 종속성(Transitive Dependencies)으로 인한 메인 스레드 점유율 상승.
2. **코드 분할 및 지연 로딩 (Strategic Splitting)**
- `React.lazy()``<Suspense>`를 활용하여 특정 라우트나 무거운 UI 요소(차트, 모달 등)를 독립적인 청크(Chunk)로 분리.
- 사용자가 필요로 하는 시점에만 코드를 로드하여 초기 번들 페이로드를 획기적으로 절감.
3. **벤더 분할 전략 (Vendor Splitting)**
- Vite/Rollup의 `manualChunks` 설정을 통해 자주 변경되지 않는 핵심 라이브러리(React 등)를 별도의 청크로 고정.
- 브라우저 캐싱 효율을 극대화하여 재방문자의 로딩 속도를 가속화.
4. **서버 컴포넌트(RSC)를 통한 근본적 절감**
- 상호작용이 없는 정적 UI를 서버에서 렌더링하여 클라이언트로 전송되는 JS 페이로드를 '0'으로 수렴시키는 아키텍처 적용.
5. **분석 및 정제 도구 활용**
- `rollup-plugin-visualizer` 또는 Webpack Bundle Analyzer를 통해 번들 내부의 'Bloat'을 시각적으로 식별하고 제거.
## 매 한 줄
> **"매 byte 매 less 매 user time 매 less"**. Bundle size optimization은 production JS/CSS payload를 줄여 LCP/INP/TBT 개선 + mobile-first user 의 perceived speed 개선. 2026 standard tooling: Vite + Rollup tree-shaking, modern bundle analysis (Bundle Buddy, esbuild-visualizer), bundle budgets enforcement.
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
- **워터폴(Waterfall) 현상**: 지연 로딩을 남발할 경우 청크 간의 의존성으로 인해 순차적 로딩 지연이 발생하여 체감 성능이 오히려 저하될 수 있다.
- **네트워크 요청 수 증가**: 번들을 너무 작게 쪼개면 HTTP 요청 수가 급증하여 네트워크 오버헤드가 발생할 수 있으므로 적절한 청크 사이즈(예: 30KB~100KB) 유지가 필요하다.
- **캐시 무효화 관리**: 청크 분할 전략이 잘못될 경우 작은 코드 수정에도 모든 벤더 청크의 해시가 변경되어 캐시 효율이 떨어질 수 있다.
## 매 핵심
## 🔗 지식 연결 (Graph)
### Related Concepts (Auto-Linked)
* [[Code Splitting]]
* [[Core_Web_Vitals]]
* [[Hydration]]
* [[Index]]
* [[Lazy Loading]]
* [[Optimization]]
* [[React]]
* [[Research]]
* [[Rollup]]
### 매 4 lever
- **Tree shaking**: ESM only, sideEffects:false, no re-export wildcards.
- **Code splitting**: route / component lazy import.
- **Compression**: brotli > gzip; precompress at build.
- **Dependency surgery**: heavy lib → lighter alt or self-implement.
### Related Concepts
- **Code Splitting**: 번들을 물리적으로 분리하는 구현 패턴 (관계: 실천 방법)
- **Core Web Vitals**: 번들 최적화의 성공 여부를 측정하는 정량적 지표 (관계: 성능 평가)
- **Hydration**: 번들 크기가 클수록 직접적으로 지연되는 클라이언트 활성화 과정 (관계: 직접 영향)
### 매 측정 우선
- Bundle visualizer (rollup-plugin-visualizer, source-map-explorer).
- Bundle budget in CI (e.g., size-limit, bundlesize).
- Real device testing (slow 3G profile).
### Deeper Research Questions
1. Vite의 `manualChunks` 설정 시 변동 주기가 다른 라이브러리들을 어떻게 그룹화하는 것이 캐시 히트율에 가장 유리한가?
2. `React.lazy`를 비동기 데이터 페칭 로직과 결합할 때 레이턴시를 최소화하는 프리페칭(Prefetching) 전략은?
3. 트리 쉐이킹이 작동하지 않는 CommonJS 기반 라이브러리를 ESM 환경에서 어떻게 효율적으로 격리할 것인가?
4. 서버 컴포넌트 환경에서 클라이언트 번들에 의도치 않게 포함되는 서버 사이드 로직을 어떻게 정적으로 감지할 것인가?
5. 번들 압축 기법(Gzip vs Brotli)과 번들 크기 최적화 사이의 실제 사용자 로딩 시간 상관관계는?
### 매 응용
1. Lazy-load route chunks.
2. Remove unused locales (date-fns, moment).
3. Replace lodash with native / lodash-es.
### Practical Application Contexts
- **Vite Configuration**: `vite.config.ts`에서 Rollup 옵션을 조정하여 벤더 청크 분리.
- **Performance Budgeting**: CI/CD 단계에서 특정 번들 사이즈 초과 시 빌드를 실패하게 만드는 성능 예산 설정.
## 💻 패턴
### Adjacent Topics
- **Brotli / Gzip Compression**
- **Tree Shaking & ES Modules**
- **HTTP/2 & HTTP/3 Multi-plexing**
### Vite + visualizer
```ts
// vite.config.ts
import { defineConfig } from 'vite';
import { visualizer } from 'rollup-plugin-visualizer';
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
**언제 이 지식을 쓰는가:**
- *(TODO)*
**언제 쓰면 안 되는가:**
- *(TODO)*
## 🧪 검증 상태 (Validation)
- **정보 상태:** needs_review
- **출처 신뢰도:** A
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
## 🧬 중복 검사 (Duplicate Check)
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
- **처리 방식:** UPDATE (자동 정규화)
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
## 🕓 변경 이력 (Changelog)
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|------|-----------|-----------|--------|
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
## 💻 코드 패턴 (Code Patterns)
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
```text
# TODO
export default defineConfig({
plugins: [
visualizer({ filename: 'stats.html', gzipSize: true, brotliSize: true })
],
build: {
rollupOptions: {
output: {
manualChunks: {
react: ['react', 'react-dom'],
vendor: ['date-fns', 'zustand']
}
}
}
}
});
```
## 🤔 의사결정 기준 (Decision Criteria)
### Route-level code split (React)
```tsx
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./Dashboard'));
**선택 A를 써야 할 때:**
- *(TODO)*
<Suspense fallback={<Skeleton />}>
<Dashboard />
</Suspense>
```
**선택 B를 써야 할 때:**
- *(TODO)*
### Dynamic import for rare path
```ts
async function exportToPDF(data: Item[]) {
const { jsPDF } = await import('jspdf');
const doc = new jsPDF();
doc.text(JSON.stringify(data), 10, 10);
doc.save('out.pdf');
}
```
**기본값:**
> *(TODO)*
### Replace heavy lib
```ts
// X moment (~290KB)
import moment from 'moment';
moment().format('YYYY-MM-DD');
## ❌ 안티패턴 (Anti-Patterns)
// O Intl (built-in, 0KB)
new Intl.DateTimeFormat('en-CA').format(new Date());
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
// O date-fns/format (tree-shakeable, ~3KB)
import { format } from 'date-fns/format';
format(new Date(), 'yyyy-MM-dd');
```
### sideEffects flag
```json
// package.json — library author 측
{
"name": "my-lib",
"type": "module",
"sideEffects": false,
"exports": {
".": {
"import": "./dist/index.mjs",
"types": "./dist/index.d.ts"
}
}
}
```
### size-limit budget enforcement
```json
// package.json
{
"scripts": {
"size": "size-limit"
},
"size-limit": [
{ "path": "dist/index.js", "limit": "50 KB" },
{ "path": "dist/vendor.js", "limit": "120 KB" }
]
}
```
### Compression at build (brotli)
```ts
import compression from 'vite-plugin-compression2';
export default defineConfig({
plugins: [
compression({ algorithm: 'brotliCompress', exclude: [/\.(br)$/, /\.(gz)$/] })
]
});
```
### Server: strip locales from dayjs
```ts
import dayjs from 'dayjs';
import 'dayjs/locale/ko'; // 매 필요한 것만
dayjs.locale('ko');
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| Initial bundle > 200KB | route split + lazy load |
| Single heavy lib | replace 또는 dynamic import |
| Multi-tenant build | per-tenant treeshake config |
| Library publish | ESM + `sideEffects:false` |
| Edge runtime | bundle ≤ 1MB 가까이 strict budget |
**기본값**: measure first → split → compress → swap heavy deps.
## 🔗 Graph
- 부모: [[Frontend Performance]] · [[Build Tools]]
- 변형: [[Code Splitting]] · [[Tree Shaking]]
- 응용: [[Core Web Vitals]] · [[LCP]]
- Adjacent: [[Vite]] · [[Rollup]] · [[esbuild]]
## 🤖 LLM 활용
**언제**: webpack/vite config audit, lib alternative suggestion, bundle analyzer interpretation.
**언제 X**: 매 production 매 swap deploy — actual measurement 필수.
## ❌ 안티패턴
- **CommonJS lib import**: tree shaking blocked — ESM 사용.
- **`import * as foo`**: bundler 매 mark 매 모든 export used.
- **Polyfill 전체**: target browser baseline + browserslist으로 narrow.
- **Single chunk all**: SPA → 매 long initial — split per route.
- **Dev source maps in prod**: ship source map only via separate URL or skip.
## 🧪 검증 / 중복
- Verified (web.dev bundle size guide, Vite docs, size-limit GitHub).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — bundle optim 4 lever + Vite/size-limit pattern |