Tree Shaking
트리 쉐이킹은 현대 자바스크립트 애플리케이션의 번들 크기를 최적화하는 중요한 기술이다.
트리 쉐이킹은 현대 웹 애플리케이션 최적화의 필수 요소가 되었다.
최적의 결과를 얻기 위한 권장 사항은 다음과 같다:
- ES 모듈 사용: 모든 코드를 ESM 형식으로 작성하고 사용.
- 번들러 선택: Rollup 또는 Webpack과 같은 트리 쉐이킹을 지원하는 번들러를 사용.
- 명시적 가져오기:
import * as
보다import { specificFunction }
을 선호. - 사이드 이펙트 관리:
sideEffects
속성을 설정하고 사이드 이펙트를 최소화. - 최신 라이브러리 선택: 트리 쉐이킹을 지원하는 라이브러리를 선택.
- 번들 분석: Bundle Analyzer를 사용하여 결과를 모니터링하고 개선.
- 순수 함수형 접근 방식: 가능한 한 순수 함수를 작성하고 사용.
자바스크립트 애플리케이션 최적화의 다른 측면과 마찬가지로, 트리 쉐이킹은 세심한 설계와 지속적인 개선이 필요한 분야이다. 적절하게 구현된다면 사용자 경험과 애플리케이션 성능에 상당한 개선을 가져올 수 있다.
트리 쉐이킹의 개념과 원리
정의
트리 쉐이킹(Tree Shaking)은 사용되지 않는 코드를 최종 번들에서 제거하는 프로세스이다.
이름은 나무를 흔들어 죽은 잎이나 가지를 떨어뜨리는 것에서 유래했다.
자바스크립트 컨텍스트에서는, 애플리케이션에서 실제로 사용되지 않는 코드(“데드 코드”)를 제거하는 것을 의미한다.
작동 원리
트리 쉐이킹의 기본 원리는 다음과 같다:
- 정적 분석: 코드를 실행하지 않고 구조를 분석한다.
- 의존성 그래프 구축: 모듈 간의 가져오기/내보내기 관계를 기반으로 의존성 그래프를 만든다.
- 사용되는 코드 식별: 애플리케이션의 진입점(entry point)에서 시작하여 실제로 접근되는 코드 경로를 추적한다.
- 미사용 코드 제거: 의존성 그래프에서 접근되지 않는 코드를 최종 번들에서 제외한다.
위 예제에서 unused
함수는 가져오지 않고 사용하지 않았기 때문에 최종 번들에서 제거된다.
트리 쉐이킹을 위한 필수 조건
트리 쉐이킹이 효과적으로 작동하기 위해서는 몇 가지 중요한 조건이 필요하다:
ES 모듈(ESM) 사용
트리 쉐이킹은 ES 모듈의 정적 구조에 크게 의존한다.
ES 모듈은 정적 가져오기/내보내기 구문을 사용하므로 번들러가 빌드 시간에 의존성 그래프를 정확하게 분석할 수 있다.사이드 이펙트 최소화
사이드 이펙트(부작용)가 있는 코드는 트리 쉐이킹을 방해할 수 있다. 사이드 이펙트란 모듈이 로드될 때 다른 모듈이나 전역 상태를 변경하는 것을 의미한다.순수 함수 선호
순수 함수(입력이 같으면 항상 같은 출력을 반환하는 함수)는 트리 쉐이킹에 이상적이다.
외부 상태에 의존하거나 외부 상태를 변경하지 않기 때문이다.
트리 쉐이킹 최적화 전략
효과적인 트리 쉐이킹을 위한 몇 가지 주요 전략은 다음과 같다:
내보내기/가져오기 최적화
사이드 이펙트 관리
순수 함수 사용
바벨 플러그인 활용
바벨의transform-imports
같은 플러그인을 사용해 자동으로 가져오기를 최적화할 수 있다:
트리 쉐이킹의 영향 및 성능 개선
트리 쉐이킹이 실제 애플리케이션에 미치는 영향을 살펴보면:
번들 크기 감소
트리 쉐이킹을 통해 다음과 같은 번들 크기 감소를 기대할 수 있다:- 작은 라이브러리: 10-30% 감소
- 대형 프레임워크: 40-60% 감소
- 유틸리티 라이브러리: 최대 90% 감소(예: Lodash)
로딩 및 실행 성능 개선
번들 크기 감소는 다음과 같은 성능 개선으로 이어진다:- 초기 로딩 시간 단축: 더 작은 번들로 다운로드 시간 단축
- 파싱 시간 감소: 브라우저가 처리해야 할 코드 양 감소
- 실행 시간 개선: 초기화해야 할 코드 감소
사례 연구: Lodash
Lodash는 트리 쉐이킹의 중요성을 보여주는 대표적인 예:
트리 쉐이킹의 한계와 도전 과제
트리 쉐이킹이 항상 완벽한 해결책은 아니다.
몇 가지 한계와 도전 과제가 있다:
동적 가져오기의 어려움
CommonJS와의 호환성 문제
사이드 이펙트 감지의 어려움
프로토타입 수정과 관련된 문제
ESM vs. CommonJS 트리 쉐이킹 비교
모듈 시스템 | 트리 쉐이킹 효과 | 정적 분석 용이성 | 번들러 지원 | 추가 구성 필요 |
---|---|---|---|---|
ES Modules (ESM) | 우수함 (90-100%) | 매우 높음 | 모든 주요 번들러 | 최소 또는 없음 |
CommonJS | 제한적 (0-40%) | 낮음 | 일부 번들러만 부분 지원 | 복잡한 구성 필요 |
AMD | 제한적 (20-50%) | 중간 | 일부 번들러 | 중간 수준 |
UMD | 제한적 (10-30%) | 낮음 | 일부 번들러 제한적 지원 | 복잡한 구성 필요 |
ESM 예시
|
|
결과: subtract
와 divide
함수는 최종 번들에서 제외된다.
CommonJS 예시
|
|
결과: 일반적으로 모든 함수가 번들에 포함되지만, 일부 번들러는 특별한 분석을 통해 제한적인 트리 쉐이킹을 시도한다.
트리 쉐이킹에 관한 번들러, 프레임워크, 라이브러리 비교
주요 번들러의 트리 쉐이킹 구현
다양한 자바스크립트 번들러는 각기 다른 방식으로 트리 쉐이킹을 구현한다:
번들러 | 트리 쉐이킹 기본 지원 | 구성 복잡성 | ESM 지원 | CommonJS 지원 | 사이드 이펙트 처리 | 성능 |
---|---|---|---|---|---|---|
Webpack | 지원 (v2+) | 중간 | 완전 지원 | 제한적 지원 | sideEffects 플래그 지원 | 중간 |
Rollup | 처음부터 내장 | 낮음 | 완전 지원 | 플러그인 필요 | 세밀한 제어 가능 | 우수함 |
ESBuild | 기본 내장 | 매우 낮음 | 완전 지원 | 제한적 지원 | 기본 지원 | 매우 우수함 |
Parcel | 기본 내장 | 거의 없음 | 완전 지원 | 제한적 지원 | 기본 지원 | 우수함 |
Browserify | 플러그인 필요 | 높음 | 플러그인 필요 | 기본 지원 | 제한적 | 낮음 |
Webpack
Webpack은 가장 널리 사용되는 번들러 중 하나로, 트리 쉐이킹을 위해 다음과 같은 기능을 제공한다:
- 프로덕션 모드:
mode: 'production'
설정으로 자동 최적화 - 사이드 이펙트 표시:
package.json
의sideEffects
필드 활용 - Terser 통합: 미사용 코드 제거를 위한 최종 최적화
Rollup
Rollup은 트리 쉐이킹에 초점을 맞춘 번들러로, 기본적으로 더 효과적인 트리 쉐이킹을 제공한다:
- ES 모듈 중심: 기본적으로 ES 모듈에 최적화됨
- 정교한 정적 분석: 더 철저한 데드 코드 검출
- 코드 분할 및 동적 가져오기 지원
ESBuild
ESBuild는 속도에 최적화된 최신 번들러로 트리 쉐이킹도 지원한다:
- Go로 작성: 매우 빠른 성능
- 기본 내장 트리 쉐이킹
- 사이드 이펙트 표시 지원
다양한 프레임워크에서의 트리 쉐이킹
프레임워크 | 트리 쉐이킹 지원 | 기본 모듈 시스템 | 사이드 이펙트 관리 | 코드 분할 지원 |
---|---|---|---|---|
React | 매우 좋음 | ESM | 컴포넌트 기반 분리 가능 | React.lazy() |
Vue.js | 좋음 | ESM | 컴포저블 API로 개선됨 | 비동기 컴포넌트 |
Angular | 매우 좋음 | ESM | NgModules 시스템 | 지연 로딩 모듈 |
Svelte | 우수함 | ESM | 컴파일 타임 최적화 | 동적 가져오기 |
Alpine.js | 중간 | ESM/IIFE | 제한적 | 제한적 |
React
React 애플리케이션에서 트리 쉐이킹 최적화:
- 컴포넌트 단위 분리: 각 컴포넌트를 개별 파일로 관리
- React.lazy()와 동적 가져오기: 필요할 때만 컴포넌트 로드
- HOC 및 렌더 프롭스 최적화: 불필요한 래퍼 컴포넌트 제거
Vue.js
Vue.js에서 트리 쉐이킹 최적화:
- ES 모듈 빌드 사용:
import Vue from 'vue/dist/vue.esm.js'
- 컴포넌트 로컬 등록: 전역 등록 대신 로컬 등록 활용
- 비동기 컴포넌트: 필요할 때만 로드
Angular
Angular에서 트리 쉐이킹 최적화:
- Angular CLI 빌드 최적화: 기본 지원됨
- 지연 로딩 모듈: 필요할 때만 모듈 로드
- NgModules 분리: 기능별로 모듈 분리
트리 쉐이킹 지원 라이브러리
트리 쉐이킹에 최적화된 몇 가지 주요 라이브러리:
라이브러리 | 트리 쉐이킹 지원 | ESM 버전 제공 | 권장 가져오기 방법 | 번들 감소 효과 |
---|---|---|---|---|
Lodash | 기본 버전은 제한적 | lodash-es | 개별 함수 가져오기 | 85-95% |
Moment.js | 미지원 | 아니오 | 대안 사용 권장 | 0% |
date-fns | 완전 지원 | 예 | 필요한 함수만 가져오기 | 90-98% |
Material-UI | 완전 지원 | 예 | 경로 가져오기 | 60-80% |
RxJS | v6+ 지원 | 예 | 파이프 가능 연산자 사용 | 70-90% |
jQuery | 미지원 | 아니오 | 대안 사용 권장 | 0% |
Ramda | 지원 | 예 | 개별 함수 가져오기 | 85-95% |
Lodash-es
Lodash의 ES 모듈 버전:
Date-fns
날짜 처리를 위한 함수형 유틸리티 라이브러리:
Material-UI / MUI
React UI 라이브러리:
실제 프로젝트에서의 트리 쉐이킹 전후 비교
실제 프로젝트에서 트리 쉐이킹 적용 전후 비교:
전형적인 프로젝트 예시 (가상 데이터)
최적화 단계 | 번들 크기 | 로딩 시간 | 실행 시간 |
---|---|---|---|
최적화 전 | 1.2MB | 780ms | 350ms |
트리 쉐이킹 적용 | 720KB | 480ms | 280ms |
추가 최적화 | 520KB | 320ms | 230ms |
Moment.js vs. Date-fns
Moment.js(트리 쉐이킹 미지원)에서 date-fns(트리 쉐이킹 지원)로 마이그레이션:
라이브러리 | 가져오기 방식 | 번들 크기 |
---|---|---|
Moment.js | import moment from 'moment' | ~230KB |
date-fns | import { format } from 'date-fns' | ~3KB |
트리 쉐이킹 진단 및 분석 도구
트리 쉐이킹 효과를 분석하고 개선하기 위한 도구들이 있다:
Webpack Bundle Analyzer
번들 내용과 크기를 시각화하여 개선 지점 식별:
|
|
Rollup Plugin Visualizer
Rollup 번들을 시각화:
|
|
Source-map-explorer
소스맵을 사용하여 번들 구성 분석:
|
|