번들러란 무엇인가? (feat. Metro, ESBuild)

홍규진·2025년 3월 7일
post-thumbnail

번들러란?

번들의 정의

구글 번역기로 돌려보면 다음과 같은 '묶음' 이라고 나온다. 즉, 이를 코딩에서는 '코드들을 묶어주는 것' 이라고 보면 된다. 당신이 짜둔 코드들을 하나로 엮어서 하나의 파일로 만들어준다. 그 과정에서 여러 기법이 들어가며, 성능 최적화를 이끌어내준다.

급한 분들을 위해 결론먼저!

  1. 번들러는 당신이 짜둔 코드들을 엮어 하나의 파일로 만들어준다.
  2. 그 과정에서 번들러에는 여러 선택지가 존재한다. 번들러에 따라 Tree Shaking, 코드 분할, 동적 임포트 등 지원하는 기능이 다르다.
  3. 개발을 위한 번들링과, 프로덕션 배포를 위한 번들링 설정을 다르게 하여, 빠른 개발 후 - 높은 성능의 배포 버전을 이끌어낼 수 있다.
  4. 번들러 내부 설정을 다르게 설정함에 따라서, 성능상의 차이를 낼 수 있다.

번들러: 코드의 마법사, 애플리케이션의 연금술사

상상해보자. 당신은 거대한 퍼즐을 완성하려 한다. 수천 개의 조각들이 무질서하게 흩어져 있다. 이 조각들을 하나하나 맞추는 것은 시간도 오래 걸리고 실수하기도 쉽다. 이때 마법사가 나타나 지팡이를 휘두르면 퍼즐 조각들이 순식간에 제자리를 찾아간다. 웹 개발 세계에서 이 마법사의 역할을 하는 것이 바로 '번들러'다.

번들러는 현대 웹과 모바일 애플리케이션 개발에 필수적이다. JavaScript 파일들, CSS, 이미지, 그리고 기타 자원들을 하나로 묶어 애플리케이션의 성능을 극대화하는 연금술사와 같은 존재다. React와 React Native 개발자들에게 번들러는 단순한 도구를 넘어 필수적인 동반자다.

이제 이 번들러에 대해 자세히 알아보자.


번들러의 정의와 역할

즉, 번들러는 JavaScript 코드, CSS, 이미지 등 다양한 자원을 하나의 파일 또는 소수의 파일로 결합하는 도구이다.

번들러의 주요 역할은 다음과 같다:

  1. 코드 최적화: 불필요한 코드를 제거하고 파일 크기를 줄여 애플리케이션의 로딩 속도를 향상시킨다. - Tree Shaking 이라고 한다.
  2. 의존성 관리: 모듈 간의 의존성을 분석하고 관리한다.
  3. 자원 변환: JSX를 JavaScript로 변환하거나, 최신 JavaScript 문법을 구버전 브라우저에서 실행 가능한 코드로 변환한다.
  4. 개발 환경 개선: 핫 리로딩(저장시 바로 반영)과 같은 기능을 제공하여 개발자 경험을 향상시킨다.

Before React

과거 React라는 라이브러리가 없던 시절의 번들링은 지금과는 많이 달랐다.

웹 개발자들은 마치 퍼즐 조각을 하나하나 맞추듯이 수작업으로 파일들을 관리해야 했다. HTML내에 JavaScript, CSS, 이미지 등 모든 자원을 수동으로 연결하고 최적화하는 과정은 매우 복잡하고 시간이 많이 소요되는 작업이었다.

예를 들어, 간단한 CRUD 애플리케이션을 만들 때도 여러 개의 JavaScript 파일로 기능을 분리하고 이를 HTML에 순서대로 로드해야 했다. 이는 다음과 같은 문제를 야기했다:

  1. 파일 의존성 관리의 어려움
  2. 여러 HTTP 요청으로 인한 성능 저하
  3. 코드 최적화와 압축의 어려움
  4. 브라우저 호환성 문제

또한 서드파티 라이브러리를 사용할 때마다, 별도의 <script> 태그를 추가해야 했고, 이는 페이지 로딩 시 여러 번의 요청을 발생시켰다.

이러한 문제를 해결하기 위해 초기의 번들러들이 등장했다. Browserify와 같은 도구가 Node.js의 require 함수를 브라우저에서 사용할 수 있게 해주어 모듈화된 개발을 가능하게 했다. 이는 서버와 클라이언트 간 코드 공유를 용이하게 만들었다.


Browserify 의 사이트 모습. 어느새 당연해진 require() 등의 모듈로 나눠둔 파일을 가져오는 것이 당연해진 현재완 달리, 과거에는 이런 번들러를 사용해만 했다.

그러나 이러한 초기 번들러들은 현대의 Webpack, Rollup, Vite, ESBuild,Parcel 등과 비교하면 기능이 제한적이었고, 추후에 설명할 현대의 번들러에서는 코드 분할, 트리 쉐이킹, 동적 임포트 등의 기능은 그 이후에서 발전되었다.

결론적으로, React 이전의 번들링은 현재와 비교하면 매우 원시적이고 수동적인 과정이었다. 현대의 번들러들이 제공하는 자동화와 최적화 기능은 당시 개발자들의 꿈과도 같은 것이었다고 할 수 있다.


번들러의 장단점

장점

  1. 성능 최적화: 코드를 최소화하고 압축하여 애플리케이션의 로딩 속도를 향상시킨다. (리엑트는 CSR - Client Side Rendering 으로 이루어진다. 즉, 클라이언트가 이를 랜더링 해야하기에, 이 번들러를 잘 다룰 수 있는 것이 성능상의 차이점을 낼 수 있게 되는 것이다.)
  2. 모듈화: 코드를 모듈 단위로 관리할 수 있어 재사용성과 유지보수성이 향상된다.
  3. 자원 관리: 다양한 유형의 자원을 효율적으로 관리하고 처리할 수 있다.
  4. 크로스 브라우저 호환성: 최신 문법을 사용하면서도 구버전 브라우저에서 실행 가능한 코드를 생성한다.

단점

  1. 설정 복잡성: 번들러의 설정이 복잡할 수 있어 초보자에게는 진입 장벽이 될 수 있다. (Vite 최고!!)
  2. 빌드 시간: 프로젝트 규모가 커질수록, 하나로 묶는 과정에서의 빌드 시간이 길어질 수 있다. 이 때, 번들러의 설정이나, 번들러 자체에 대해서의 고민이 필수적으로 선행되어야 한다.
  3. 추가적인 의존성: 번들러 자체가 프로젝트 내에서의 추가적인 의존성으로 작용하며, 최근에는 번들러의 경계가 모호해질만큼 복합적인 툴이 많이 생겨났기에, 이에 유의하여 각 툴의 역할들 간의 충돌을 방지하려면, 각 툴이 어디까지 기능을 지원하고, 그 경계선에 대한 정확한 이해가 필수적이다.

개발을 위한 번들링, 프로덕션를 위한 번들링

번들러는 개발 및 프로덕션 빌드 과정에서 각각 다른 역할을 수행한다. 선물을 포장하는 마지막 단계에서나 이쁘게 틀을 잡기만 하면 되지, 선물을 고르고 담는(개발을 하는) 과정에서부터 너무 이쁘게 하려고 하면(번들링을 통해 성능 최적화를 매 순간 신경쓴다면) 개발 경험이 떨어지게 된다.

ESBuild는 개발 환경과 프로덕션 빌드 환경에서 명확히 다른 역할을 수행한다.

개발 환경에서의 ESBuild 역할

  1. 속도: ESBuild는 Go 언어 기반으로 설계되어 번들링 속도가 압도적이다. 코드 변경 시 즉각적인 결과를 제공하며, 개발 중 빠른 피드백을 보장한다.
  2. 의존성 처리: 외부 라이브러리를 사전 번들링하여 브라우저가 효율적으로 로드할 수 있도록 한다. 이는 개발 중 효율성을 극대화한다.
  3. 최적화 없음: 개발 환경에서는 최적화를 최소화하여 디버깅과 테스트에 초점을 맞춘다. 이 단계에서 번들 파일은 크기나 성능보다는 실시간 피드백이 중요하다.

프로덕션 빌드 환경에서의 ESBuild 역할

  1. 코드 압축: ESBuild는 프로덕션 빌드 시 코드 압축(Minification)을 수행하여 파일 크기를 줄이고 배포 속도를 개선한다.
  2. 트리 쉐이킹: 사용되지 않는 코드를 제거하여 번들 크기를 최소화한다. 이는 성능 최적화를 위한 필수 작업이다.
  3. 제한된 유연성: ESBuild는 기본적인 최적화를 제공하지만, Webpack과 Rollup처럼 고급 플러그인 생태계를 활용한 세밀한 최적화는 부족하다.

개발 환경과 프로덕션 빌드 환경의 차이점

특징개발 환경프로덕션 빌드
목적실시간 피드백 제공최적화된 코드 생성 및 배포
빌드 속도매우 빠름상대적으로 느림
코드 최적화일부 적용코드 압축 및 트리 쉐이킹 적용
결과물디버깅용 번들(개발 전용)배포용 최적화된 번들로 번들링은 오래 걸리지만, 결과물은 빠르다!

ESBuild는 개발 환경에서 최고의 속도를 제공하며, 간단한 프로젝트에 적합하다. 그러나 프로덕션 빌드에서는 고급 최적화가 필요한 경우 Webpack이나 Rollup을 고려해야 한다. ESBuild는 빠른 번들링과 기본적인 최적화를 원할 때 사용하는 도구다.


Metro 번들러와 ESBuild 번들러의 차이점

매트로 번들러

개발하려는 목적과, 결과물(웹 / 앱)에 따라서 환경이 달라지면서 자연스레 번들러 또한 다양하다. React 개발을 위한 번들러, React Native를 위한 번들러가 달라지는 것도 당연한 것이다.

  1. 설계 목적: Metro는 React Native를 위해 특별히 설계되었으며, ESModule 번들러는 웹 브라우저의 네이티브 모듈 시스템을 활용한다. 따라서 React로 웹 개발 시에는 ESBuild을, React Native로 앱 개발 시에는 Metro 번들러를 사용한다. (그러나, 최근 토스에서는 Metro 번들러를 ESBuild 로 대체하며 성능 상의 이점을 가져가는 등 꼭 제한된 것은 아니다.)
  1. 성능 최적화: Metro는 React Native의 특성에 맞춰 최적화되어 있어 네이티브 앱 개발에 더 적합하다. ESModule 번들러는 브라우저의 기능을 활용하여 개발 시 더 빠른 리로드를 제공할 수 있다.

  2. 구성의 유연성: Metro는 성능을 위해 구성의 유연성을 일부 희생한 반면, ESModule 번들러는 더 많은 사용자 정의 옵션을 제공한다.

  3. 호환성: Metro는 React Native 프로젝트와 완벽하게 호환되며, ESModule 번들러는 주로 웹 프로젝트에 사용된다.

  4. 개발 환경: Metro는 네이티브 파일 감시 기능과 원격 캐시 공유 등 대규모 프로젝트에 최적화된 기능을 제공한다.


현대의 번들러


막대 그래프 : 각 프로젝트의 빌드 시간
녹색 선 그래프 : 깃허브 스타의 수

현대 웹 번들러 비교 (2025)

번들러빌드 시간(초)인기도(k stars)특징
Webpack5.265.0- 성숙한 생태계와 광범위한 플러그인 + 높은 유연성과 구성 가능성- 복잡한 구성이 필요하고 학습 곡선이 가파름 (높은 자유도를 가지는 만큼 잘 쓰면 정말 좋습니다.)
Vite0.3565.3- ESBuild 기반 온디맨드 번들링- 빠른 개발 서버 시작 시간- 즉각적인 HMR(Hot Module Replacement)
Parcel2.043.2- 설정이 전혀 필요없는 방식- 자동 코드 분할- 멀티코어 처리로 빠른 빌드
Esbuild0.137.4- Go 언어로 작성되어 매우 빠른 속도- 최소한의 구성- 트리 쉐이킹 및 축소화 내장

이 때의 빌드 시간은 개발 환경에서의 첫 빌드 시간(Dev first build) 입니다.
출처 : https://kinsta.com/blog/vite-vs-webpack/

주요 결론

  • 빌드 속도: Esbuild > Vite > Parcel > Webpack
  • 인기도: Vite > Webpack > Parcel > Esbuild
  • Vite는 빠른 빌드 속도와 높은 인기도를 모두 갖춘 균형 잡힌 선택
  • Webpack은 여전히 복잡한 프로젝트에 적합하지만 빌드 속도가 느림
  • Esbuild는 가장 빠르고 기반이 되는 기술

결론

번들러는 현대 웹 및 모바일 애플리케이션 개발에서 필수적인 도구이다. React와 React Native 개발에서는 각각, ESBuild 및 Metro가 기본 번들러로 사용되며, 이는 빌드 당시 최종적인 하나의 파일로 제공하기 위한 도구이다. 최근에는 보다 더 발전하여, 개발 경험,성능,최적화 등에 중점을 두고 여러 기능을 수행하기도 한다. 그 과정에서 여러 선택지가 있으니, 잘 선택해야만 한다.

profile
블로그 이사했어요! kyu-log.com

0개의 댓글