트리 쉐이킹(Tree Shaking)은 사용되지 않는 코드(Dead Code)를 번들에서 제거하는 최적화 기법이다. ES 모듈의 정적 구조를 분석해 참조되지 않는 exports를 번들에서 제거한다. 용어는 "나무를 흔들어 죽은 잎을 떨어뜨린다"는 비유에서 유래했다.
작동 원리
javascript
// utils.js - 여러 함수 export
export function add(a, b) { return a + b; }
export function multiply(a, b) { return a * b; }
export function subtract(a, b) { return a - b; } // 사용 안 함
// main.js
import { add, multiply } from './utils'; // subtract는 임포트 안 함
// 번들 결과: subtract 함수가 제거됨
ES 모듈이 필요한 이유
javascript
// CommonJS: 동적 구조 → 트리 쉐이킹 불가
const utils = require('./utils');
const fn = utils[dynamicName]; // 런타임에 결정 → 전부 포함
// ES Modules: 정적 구조 → 트리 쉐이킹 가능
import { add } from './utils'; // 컴파일 시 분석 가능
트리 쉐이킹 방해 요소
javascript
// 나쁜 예: 사이드 이펙트 있는 임포트
import 'some-polyfill'; // 사이드 이펙트로 간주 → 제거 안 됨
// package.json에 sideEffects 명시
{
"sideEffects": ["*.css", "polyfills.js"],
"sideEffects": false // 모든 파일이 사이드 이펙트 없음
}
javascript
// 나쁜 예: 전체 라이브러리 임포트
import _ from 'lodash'; // 전체 lodash 포함
_.map(array, fn);
// 좋은 예: 필요한 것만 임포트
import map from 'lodash/map'; // lodash-es 또는 개별 임포트
import { map } from 'lodash-es'; // ES 모듈 버전
typescript
// vite.config.ts
export default defineConfig({
build: {
// 트리 쉐이킹은 기본 활성화
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // console.log 제거
drop_debugger: true, // debugger 제거
pure_funcs: ['console.log'],
},
},
},
});
효과 측정
bash
# 번들 크기 비교
# lodash (전체): ~70KB gzip
# lodash-es (트리 쉐이킹): ~2KB gzip (map만 사용 시)
# date-fns 전체: ~75KB vs 필요한 함수만: ~2KB
관련 개념