--- id: wiki-2026-0508-code-splitting title: Code Splitting category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Bundle Splitting, Dynamic Import] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [bundling, performance, webpack, vite, frontend] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: TypeScript framework: Vite / Webpack / Next.js --- # Code Splitting ## 매 한 줄 > **"매 bundle 의 chunk 의 분리, on-demand load 의 first-paint 단축"**. Code Splitting 은 dynamic `import()` + bundler chunking 의 결합 의 매 monolithic JS bundle 의 분해. 2026 Vite/Rspack/Turbopack 시대 에 route-level + component-level + vendor split 의 매 표준. ## 매 핵심 ### 매 splitting 의 axis - **Route-based**: 각 page 의 separate chunk — 매 SPA / Next.js 의 default - **Component-based**: heavy component 의 lazy (Modal, Chart, Editor) - **Vendor**: `node_modules` 의 separate chunk — long-term cache - **Dynamic feature**: locale, A/B variant 의 conditional load ### 매 mechanism - **Dynamic `import()`**: ECMAScript spec — Promise 의 return - **Bundler 의 split point detection**: `import()` 호출 의 chunk boundary - **Manifest**: hashed filename 의 mapping - **Preload / prefetch**: `` hint ### 매 cost trade-off - **Pro**: initial bundle 의 작아짐 → faster TTI - **Con**: extra HTTP request, waterfall 위험 — preload 의 mitigate ### 매 응용 1. Route-level lazy (React Router, Next.js). 2. Modal / dialog (open 시 load). 3. Heavy editor (Monaco, CodeMirror). 4. Chart library (Recharts, ECharts). 5. i18n locale chunk. ## 💻 패턴 ### React.lazy + Suspense ```tsx import { lazy, Suspense } from 'react'; const Settings = lazy(() => import('./Settings')); export default function App() { return ( }> ); } ``` ### Next.js dynamic ```tsx import dynamic from 'next/dynamic'; const Chart = dynamic(() => import('@/components/Chart'), { loading: () =>

Loading chart...

, ssr: false, // browser-only }); export default function Dashboard() { return ; } ``` ### Route-level (React Router v6) ```tsx import { lazy } from 'react'; import { createBrowserRouter, RouterProvider } from 'react-router-dom'; const router = createBrowserRouter([ { path: '/', lazy: () => import('./routes/Home') }, { path: '/about', lazy: () => import('./routes/About') }, { path: '/admin/*', lazy: () => import('./routes/Admin') }, ]); export default function App() { return ; } ``` ### Vite의 manualChunks ```ts // vite.config.ts import { defineConfig } from 'vite'; export default defineConfig({ build: { rollupOptions: { output: { manualChunks: { react: ['react', 'react-dom'], ui: ['@radix-ui/react-dialog', '@radix-ui/react-tabs'], charts: ['recharts', 'd3'], }, }, }, }, }); ``` ### Webpack magic comment ```ts const Editor = () => import( /* webpackChunkName: "editor" */ /* webpackPrefetch: true */ './Editor' ); ``` ### Conditional import (locale) ```ts async function loadLocale(lang: string) { const messages = await import(`./locales/${lang}.json`); return messages.default; } ``` ### Preload critical chunk ```html ``` ```tsx // React: preload on hover import('./Settings')} > Settings ``` ### Module Federation (micro-frontend) ```ts // host webpack.config.js new ModuleFederationPlugin({ remotes: { checkout: 'checkout@https://cdn/checkout/remoteEntry.js', }, }); // usage const Checkout = lazy(() => import('checkout/Cart')); ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | SPA, multi-page | Route-based split | | Heavy modal / editor | `lazy()` + Suspense | | Vendor lib stable | manualChunks vendor split | | SSR + browser-only | `dynamic({ ssr: false })` | | Independent deploy | Module Federation | | Hover-triggered | preload on intent | **기본값**: route-based + heavy-component lazy + vendor chunk. ## 🔗 Graph - 부모: [[Web Performance]] - 변형: [[Module Federation]] - 응용: [[Lazy-Loading-Strategies|Lazy Loading]] - Adjacent: [[Vite]] · [[Next.js]] · [[Suspense]] ## 🤖 LLM 활용 **언제**: route lazy, heavy component 의 split, vendor chunking 코드 generation. **언제 X**: 매 small app (10kb 의 split 의 overhead 가 더 큼). ## ❌ 안티패턴 - **너무 fine-grained split**: 100개 chunk → request flood — 매 ~10-30 chunk 의 sweet spot. - **Waterfall**: A → B → C 의 sequential — 매 parallel preload. - **Vendor chunk 의 무한 growth**: dependency 추가 시 cache invalidation — 매 stable lib 만 vendor. - **Suspense 의 boundary 누락**: error / blank screen. - **`ssr: false` 의 abuse**: SEO 손실. ## 🧪 검증 / 중복 - Verified (Vite docs, Webpack docs, Next.js docs, React 19). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — splitting strategies + bundler config + MF |