웹 개발, 특히 프론트엔드 개발을 하다보면 빌드 도구와 번들러에 대해 듣곤 합니다.
오늘은 그 중에서도 빌드 도구와 번들러에 대해 알아보겠습니다.
빌드 도구란?
빌드 도구는 단순히 파일을 합치는 번들링 외에도, 코드의 변환(트랜스파일링), 압축, 테스트, 핫 리로딩 등을 지원하는 더 넓은 범주의 도구입니다. 빌드 도구는 번들링뿐만 아니라 다양한 개발 및 배포 관련 작업을 자동화합니다.
번들러란?
번들러는 여러 개의 소스 파일(자바스크립트, CSS, 이미지 등)을 하나 또는 여러 개의 파일로 합쳐서 브라우저에서 더 빠르게 로드할 수 있도록 해주는 도구입니다. 번들러는 코드의 종속성을 분석하고 최종 배포를 위한 파일 크기를 줄이는 데 중점을 둡니다.
결국 번들러 ⊂ 빌드도구 라고 이해하면 되겠네요.
빌드 도구들은 기본적으로 빌드 과정을 위한 번들러를 내장하고 있지만, 번들러 그 자체는 빌드도구가 아닐 수 있습니다.
그런데 번들러가 도대체 왜 필요할까요? 그냥 JS 파일을 전부 <script> 태그로 개별적으로 로딩해오면 안되는걸까요?
사실 아주 작은 프로젝트의 경우 번들러까지 필요없을 수 있습니다. 하지만 조금만 HTML, JS, CSS 파일이 늘어나고, 서로 종속적으로 영향을 주고 받게 된다면.. 심각한 문제가 발생해요.
번들러가 필요한 이유
1. 파일 로드 성능 문제 개선
- 웹 페이지에서 각 JavaScript 파일을 <script> 태그로 개별 로드할 경우, 브라우저는 매번 네트워크 요청을 보내서 파일을 받아오게 됩니다. 파일이 많아질수록 이 요청들이 병목 현상을 일으킬 수 있어 페이지 로딩 시간이 느려지게 될겁니다.
- 하지만 번들러의 경우, 여러 개의 JavaScript 파일을 하나의 번들로 합치기 때문에 브라우저가 한 번만 요청해서 필요한 모든 스크립트를 받아올 수 있고, 이는 네트워크 요청 수를 줄이는데 기여할 수 있습니다.
2. 변수 충돌 문제 해결 + 종속성 관리
- 기본적으로 하나의 HTML 파일에 <script> 태그로 JS 파일을 여러개 불러온다고 생각해봅시다. 그럼 각 JS 스크립트 내부에서 정의해둔 변수명이 충돌하는 문제가 발생합니다. 예를 들어, 1.js에서 title이라는 변수를 선언해서 사용하고 있고 2.js에서도 title이라는 변수를 선언해서 사용하고 있었다면, 2개의 스크립트 파일에서 같은 이름의 변수를 사용하기에 충돌이 나게 됩니다.
- 하지만, 번들러를 사용한다면 import, require와 같은 키워드로 스크립트 파일들을 가져올 수 있게 되고,
import / require 와 같은 키워드로 가져온 파일들은 각각 모듈(module)로 인식되어, 각각의 모듈 내부(js 파일 내부)에서 지역 변수로 인식됩니다. 즉, 충돌 문제를 해결할 수 있습니다. - 또한, 가져오는 파일의 순서를 일일히 신경 쓰지 않아도 됩니다.
즉, 알아서 필요한 순서대로 파일들이 로딩되도록 만들어줍니다. (ex main.js -> section.js -> article.js 순서)
3. Transpiling 제공 -> 호환성 문제 해결
- 단순히 js 파일로만 개발하지 않죠?
jsx 와 같은 리액트를 위한 확장 언어부터, 타입을 체크하기 위한 타입스크립트(ts), tsx ...
그러나 브라우저에서는 오직 js만 인식할 수 있습니다. 그래서 이 확장 언어들을 js로 변환하는 과정이 필요합니다. 이를 트랜스파일링(Transpiling)이라고 하는데, 번들러는 이를 내부적으로 제공합니다. - 물론 번들러 내부에 있는 트랜스파일 도구를 사용하는겁니다! 가장 유명한 건 속도 빠른 SWC가 있겠네요.
4. 코드 최적화 제공
- Minification : 불필요한 코드를 제거하거나 압축합니다.
즉, 주석, 공백을 제거하고, 변수 이름을 짧게 만들어 파일 크기를 줄입니다. - Tree Shaking : 실제로 사용되지 않는 코드를 번들에서 제거합니다. 예를 들어 라이브러리에서 일부 기능만 사용하는 경우, 사용하지 않는 나머지 코드들을 삭제해서 최종 파일 크기를 줄입니다.
5. 개발 편의성 제공
- 핫 리로딩(Hot Reloading): 코드 변경 시마다 브라우저를 새로고침하지 않고도 실시간으로 변경 사항을 확인할 수 있게 만들어줍니다. Vite를 사용하거나 CRA를 사용하여 개발할 때, Ctrl + S만 해도 변경사항이 반영되는 걸 본 적 있으시죠?
- 코드 스플리팅 : 번들링된 파일이라고 해서 한번에 오는 것이 아니라, chunk 단위로 나누어서 받아옵니다. 이를 통해 초기 렌더링 속도를 높일 수 있습니다. 만약 spliting을 안한다면.. 전부 렌더링될 때까지 빈 화면을 보고 있어야 했을겁니다.
번들링 프로세스에 대해 이해하기

번들링 프로세스는 크게 2가지로 나눌 수 있습니다.
1. Mapping a Dependency Graph
2. Bundling
1번 과정은 의존성이 있는 파일들끼리 묶는 과정이라고 생각하면 되고,
2번 과정은 하나의 번들링된 파일로 만드는 과정이라고 생각하시면 됩니다.

1. Mapping a Dependency Graph (의존성 그래프 만들기)

app.js 파일을 예시로 들겠습니다. 해당 파일에서는 두개의 파일을 필요로 하네요. (logging, utils) 그럼 해당 파일은 추후 하나의 번들로 묶여야할 겁니다. 그러나 그림을 보면 상대 경로로 파일들을 불러오고 있습니다. 그러나 번들링된 상황에서, 상대 경로를 인식하기는 쉽지 않은데요. 이럴 떄 나온 해답이 바로 module map 입니다.

아까 위에서 정보 객체가 있었습니다. 해당 정보 객체에는 파 일의 이름과 식별자, 파일의 경로, 파일의 코드, 파일의 의존성 정보가 담겨있었는데요, 이 정보를 바탕으로 엔트리 파일 중심의 관계성 맵(Module Map)을 그리게 됩니다.
그리고 해당 맵의 각 파일에 고유한 ID를 부여하여 추후 종속성 탐색에 사용합니다.
참고) 의존성 그래프는 왜 필요할까요?
의존성 그래프를 생성하는 과정이 필요한 이유는 아래와 같습니다.
1. 모듈이 의존성 순서를 구성할 수 있게 해주고, 브라우저의 요청을 받았을 때 관련된 함수를 검색하여 반환하는데 필수적이기 때문입니다.
2. 이름이 중복되어서 충돌나는 것을 막아줍니다.번들러가 모든 파일의 의존성에 대한 소스맵을 가지고 있기 때문입니다.
3. 사용하지 않는 불필요한 파일을 인식하고 제거 할 수 있습니다.
2. Bundling (번들링 - 매핑되어 있는 파일들을 하나의 파일로 만들기)

이렇게 하나의 실행 가능한 파일로 만드는 과정을, output이 나오는 과정을 Packing이라고 합니다. (번들링이라고도 합니다.) 이렇게 총 번들링의 과정을 마치게 됩니다.
빌드 과정에 번들링 과정이 포함된다는 것은 잊지 마세요! 트랜스파일링, 압축등의 과정은 번들링과는 다릅니다.
빌드 도구 예시 (Vite)

Vite는 정말 유명한 빌드 도구죠! 내부적으로는 Rollup 이라는 번들러를 사용하고 있습니다.
번들러 예시 ( ESBuild, Webpack, PARCEL, Rollup )




차례대로 ESBuild, Webpack, PARCEL, Rollup 이라는 번들러입니다.
사실 ESBuild, Webpack은 번들러이지만 그 자체로 빌드 도구라고 평가되기도 합니다. 빌드에 필요한 작업들을 많이 진행해주거든요.
각 빌드 도구와 번들러의 특징(장,단점)은 나중에 다루겠습니다.
지금까지 빌드 도구와 번들러의 기본 개념, 그리고 번들링 프로세스에 대해 자세히 알아보았습니다.
다음에는 기회가 된다면, 각각의 번들러 초기 설정을 하는 과정을 통해 더욱 깊게 알아보는 시간을 갖겠습니다.
긴 글 읽어주셔서 감사합니다 !
출처: https://ocahs.tistory.com/2 [ocahs 개발 블로그:티스토리]
'1주차' 카테고리의 다른 글
[HTML] 간편하게 아이콘 불러오기 : Font Awesome (0) | 2024.10.11 |
---|---|
[ CSS ] CSS 방법론 (0) | 2024.10.11 |
웹 접근성을 고려하는 법 (0) | 2024.10.11 |
[CSS] object-fit 과 object-position 속성으로 깔끔하게 사진과 싸움 끝! (0) | 2024.10.11 |
CSS 애니메이션 및 전환 (1) | 2024.10.11 |