번들 사이즈 최적화
번들 사이즈는 초기 로딩 속도에 직접적인 영향을 미칩니다. 사용하지 않는 코드를 제거하고, 필요한 시점에만 로드하는 것이 핵심입니다.
면접에서 "초기 로딩 속도를 어떻게 개선하나요?"라고 물으면, 번들 분석 → 코드 분할 → Tree-shaking 순서로 설명할 수 있어야 합니다.
번들 분석
# rollup-plugin-visualizer로 번들 구성 확인
npm install -D rollup-plugin-visualizer
// vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
plugins: [
vue(),
visualizer({
open: true, // 빌드 후 자동으로 열기
gzipSize: true, // gzip 크기도 표시
brotliSize: true
})
]
})
코드 분할 전략
// router/index.ts — 라우트별 코드 분할
const routes = [
{
path: '/',
component: () => import('@/views/HomeView.vue')
},
{
path: '/dashboard',
component: () => import('@/views/DashboardView.vue'),
children: [
{
path: 'analytics',
// 청크 이름 지정으로 관련 컴포넌트 그룹핑
component: () => import(/* webpackChunkName: "dashboard" */ '@/views/AnalyticsView.vue')
}
]
}
]
<script setup lang="ts">
import { defineAsyncComponent } from 'vue'
// 조건부 로딩 — 사용자가 필요로 할 때만
const RichEditor = defineAsyncComponent(() =>
import('@/components/RichEditor.vue')
)
const ChartComponent = defineAsyncComponent(() =>
import('@/components/ChartComponent.vue')
)
</script>
<template>
<RichEditor v-if="editMode" />
<ChartComponent v-if="showChart" />
</template>
Tree-shaking 활용
// 나쁜 예: 전체 라이브러리 import
import _ from 'lodash'
_.debounce(fn, 300)
// 좋은 예: 필요한 함수만 import
import debounce from 'lodash/debounce'
debounce(fn, 300)
// 더 좋은 예: 전용 패키지
import { debounce } from 'lodash-es' // ESM 버전
// Vue의 API도 tree-shakable
import { ref, computed } from 'vue' // 사용한 것만 번들에 포함
큰 의존성 대체
moment.js (72KB gzip) → date-fns (tree-shakable) 또는 dayjs (2KB)
lodash (72KB gzip) → lodash-es (tree-shakable)
chart.js → 필요한 컴포넌트만 등록
axios → 네이티브 fetch (별도 라이브러리 불필요)
Vite 빌드 최적화
// vite.config.ts
export default defineConfig({
build: {
// 매뉴얼 청크 분할
rollupOptions: {
output: {
manualChunks: {
// vendor 라이브러리를 별도 청크로
'vue-vendor': ['vue', 'vue-router', 'pinia'],
'ui-vendor': ['@headlessui/vue']
}
}
},
// 청크 크기 경고 임계값
chunkSizeWarningLimit: 500, // KB
// CSS 코드 분할
cssCodeSplit: true,
// 소스맵 (프로덕션에서는 비활성화 권장)
sourcemap: false,
// minify 옵션
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // console.log 제거
drop_debugger: true
}
}
}
})
동적 import와 prefetch
<script setup lang="ts">
import { onMounted } from 'vue'
onMounted(() => {
// 유휴 시간에 미리 로드 (prefetch)
if ('requestIdleCallback' in window) {
requestIdleCallback(() => {
import('@/views/HeavyView.vue')
})
}
})
</script>
면접 팁
- 번들 분석이 첫 단계 입니다. 무엇이 크기를 차지하는지 모르면 최적화할 수 없습니다
import()동적 import가 코드 분할의 핵심이라는 것을 알고 있어야 합니다- Tree-shaking이 동작하려면 ESM(ES Modules) 형식 이어야 한다는 점을 설명할 수 있으면 좋습니다
요약
번들 사이즈 최적화는 분석(visualizer) → 코드 분할(라우트/컴포넌트) → Tree-shaking(named import) → 의존성 최적화(경량 대체) → 빌드 설정(manualChunks, minify) 순서로 진행합니다. Vue 3와 Vite는 기본적으로 Tree-shaking을 지원하므로, 올바른 import 방식만으로도 큰 효과를 볼 수 있습니다.
댓글 로딩 중...