6. 번들러 — 왜 묶어야 하는가
내가 쓴 코드와 브라우저가 받는 코드는 다른 물건이다
이 장에서 처음 나오는 말4개
번들러Bundler- 수백 개의 모듈 파일을 브라우저에 보내기 좋은 소수의 파일로 묶는 도구. webpack, Rollup, esbuild, Rolldown.
트랜스파일Transpile- 같은 언어 수준에서의 변환 — TS를 JS로, 최신 JS를 옛 브라우저용 JS로, JSX를 함수 호출로. 컴파일의 사촌이다.
미니파이Minify- 동작은 그대로 두고 공백·긴 변수명을 줄여 파일을 압축하는 것. 배포용 JS가 읽을 수 없게 생긴 이유다.
트리셰이킹Tree Shaking- 가져왔지만 실제로 안 쓰는 코드를 번들에서 털어내는 것. 나무를 흔들어 죽은 잎을 떨군다는 비유.
문제 설정 — 소스와 배포물의 간극
섹션 제목: “문제 설정 — 소스와 배포물의 간극”우리가 쓰는 코드는 브라우저가 바로 실행하기 어려운 것투성이다.
| 소스에 있는 것 | 브라우저의 사정 |
|---|---|
import react from 'react' | node_modules라는 개념이 없다 — 저게 어디 있는 파일인지 모른다 |
| TypeScript, JSX | 실행 못 한다 — 표준 JS가 아니다 |
| 모듈 수백~수천 개 | 하나씩 받으면 요청 수가 폭발한다 |
| 읽기 좋은 코드, 주석 | 전송량 낭비다 |
이 간극을 메우는 게 빌드이고, 그 중심 도구가 번들러다.
번들러가 하는 일
섹션 제목: “번들러가 하는 일”-
그래프 그리기 — 진입점(
main.tsx)에서 시작해import를 따라가며 의존 관계 그래프를 만든다.node_modules해석이 여기서 일어난다 -
변환 — TS는 타입을 벗기고, JSX는 함수 호출로 바꾼다 (트랜스파일)
-
묶기 — 그래프를 소수의 파일로 합친다. 페이지별로 나눠 담기도 한다(코드 스플리팅)
-
다이어트 — 안 쓰는 코드를 털고(트리셰이킹), 남은 것을 압축한다(미니파이)
pnpm build가 만들어 내는 dist/ 폴더가 이 결과물이고, 배포(12장)란 이 폴더를
어딘가에 올리는 일이다.
webpack의 시대 — 표준이 치른 대가
섹션 제목: “webpack의 시대 — 표준이 치른 대가”2015~2022년경의 사실상 표준은 webpack이었다. “모든 것은 모듈이다”라는 관점으로 JS뿐 아니라 CSS·이미지까지 그래프에 넣었고, loader와 plugin으로 무엇이든 할 수 있었다.
무엇이든 할 수 있다는 것의 대가 —
- 설정 지옥 — 프로젝트마다 수백 줄의
webpack.config.js. “webpack 설정할 줄 아는 사람”이 직무가 되던 시절이 실제로 있었다 - 속도 — JS로 짠 도구가 수천 모듈을 파싱·변환하니, 프로젝트가 크면 빌드 수 분, dev 서버 시작도 수십 초~분 단위였다
그래서 다음 세대는 두 방향으로 갈라졌다 — 설정을 없애자(프레임워크에 내장, 7장의 Vite), 그리고 더 빠른 언어로 다시 쓰자.
네이티브의 물결 — Go와 Rust로 다시 쓰기
섹션 제목: “네이티브의 물결 — Go와 Rust로 다시 쓰기”2020년 전후, JS 도구를 Go·Rust로 다시 쓰는 흐름이 시작됐다. 파싱과 변환은 CPU 집약 작업이라 네이티브 언어와 병렬화의 이득이 크게 난다. 도구와 프로젝트에 따라 차이는 크므로 특정 배수를 일반화하기보다 실제 빌드를 측정해야 한다.
| 도구 | 언어 | 무엇을 대체했나 | 지금 위치 |
|---|---|---|---|
| esbuild | Go | 번들러 + 트랜스파일러 | 이 물결의 시작. Vite 7까지 dev 변환·사전 번들 담당 |
| SWC | Rust | Babel (트랜스파일러) | Next.js 내부의 변환기 |
| Rolldown | Rust | Rollup + esbuild | Vite 8의 기본 번들러 (7장) |
| Turbopack | Rust | webpack | Next.js 전용 번들러 |
| Oxc | Rust | 파서·린터·포매터 일습 | Rolldown의 기반. oxlint(8장) |
HTTP/2 이후에도 번들이 필요한가
섹션 제목: “HTTP/2 이후에도 번들이 필요한가”“이제 요청을 여러 개 보내도 빠른데(HTTP/2 멀티플렉싱), 번들 왜 하나?”는 좋은 질문이다. 실제로 dev에서는 번들 없이 모듈을 그대로 서빙하는 게 가능해졌다 — 그게 7장 Vite의 발상이다.
하지만 배포용에서는 여전히 묶는다 —
- 모듈이 수천 개면 요청당 오버헤드가 여전히 쌓인다 (특히 의존성이 의존성을 부르는 연쇄 왕복)
- 여러 모듈을 함께 분석해야 교차 모듈 트리셰이킹과 청크 최적화를 더 적극적으로 할 수 있다
- 요청 수·압축 효율·공통 청크 캐시 사이의 균형을 잡을 수 있다
즉 “번들은 끝났다”가 아니라 “dev에선 안 묶고, 배포용은 묶는다”로 정리됐다. 이 비대칭이 다음 장의 주제다.
6장 요약
섹션 제목: “6장 요약”- 소스와 배포물 사이에는 간극이 있다 — 브라우저는 TS도, JSX도,
node_modules도 모른다 - 번들러의 네 동사 — 그래프 · 변환 · 묶기 · 다이어트. 도구가 바뀌어도 이건 안 바뀐다
- webpack은 표준의 대가로 설정 지옥과 속도를 치렀고, 다음 세대는 설정 제거(Vite)와 네이티브 재작성(Go·Rust)으로 갈라졌다
- esbuild·SWC·Rolldown·Turbopack — 로그에 나오는 이 이름들의 역할을 알아 두자
- 결론은 비대칭 — dev는 안 묶고, 배포용은 묶는다