JavaScript 번들러의 이해 — (4) Webpack 및 다른 번들러들

권세규
네이버 플레이스 개발 블로그
9 min readJun 17, 2022

--

이 글은 JavaScript 번들러의 이해 — (3) 번들러 개론에 이어지는 글로, Webpack을 비롯한 여러가지 번들러를 간단히 알아봅니다. 번들러에 대한 일반적인 이야기가 궁금하신 분들은 이전 편을 참고하시면 되겠습니다.

2022년 6월 15일 웹 생태계의 역사에 한 획을 그을 사건이 발생했습니다. 바로 Internet Explorer 지원 종료입니다. 이는 2021년부터 예고된 사실이었는데요. 이 사건은 번들러와도 밀접한 관계가 있습니다. 왜 그럴까요.

IE와 모던 브라우저의 가장 큰 차이점은 ES6 지원 유무입니다. ES6는 JavaScript 역사상 가장 큰 개변이 일어난 표준 개정안이었고, 기술적으로 웹 개발 생태계에 큰 영향을 미칠 수 밖에 없었습니다. IE는 최신 웹 기술의 발목을 잡았고, IE 사용률이 0은 아니었던 상황에서, JavaScript 파일을 합치는 번들러는 이를 의식할 수 밖에 없었습니다.

후술할 최신 번들러 중 일부는 아예 IE를 고려 대상에서 제외했고, IE를 지원하고 싶었던 조직들은 이런 기술을 채택하고 싶어도 채택할 수 없었습니다. 하지만 더이상 IE를 지원할 당위성이 사라지면서, 향후 기술 선택의 폭은 한층 더 넓어지게 될 것입니다.

이런 시류 속에서, 오늘은 여전히 많이 쓰이는 Webpack과 다른 번들러들을 간단히 알아보고자 합니다.

Webpack

webpack is a bundler which bundles your assets
출처: https://webpack.js.org/

Webpack은 2014년에 1.0 버전으로 첫 등장을 했습니다. 기능이 빈약했던 browserify와 불편한 gulp의 단점을 극복하고자 했지요. 2022년 6월 기준 5.73.0 버전을 출시한 상태입니다. 소스코드 곳곳에는 차기 버전에 대한 언급도 있는데, 공식적으로는 이에 관련된 발표가 없습니다.

Webpack의 내부는 tapable이라는 자체 개발 함수형 이벤트 핸들링 라이브러리로 구현돼 있습니다. 이것들은 Plugin이라는 개념으로 추상화하여 Webpack의 근간을 이룹니다. 이런 유연한 구조 덕분에 JavaScript에만 국한되지 않고 다양한 서드파티를 수용하여, 점유율 1위라는 업적을 달성할 수 있지 않았나 싶습니다.

이 그림은 글쓴이가 직접 Webpack 소스코드를 분석하여 도식화한 것입니다.

Webpack은 위와 같은 파이프라인을 채택하고 있는데요. 이를 이해하려면 Webpack의 추상화된 요소를 이해할 필요가 있습니다. 이에 관한 구체적인 설정 값은 공식 문서를 참고하시는 것을 권장합니다.

Plugin

apply 인터페이스를 가진, 빌드 과정에 관여할 수 있는 동작의 단위. 내부적으로도 Plugin 단위로 로직을 작성하였고, 서드파티 역시 이 인터페이스로 자체 로직을 개발할 수 있습니다. (ex: ProviderPlugin , HtmlWebpackPlugin 등)

Resolution

의존성 분석 과정에서 소스코드에 포함된 파일 및 경로를 식별하고 확장자를 결정하는 것. 가령 JavaScript에서 import { foo } from '@utilities/foo' 라는 구문을 만났을 때, “@utilities”는 어떻게 해석을 해야 하는지, “foo”는 무슨 파일인지를 결정합니다.

Rule

Resolution에 의해 인식된 파일의 이름을 보고 처리 방식을 결정하는 규칙. (ex: 파일 이름이 정규표현식 \.tsx?$ 로 끝나면, 이 파일은 ts-loader 로 처리하라)

Loader

Rule에 의해 결정된 파일을 처리하는 구체적인 주체. (ex: ts-loader , style-loader , babel-loader 등) 일반적으로 트랜스파일러를 Webpack에 맞게 래핑한 서드파티 소프트웨어가 들어갑니다.

Chunk

Loader에 의해 처리된 출력물로, Webpack이 최종 연결 단계에서 다루는 단위

Webpack은 고도로 추상화된 유연한 구조 덕분에, 많은 사용자와 견고한 서드파티들을 확보하였습니다. 오랜 개발 기간 동안 쌓아올린 안정성 역시 무시할 수 없습니다. 그러나 후기에 나온 번들러에 비하면 처리 속도가 많이 느린 편이며, 트리 쉐이킹에서 대단히 부족한 모습을 보입니다.

Webpack은 create-react-app이나 Next.js 등의 유명 도구에서도 자체 내장되어 사용됩니다.

parcel

parcel은 2017년에 등장한 번들러로, zero-config에 초점을 맞춘 번들러입니다. Webpack은 강력한 기능을 제공하지만, 초심자 입장에서 배워야 할 것들이 너무 많습니다. zero-config는 번거로운 설정을 줄이고, 번들러가 최대한 많은 기본 옵션을 제공하는 사상입니다.

parcel은 Webpack과 다르게 HTML 파일을 엔트리로 지정합니다. 똑똑한 캐싱 정책을 사용하여 빌드 시간을 단축하였고, 트리 쉐이킹도 개선하였습니다. 그러나 zero-config의 태생적인 문제인 “설정이 필요한 상황”에서는 오히려 불편한 모습을 보여줍니다.

글쓴이가 개인적으로 parcel을 사용하였을 때 (22년 4월), parcel에 내장된 PostCSS 버전과 외부 플러그인의 버전이 맞지 않아, 제대로 사용이 불가능했던 경험이 있었습니다. 내부 설정을 마음대로 건드릴 수 없었기 때문에 발생한 문제입니다.

rollup.js

rollup.js는 2018년에 등장한 번들러로, 강력한 트리 쉐이킹을 강점으로 내세운 번들러입니다. 원래는 입력으로 ESM만 지원을 했으나, 플러그인을 통해 CommonJS도 불러올 수 있습니다. 출력은 ESM 및 CommonJS를 지원합니다.

트리 쉐이킹이 뛰어나다는 특징 때문에 라이브러리나 모듈 개발에 많이 사용합니다. 그러나 공식적으로 지원하는 HMR이 없고 watch 후 재빌드만 가능하다는 단점이 있습니다. 처리 속도가 상당히 느린 것으로 알려져 있으나, 후술할 esbuild를 사용한 플러그인으로 개선할 수 있습니다.

esbuild

esbuild는 2020년에 등장한 번들러로, 빌드 속도에 특화된 번들러입니다. 타 번들러 대비 10 ~ 100배 이상 빠른데, 비결은 Go로 개발한 네이티브 코드 컴파일러 사용과 병렬 처리 덕분이라고 합니다. 또한 최대한 다른 서드파티를 사용하지 않고 자체 개발을 지향하여, 의존성 문제를 최소화하려는 모습도 보입니다.

그러나 2022년 6월 기준으로 1.0 버전이 안나왔고 여전히 개발 중인 기능이 많아, 번들러로서 프로덕션 도입은 망설여집니다. 그럼에도 불구하고 빠른 빌드 속도는 매력적이기 때문에, 컴파일러만 떼서 다른 번들러에서 가져다 쓰는 경우가 많습니다. (ex: esbuild-loader for Webpack, rollup-plugin-esbuild for rollup)

Vite

Vite는 2020년에 등장한 번들러로, 개발 경험 개선에 특화된 번들러입니다. 원래는 vue.js에서 내부적으로 쓰던 것을 개선하여 독립을 시킨 것으로, 개발용으로는 esbuild를 프로덕션 빌드에는 rollup을 내부적으로 활용합니다.

Vite의 가장 큰 특징은 Unbundled Development 철학입니다. 기성적인 번들러들은 캐싱을 활용할지언정 번들링을 안하진 않았는데요. Vite는 개발 단계에서는 ESM을 활용하여, 번들링을 하지 않음으로서 반응 속도를 극적으로 끌어올렸습니다.

출처: https://vitejs.dev/guide/why.html#slow-server-start

JavaScript 트렌드 조사 사이트인 The State of JS의 2021년 설문 결과에 따르면, Vite는 번들러 부문 만족도 1위, 관심 1위에 등극을 한 강력한 신흥 강자입니다. 실제 사용하고 있다는 응답도 30%에 이르는데요. Vite의 단점이었던 IE 미지원 문제가 지원 종료라는 형태로 해결되어, 향후 행보가 궁금한 번들러입니다.

WMR

WMR은 2021년에 1.1.0이 출시된 번들러로, 미니멀리즘에 초점이 맞춰진 번들러입니다. WMR은 React의 방언으로 유명한 Preact 팀에서 개발하였는데요, zero-config와 가벼움을 표방하고 있습니다.

WMR은 작은 웹 어플리케이션 또는 프로토타이핑에 특화된 번들러로, 범용적인 용도로 쓰려면 플러그인 설치가 필요합니다. 특히 프레임워크를 Preact로 강제하고 있어, Preact 사용자가 아니면 접근성이 다소 떨어집니다.

WMR의 인지도는 오늘 소개한 번들러 중 가장 떨어지지만, 이런 개발 철학과 방향도 있다는 것을 소개하고 싶어 언급하였습니다.

이외에도 Snowpack이라는 Unbundled Development 철학의 번들러도 있으나, 완성도가 낮고 개발이 방치된 것으로 보여 자세히 소개하지는 않겠습니다. 시류에서 사라져가는 browserify와 gulp 역시 honorable mention 정도로만 해두겠습니다.

이처럼 프론트엔드 생태계는 변화무쌍합니다. 혹자는 이것에 대한 피로감을 호소하지만, 유행을 쫓는 것에 너무 스트레스를 받을 필요는 없을 것 같습니다. 신기술이 프로덕션에 정착하기까지는 상당히 긴 시간 동안의 검증과 개선이 필요하기 때문입니다.

그렇기에 특정 도구에 국한되지 않은, 보다 일반화된 개념을 습득하고, 시대의 흐름은 읽되 끌려가지는 않는 주도적인 자세가 필요하다고 생각합니다. 그러기 위해 우리는 JavaScript 모듈에서 시작하여, 번들러에 이르기까지 짧지만 긴 여정을 이어왔습니다.

개인 개발을 하시는 분이라면, 이번 기회에 최신 번들러를 사용해보시는 건 어떨까요. 분명 많은 것들을 배울 수 있을 것이라 생각합니다.

이전 편 읽기

(1) JavaScript 모듈
(2) TypeScript 모듈
(3) Webpack 및 다른 번들러들

--

--