번들러 비교를 통한 빌드 최적화

2022.06.07

1. 들어가며 

많은 JS 프로젝트에서는 모듈화를 위해 Webpack, Browserify, Rollup, Parcel 등 다양한 번들러를 활용하고 있습니다. 하지만 대부분의 프로젝트는 해당 번들러의 사용 이유를 분명히 하지 않으면서 번들러 설정을 구성하는 상황이 많이 발생하고 있습니다. 라인웍스 프론트엔드 그룹 내에서도 뚜렷한 목적성 없이 기존 번들러 설정을 재사용하고 있다는 문제가 발생하고 있었고, 이 문제를 개선하기 위해 번들러들 간의 비교를 통해 번들러의 사용 목적을 정리하고, 더 나아가 빌드 과정을 최적화하고자 노력하였습니다.

이 글에서는 번들러를 사용하면서 동일한 고민을 가지고 있는 JS 개발자 분들에게 저희 그룹 내에서 사용할 번들러를 선정함에 있어서 고려한 부분과 비교한 자료들을 공유하고자 합니다. 아래 내용은 JS 파일의 세부 빌드 과정, 번들러의 사용 목적 및 설정 방법, swc 에 대한 사전 지식을 가지고 계시다면 보다 편안하게 이해하실 수 있습니다.

2. JS 빌드 과정

번들러에 대해 이해하기 위해서는 JS 파일이 빌드될 때 진행되는 트랜스파일, 번들링, 압축 과정에 대해 간단히 이해할 필요가 있습니다. 

그림 1. JS 파일 빌드 과정

1) 트랜스파일(Transpiling) 

프론트엔드에서 사용하는 JS 파일은 대부분 ES6나 JSX 등을 활용할 수 있는 최신 고급 문법을 사용하여 구성됩니다. 이러한 문법은 JS 의 다양한 기능을 활용할 수 있다는 장점이 있지만, 구형 브라우저들이 고급 JS 문법을 이해하지 못한다는 호환성 문제가 존재합니다. 이 문제를 해결하기 위해 트랜스파일이라는 기법을 적용하게 되었습니다. 

트랜스파일은 하나의 프로그래밍 언어로 작성된 파일을 아예 다른 프로그래밍 언어가 아닌, 비슷한 수준의 언어로 변환하는 기법입니다. JS 의 트랜스파일은 최신 버전의 JS 코드를 구형 버전의 JS 코드로 변환하기 위해 활용하고 있습니다.

2) 번들링(Bundling)

트랜스파일된 JS 코드를 통해 구형 브라우저에 대응할 수 있게 되었지만, 각각의 JS 파일을 사용하기 위해 파일을 불러오는 순서를 고려하면서 무수히 많은 스크립트 태그를 추가해야하는 등의 문제가 발생하게 되었습니다. 이 문제를 해결하기 위해 수많은 JS 파일과 모듈을 하나의 파일로 묶는 번들링 기법이 등장하게 되었습니다. 

3) 압축(Minifying)

번들링 기법을 통해 하나의 JS 파일을 관리할 수 있게 된 것은 좋지만, 수많은 파일들을 하나의 파일에 담은 만큼 파일 용량이 커질 수 밖에 없었습니다. 이렇게 커진 파일 용량은 JS 파일을 브라우저 상으로 로드하는 시간이 늘어나는 문제로까지 이어지게 되었습니다. 이러한 문제는 번들 파일에 압축(Minifying) 기법을 적용하면서 자연스럽게 해결되었고, 파일 용량과 로드 시간을 최적화한 JS 빌드 파일을 생성할 수 있게 되었습니다.

3. 번들러 특징 비교

위에서 설명한 빌드 과정을 살펴보기 위해 JS 파일을 번들링할 때 자주 사용되는 Webpack, Rollup, Parcel 번들러를 비교하기로 결정하였습니다. 추가적으로 트랜스파일과 압축 과정을 최적화하기 위해 SWC 라이브러리를 적용한 상황도 함께 비교하고자 하였습니다. 각각의 라이브러리들은 다음과 같은 핵심적인 특징을 내세우고 있습니다.

  • Webpack 
    • 오랫동안 사용되어 개발 레퍼런스가 다양해 가장 안정적인 번들러
    • 로더를 통해 JS 모듈과 JS 이외의 모듈들을 통합
    • 많은 서드파티를 필요로 하는 복잡한 애플리케이션에 주로 활용
  • Rollup
    • ES6 모듈 형식으로 빌드 결과물을 생성할 수 있는 번들러
    • 진입점을 다르게 설정하여 번들링 가능
    • 최소한의 서드파티로 라이브러리를 만들기 위해 주로 활용
  • Parcel
    • 설정이 필요없는 번들러
    • 캐싱을 사용하여 빌드 속도가 빠름
    • 복잡한 설정을 피하고 간단한 애플리케이션을 빠르게 만들고 싶을 때 주로 활용
  • SWC
    • Rust 로 구성된 최신 JS 트랜스파일러
    • JS 트랜스파일링, 코드 압축 과정을 최적화하여, 우수한 성능을 보임

4. 번들링 결과 비교

위에서 살펴본 번들러들의 특징과 함께 번들링 결과물을 살펴보기 위해 사내 디자인 시스템 라이브러리를 기준으로 번들링 설정을 진행하였습니다. 저희의 디자인 라이브러리는 번들링을 위해 다음 기준을 만족해야합니다.

  • Multi Entry Point 지정 
  • Global CSS 지원
  • TypeScript + React 환경
  • ESM 모듈을 통한 TreeShaking 적용

해당 기준에서 각 번들러 설정을 구성하였을 때 각각의 빌드 용량과 빌드 시간은 다음과 같았습니다. 

빌드 테스트 환경

하드웨어

  • OS: MacOS
  • CPU : Apple M1
  • Memory : 16GB

소프트웨어

  • NodeJS : v14.18.1
  • webpack :  v5.72.0 
  • swc-loader : v0.2.0
  • terser-webpack-plugin: v5.3.1 (swcMinify 적용)
  • rollup : v2.34.2
  • rollup-plugin-swc : v0.2.1 
  • parcel-bundler : v1.12.5

빌드 결과 (Production)

  • Webpack
그림 2. Webpack 빌드 결과
  • Webpack + swc
그림 3. Webpack + swc 빌드 결과
  • Rollup
그림 4. Rollup 빌드 결과
  • Rollup + swc
그림 5. Rollup + swc 빌드 결과
  • Parcel
그림 6. Parcel 빌드 결과
번들러빌드 용량 (MB)빌드 시간 (s)
Webpack6.116.66
Webpack + swc6.013.88
Rollup6.114.88
Rollup + swc6.211.63
Parcel6.46.66
표 1. 번들러 빌드 결과

5. 정리하

번들러 간의 비교를 정리하면서  프론트엔드 그룹 내에서는 빌드를 위해 Webpack 과 SWC 조합을 활용하기로 결정하였습니다. 우수한 빌드 결과를 보여 주고 있고, 빌드 결과 이외에도 아래와 같은 장점이 있다고 생각했기 때문입니다.

  • Webpack 의 광범위한 개발 레퍼런스를 활용할 수 있다.
  • Webpack 의 다양한 플러그인을 활용할 수 있다.
  • ESM 모듈에 대한 TreeShaking을 지원한다.
  • SWC 를 통해 JS 트랜스파일 및 압축 과정을 최적화 할 수 있다.
  • NextJS v12 부터 SWC 가 정식으로 도입된만큼, 장기적으로 Webpack 과 SWC 의 조합은 NextJS를 사용하는 프로젝트에서 최적의 조합이 될 수 있다.

이번 번들러 비교는 번들러의 사용 목적을 정리하고, 앞으로의 빌드 방향성을 결정하는 좋은 시간이 되었습니다. 앞으로도 프론트엔드 그룹은 사용하고 있는 기술 스택의 목적성과 방향성을 결정하기 위해 지속적으로 기술적 비교를 해 나갈 것입니다. 

긴 글 읽어주셔서 감사합니다.

참고자료