stack-analysis
CHAPTER 93 / 120
읽기 약 2분
FUNCTION
번들 최적화: Tree Shaking + Code Splitting
핵심 개념
webpack/rollup·dynamic import·side effects·analyze — JS 80% 감소.
본문
Tree Shaking 작동 조건
1. ESM (import/export) — CommonJS 안 됨
2. side effects 표시 (package.json)
3. 사용 안 하는 코드는 export 안 됨
// package.json
{
"sideEffects": false // 모든 import 제거 가능
}
// 또는 일부만 부수효과
{
"sideEffects": ["./src/polyfills.ts", "*.css"]
}잘못된 import — Tree shaking 안 됨
// ❌ 전체 lodash (70KB)
import _ from 'lodash';
_.debounce(fn, 300);
// ❌ named import도 lodash main entry는 CJS
import { debounce } from 'lodash';
// → 여전히 전체 import
// ✅ 개별 entry import
import debounce from 'lodash/debounce';
// → 1KB만
// ✅ lodash-es (ESM 버전)
import { debounce } from 'lodash-es';
// → tree-shake 가능큰 라이브러리 대체
| 라이브러리 | 크기 | 대체 | 크기 |
|---|---|---|---|
| moment | 290KB | date-fns | 13KB (필요한 함수만) |
| moment | 290KB | dayjs | 7KB |
| lodash | 70KB | lodash-es + named | 5KB |
| jquery | 87KB | vanilla JS | 0KB |
| chart.js | 200KB | recharts | 90KB |
| chart.js | 200KB | uPlot | 40KB |
| axios | 35KB | fetch + ofetch | 5KB |Code Splitting — Dynamic Import
// 라우트별 자동 분할 (Next.js)
// app/heavy/page.tsx → 별도 chunk
// 컴포넌트 동적 로드
import dynamic from 'next/dynamic';
const HeavyChart = dynamic(() => import('@/components/HeavyChart'), {
loading: () => <Skeleton />,
ssr: false,
});
// 조건부 로드
async function showEditor() {
const { Editor } = await import('@tiptap/react');
return <Editor />;
}
// 라이브러리 — 사용 시점에만
const handleExport = async () => {
const XLSX = await import('xlsx');
XLSX.writeFile(...);
};라우트별 prefetch
import Link from 'next/link';
<Link href="/heavy" prefetch> {/* 호버 시 prefetch */}
무거운 페이지
</Link>
// 수동 prefetch
import { useRouter } from 'next/navigation';
const router = useRouter();
useEffect(() => {
router.prefetch('/heavy');
}, []);번들 분석 — @next/bundle-analyzer
pnpm add -D @next/bundle-analyzer// next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({});ANALYZE=true pnpm build
# → /analyze/client.html, server.html 자동 열림
# → 큰 chunk 식별일반적인 큰 chunk 원인
1. Polyfills
- core-js, regenerator-runtime
→ modern browsers 대상이면 제거
2. 큰 라이브러리
- moment, lodash, antd
→ 위 대체 표 참조
3. Locales
- moment locale 모두 포함
→ 필요한 것만 import
4. Source Maps in production
- 의도치 않게 포함
→ productionBrowserSourceMaps: false (Next.js)
5. Duplicate dependencies
- 같은 라이브러리 다른 버전
→ pnpm dedupe / npm dedupeES2020+ 타깃
// next.config.js — 모던 브라우저만
module.exports = {
compiler: {
// 구 브라우저 polyfill 제거
},
};
// .browserslistrc
> 0.5%
last 2 versions
not dead
not ie 11
not op_mini all
// 결과
// - 폴리필 80% 감소
// - 코드 transpilation 최소측정 — performance budget
// next.config.js
module.exports = {
experimental: {
bundlePagesRouterDependencies: true,
},
// budget 검증 (CI)
webpack: (config) => {
config.performance = {
maxAssetSize: 250000, // 250KB
maxEntrypointSize: 400000, // 400KB
hints: 'error', // 초과 시 빌드 실패
};
return config;
},
};
// Lighthouse CI에 budget.json
[
{
"path": "/*",
"resourceSizes": [
{ "resourceType": "script", "budget": 300 },
{ "resourceType": "image", "budget": 500 },
{ "resourceType": "total", "budget": 1500 }
]
}
]다음 챕터
CH.94 "렌더링 전략: SSR vs SSG vs ISR vs CSR".
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 코드의 번들 최적화 부분을 분석해서 실전 분석 + 개선 우선순위를 알려줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
번들 최적화 관련 베스트 프랙티스 5가지를 비교 분석해서 패턴 추출를 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 프로젝트 전체에서 번들 최적화 최적화 가능 위치를 보고해줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 시장의 번들 최적화 트렌드를 솔직히 알려줘.
⭐ 이것만 기억하세요
번들 최적화: Tree Shaking + Code Splitting는 이 3가지만 확실히 잡으세요
1.Tree shaking은 ESM + sideEffects:false — CommonJS는 안 됨
2.lodash-es / dayjs / native fetch로 대체 = 200KB 절감
3.dynamic import + bundle analyzer = 큰 chunk 식별 + 분할
공유하기
진행도 93 / 120