1. 개선 방향
bundle size 분석을 위하여 webpack-bundle-analyzer를 사용하였습니다. [부록 4.1]
성능 개선을 위하여 번들파일 분석을 진행하였고, 우선적으로 가장 사이즈가 큰 vender 파일을 중점으로 개선방향을 모색하였습니다.
현재 벤더파일의 문제점으로 용량이 큰 라이브러리(lodash, moment)들이 트리쉐이킹 되지지 않은 채 통째로 번들링되어 벤더파일로 적재되어 있는것을 발견하였고 이를 경량화 하는것을 이번 태스크의 목표로 잡았습니다.S
2. 개선 과정
단순 타겟 라이브러리의 개선 결과가 아닌 과정을 기록한 이유는 향후 다른 라이브러리를 도입하게 될 때 이번 트리쉐이킹에서 배제된 기술들이 더 용이한 경우도 있어 참고용으로 기록하였습니다.
2.1 lodash
현재 프로젝트에서 lodash를 사용하는 구문은 아래와 같습니다.
import { orderby } from 'lodash'; //71.1k
현재 개발환경에서 named import 를 사용하는건 탁월한 선택입니다. webpack에서 자동으로 tree shaking을 진행하여 사용되지 않은 메소드들은 번들파일에 포함되지 않기 때문입니다. 하지만 예외 사항으로 위의 lodash 처럼 commonJS 모듈을 사용하는 경우는 webpack은 트리쉐이킹을 진행하지 않습니다.
이를 해결하기 위하여 lodash를 트리쉐이킹하는 보편적인 3가지 방법을 소개하겠습니다
2.1.2 default import
import orderBy from "lodash/orderBy"; //20.8k
const arr = [1, 2, 3, 4, 5];
orderBy(arr, (num) => {
console.log(num, "hello");
});
장점: lodash는 default import가 가능하며, 지정한 메서드만 사용하기 때문에 이미 트리쉐이킹 한 효과를 줄 수 있습니다.
단점: lodash의 메서드를 사용하기 때문에 lodash-es보다 사이즈가 크며 lodash의 여러가지 기능을 사용 시 부수적인 작업이 필요합니다.
ex) 여러개의 메소드드 가져올 시 webpack 세팅 필요
// 개별 import
import orderBy from "lodash/orderBy";
import debounce from "lodash/debounce";
//여러개 import 시 webpack 세팅 필요
import {orderBy, debounce} from "???"
2.1.3 lodash-es
import { orderBy } from "lodash-es"; //16.4k
const arr = [1, 2, 3, 4, 5];
orderBy(arr, (num) => {
console.log(num, "hello");
});
장점: es6 구문으로만 쓰여저 가장 크기가 작으며, commonJS 모듈을 사용하지 않아 웹팩에서 tree shaking을 지원해줍니다. 즉 import 시 조금만 신경을 쓸 시 webpack 세팅이나 babel-plugin-lodash 등을 사용하지 않아도 자유롭게 사용 가능합니다.
단점: lodash uninstall 후 lodash-es 설치, import 변경 ‘lodash’ ⇒ ‘lodash-es’
2.1.4 개선 결과
2.1.3 lodash-es를 채택하여 현 프로젝트에 적용 시켜 보았습니다.
부수적인 코드 작성 없이 성능개선을 이루어낼 수 있었습니다
2.2 moment
현 프로젝트에서 moment의 사용은 아래와 같이 이루어져 있습니다.
import moment from 'moment';
formatDate(date) {
return date ? moment(date.slice(0, 8)).format('MM월 DD일') : '';
}
현재 moment의 일부 기능만 사용하지만 모든 moment 기능이 트리쉐이킹 되지 않고 남아있는것을 볼 수 있습니다. 이를 개선하기위한 3가지 방법을 소개하겠습니다.
2.2.1 IgnorePlugin
const webpack = require('webpack')
module.exports = {
plugins: [
new webpack.IgnorePlugin(/^\\.\\/locale$/, /moment$/),
],
}
웹팩 내장 메서드를 사용하여 moment의 locale을 전부 무시할 수 있습니다. locale을 사용하지 않고 순수 date조작 기능만 사용하는 경우 유용한 방법입니다.
2.2.2 ContextReplacementPlugin 사용
const webpack = require('webpack')
module.exports = {
plugins: [
new webpack.ContextReplacementPlugin(/moment[/\\\\]locale$/, /ko/),
],
}
웹팩 내장 메서드를 사용하여 moment의 특정 locale만 추가하여 가져올 수 있는 방법입니다. date조작 및 특정 언어의 지원이 필요할 시 유용한 방법입니다.
2.2.3 moment → dayjs
moment를 뜯어내고 dayjs를 도입하는 방법입니다.
moment 단점
- 내부적으로 정규표현식을 사용하여 타 date 라이브러리보다 느림
- 용량이 무겁고 locale을 트리쉐이킹 하더라도 타 data 라이브러리 보다 무거움
- Moment 라이브러리의 개발 중단(업데이트 x 트리쉐이킹 개선 x)
dayjs 장점
- Immutable
- 2KB의 경량 사이즈
- moment의 대부분의 기능 대체 가능 및 사용법이 비슷해 러닝커브가 짧음
- 가장많이 쓰는 date 라이브러리
2.2.4 개선 결과
2.2.2의 contextReplacementPlugin을 사용하여 해결하였습니다.
webpack에 간단한 플러그인을 추가하여 성능 개선을 이루어 낼 수 있었습니다.
2.2.1 미채택 - 현 프로젝트에서 moment.local(’ko’) 의 사용
2.2.3 미채택 - 팀원들의 협의가 필요
3. 개선 결과
번들사이즈 전/후
빌드 속도 전/후
빌드 속도 측정을 위하여 [부록 4.2]의 speed-measure-webpack-plugin 를 사용하였습니다.
청크 사이즈 축소 435kb → 350 kb
번들 사이즈 측면에서 10%이상의 개선효과를 볼 수 있었으며, 빌드 속도 측면에서는 40%이상의 개선 효과가 있었습니다.
4. 부록
4.1 webpack-bundle-analyzer
4.1.1 소개
웹팩 번들 분석 플러그인 입니다. 웹팩을 이용하여 번들링되는 모듈들을 분석해서 시각적으로 나타냅니다.
자세한 사용법은 사이트 참조
4.1.2 사용법
# install
npm install --save-dev webpack-bundle-analyzer
//usage (as a plugin)
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
...
plugins: [
new BundleAnalyzerPlugin() //webpack 플러그인에 추가
]
...
}
실행 방법
- npm 설치
- 플러그인 추가
- 컴파일 시 자동실행
4.2 speed-measure-webpack-plugin
https://github.com/stephencookdev/speed-measure-webpack-plugin
4.1.1 소개
웹팩 번들 분석 플러그인 입니다. 웹팩을 이용하여 번들링되는 모듈들을 분석해서 시각적으로 나타냅니다.
4.1.2 사용법
# install
npm install --save-dev speed-measure-webpack-plugin
//usage (as a plugin)
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
const webpackConfig = smp.wrap({
plugins: [new MyPlugin(), new MyOtherPlugin()],
})
//smp.wrap으로 webpack 설정 감싸주기
//vue cli 기준 configureWebpack: smp:wrap({}) 자세한 이유는 vue cli 참조
실행 방법
- npm 설치
- 플러그인 추가
- 컴파일 시 자동 실행
'개발' 카테고리의 다른 글
[nextjs 톺아보기] <head> (0) | 2025.04.08 |
---|---|
Vue Ref 톺아보기 (0) | 2025.03.26 |
빌드시스템은 왜 필요할까? (0) | 2025.03.26 |
자바스크립트 이벤트 루프와 비동기 통신의 실행순서 (2) | 2024.09.06 |