목록 보기
Webpack 빌드에 날개를 달아줄 Esbuild-Loader
기타

Webpack 빌드에 날개를 달아줄 Esbuild-Loader

Webpack Loaders Webpack(웹팩)은 요즘의 웹 프론트엔드 개발 환경에서 주로 사용되고 있는 모듈 번들러입니다. 웹팩은 기본적으로 자바스크립트 리소스만 읽고 처리할 수 있는데요. HTML, CSS, Image, Font 와 같은 리소스도 모듈로 처리될 수 있도록 하려면 별도의 전처리기가 필요합니다. 이 과정을 수행해주는 것이 로더의 역할입니다. 웹팩을 통해 SPA(Single Page Application) 개발을 경험해보셨다면 Babel이라는 용어가 익숙하실 겁니다. 안타깝게도 모든 브라우저가 최신 스펙의 ECMAScript 문법을 지원하지 못하기 때문에 Babel을 통해 그러한 브라우저에서도 실행될 수 있도록 소스 코드의 형태를 변경(Transpile)하는 작업을 수행하게 됩니다. 보통 웹팩 설정파일에서 다음처럼 Babel-Loader 전처리기 설정을 입력하여 웹 애플리케이션을 다양한 브라우저에서 실행할 수 있도록 합니다. module.exports = ( ..., module: ( rules: [ ( test: /.(j|t)sx?$/,, use: ["babel-loader"], exclude: /node_modules/, ), ], ), ) Webpack의 번들링 동작 방식 현재 웹팩의 번들링 동작 방식에는 오버헤드가 존재합니다. 프로젝트 소스 코드상에서 사소한 한 부분만을 수정하여도 웹팩의 경우 설정상의 엔트리 파일부터 시작하여 다시 의존성 그래프를 구성하고 전체 프로젝트를 리빌딩하기 시작합니다. https://vitejs.dev/guide/why.html#the-problems 이 과정에서 프로젝트의 모든 자바스크립트 소스 코드 또한 Babel-Loader의 전처리 과정을 다시 수행하게 됩니다. 이런 부분에서 필요 이상의 시간을 소모하게 되는 것이죠. 번들링 동작 방식을 본질적으로 변경하기 어렵다면 이 전처리 과정에 대한 수행 시간을 줄이는 것이 대안이 될 수 있겠습니다. 그러므로 Babel-Loader를 대신할 수 있는 새로운 로더를 사용해보겠습니다. Webpack 빌드의 날개 Esbuild-Loader Esbuild-Loader는 머리말에서 이렇게 소개합니다. Webpack 빌드시 Esbuild의 속도를 통해 Transpilation과 Minification 단계에 대한 더 빠른 대안을 제공합니다. 흥미롭습니다. 간단한 예제 프로젝트에서 웹팩에서 활용할 수 있는 Babel-Loader, Esbuild-Loader에 대한 설정 파일을 준비하고 실행 시간 비교를 진행해보려 합니다. 다음은 프로젝트 개발부터 시작하여 프로덕션 배포 과정까지 마주할 수 있는 상황들입니다. Dev Server StartTime Dev Server Hot Module Replacement Time Production Build Time On Local Machine Production Build Time On Github Actions CI 실행 시간 측정은 웹팩 빌드시 각각의 로더나 플러그인의 처리시간을 측정하여 반환하는 라이브러리인 Speed-Measure-Webpack-Plugin을 활용하려 하였으나 웹팩 5 이상 버전에서 원활하게 구동하기 어려운 관계로(참고) 최대한 설정상에서 Transpiler, Minifier만 변경하도록 하고 빌드 시에 기본 출력되는 컴파일 완료 시간 값을 수집했습니다. webpack 5.72.1 compiled successfully in 3618 ms Webpack 빌드 타임 비교 다음의 항목들은 실행 상황 항목별로 웹팩이 컴파일 완료한 시간 데이터를 정리한 내용입니다. 각 시행(Attempt)마다 얼마나 시간이 걸렸는지는 프로젝트 규모나 하드웨어 성능에 의존적으로 변하는 값이기 때문에 크게 의미를 둘 필요는 없으나, Esbuild-Loader를 사용했을 때 Babel-Loader 대비 상대적으로 얼마나 빠르게 작업을 수행했는지를 비교하는 것은 의미가 있습니다. Dev Server StartTime 웹팩 개발 서버 구동을 위해 처음으로 프로젝트 컴파일을 완료하는 시간입니다. | Transpiler / Attempt | #1 | #2 | #3 | #4 | #5 | Avg | Babel-Loader | 4095ms | 3353ms | 3208ms | 3171ms | 3172ms | 3399.80ms | Esbuild-Loader | 2230ms | 2007ms | 2011ms | 1927ms | 1982ms | 2031.40ms Dev Server Hot Module Replacement Time 웹팩 개발 서버가 시작되고 난 후 HMR 기능이 동작하기 위해 리빌드되는 시간입니다. | Transpiler / Attempt | #1 | #2 | #3 | #4 | #5 | Avg | Babel-Loader | 183ms | 243ms | 182ms | 163ms | 225ms | 199.20ms | Esbuild-Loader | 109ms | 118ms | 75ms | 108ms | 100ms | 102.00ms Production Build Time On Local Machine 프로젝트 빌드 명령어를 통해 로컬 머신에서 웹팩 빌드 프로세스가 완료되는 시간입니다. | Transpiler + Minifier / Attempt | #1 | #2 | #3 | #4 | #5 | Avg | Babel-Loader + Terser Minify | 5637ms | 5647ms | 5697ms | 5554ms | 5552ms | 5617.40ms | Esbuild-Loader + Esbuild Minify | 2174ms | 2238ms | 2364ms | 2175ms | 2240ms | 2238.20ms Production Build Time On Github Actions CI 프로젝트 빌드 명령어를 통해 Github Actions CI 환경상에서 웹팩 빌드 프로세스가 완료되는 시간입니다. | Transpiler + Minifier / Attempt | #1 | #2 | #3 | #4 | #5 | Avg | Babel-Loader + Terser Minify | 19747ms | 12927ms | 21526ms | 16425ms | 14883ms | 17101.60ms | Esbuild-Loader + Esbuild Minify | 3919ms | 7674ms | 5158ms | 4722ms | 6426ms | 5599.80ms Production 빌드 타임의 상대적인 차이가 Dev 빌드보다 훨씬 크게 나타난 것을 확인할 수가 있습니다. 두 상황에 대한 변인은 Minify 절차 진행 유무입니다. 실제로 Production 빌드를 하는 상황에서 Babel-Loader + Terser를 사용하는 경우와 Esbuild-Loader + EsbuildMinifyPlugin을 사용하는 설정 구성을 나누어 진행했습니다. 결론적으로 Minify 절차도 전체 빌드 타임에서 차지하는 부분이 크다는 것을 추론해볼 수 있습니다. module.exports = ( ..., optimization: ( minimizer: [ new ESBuildMinifyPlugin(( target: "es2020", css: true, )), ], ), ) 다음의 링크에서 전체 빌드 로그를 확인할 수 있습니다. Build By Esbuild History Build By Babel + Terser History 왜 더 빠른가 ? Esbuild는 Go 언어로 작성된 모듈 번들러이기 때문입니다. 먼저 JavaScript와 Go 언어가 동작하는 본질적인 차이에서 퍼포먼스 차이가 발생합니다. 자바스크립트는 인터프리터 언어이기 때문에 프로그램을 실행할 때 한줄 한줄 인터프리터가 기계어로 변환하는 작업을 실행합니다. 반면 Go의 경우에는 프로그램 실행 전 컴파일 단계에서 미리 소스 코드를 전부 기계어로 변환해놓습니다. 실행하는 단계에서 소스 코드가 기계어로 변환되는 작업이 생략됩니다. 그리고 다중 작업을 동시에 수행할 수 있는 능력에서 차이가 발생합니다. 싱글 스레드 기반인 자바스크립트는 한 번에 한 파일씩 순차적으로 번들링 혹은 트랜스파일링 되어야 하지만 Go의 경우 공유 메모리 환경 아래에서 멀티 스레드 기반으로 동작할 수 있습니다. 그것은 여러 파일이 동시에 번들링 되거나 트랜스파일링 될 수 있다는 의미입니다. 현재는 웹팩에서 로더 형태로만 사용하고 있기 때문에 Transpile, Minify 절차만 위임하고 있기는 하지만요. 조금 더 상세한 내용은 참고자료 링크를 확인 부탁드립니다. 결론 주관적인 의견이지만 Babel-Loader를 사용하던 설정에서 Esbuild-Loader를 사용했을 때 프로젝트 실행 시 쉽게 핸들링하기 어려운 사이드 이펙트가 발견되는 것이 아니라면 한번 교체해보는 것을 권유합니다. 모듈 번들러를 완전히 교체하는 작업은 수정사항이 매우 크게 발생할 것이기 때문에 부담이 되겠지만 동일한 번들러를 사용하는 상황에서 내부 구성 요소인 로더나 플러그인을 다른 설정으로 입력해보고 테스트해 보는 것은 작업 코스트 대비 실행시간 측정자료를 참고했을 때 많게는 3배 이상의 시간을 절약할 수 있을 것입니다. 참고 자료 Esbuild-Loader Github Why Esbuild Fast.1 Why Esbuild Fast.2 Lets Talk About Esbuild Webpack Config Examples

댓글 0

댓글을 작성하려면 로그인이 필요합니다.

댓글을 불러오는 중...