C.W.K.
Stream
Lesson 02 of 05 · published

esbuild 와 swc — JavaScript 아닌 JavaScript 도구

~11 min · tooling, esbuild, swc, transpilation

Level 0노드 입문자
0 XP0/40 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"제일 빠른 JavaScript 빌드 도구가 Go 와 Rust 로 쓰임. Node 에서 돌리지만, Node 아냐. 그 구분이 왜 빠른지 + 어디서 끝나는지 둘 다 설명."

속도 스토리

10 년 동안 JavaScript tooling 이 JavaScript 로 쓰였어. Babel 이 JS 로 JS transpile. webpack 이 JS 로 JS 번들. 예측 가능한 성능: 작은 프로젝트엔 중간-빠름, 큰 거엔 고통스럽게 느림. 근본 제약은 Node 의 single-threaded 실행 — Node 에서 도는 transpiler 가 코어 하나만 쓸 수 있어, 머신에 코어 몇 개든.

esbuild (Evan Wallace, 2020) 가 번들러를 Go 로 재작성. swc (Donny Wang, 2019) 가 transpiler 를 Rust 로 재작성. 둘 다 AOT 컴파일 언어, 멀티스레드, JavaScript 의 세금 안 냄. 결과: JS 기반 전임자들보다 10-100x 빠름. Vite, Bun, Next.js, Deno 컴파일러 다 이제 밑에 둘 중 하나 씀.

esbuild — Go 의 번들러 + Transpiler

esbuild 가 둘 다 함:

  • Transpile — TS/JSX → JS, ES2022 → ES2017 등. 파일당 빠름.
  • Bundle — import walk, concatenate, tree-shake, minify. 프로젝트 전체 빠름.

npm 패키지 통해 Node 에서 invoke, 근데 무거운 일은 node_modules 에 출하된 Go 바이너리에서 일어남. Node 쪽 코드가 얇은 RPC wrapper. 빠른 성능이 "esbuild 의 JavaScript 코드가 잘 최적화됨" 아냐 — "esbuild 가 Node 가 driving 하는 Go 프로그램" 이야.

swc — Rust 의 Transpiler

swc 는 transpiler 반: TS/JSX → JS, JSX-to-React-create-element 등. Next.js 가 TypeScript 컴파일에 swc 씀. Deno 가 toolchain 일부로 썼었음. esbuild 가 번들링과 transpilation 둘 다 하는 데 비해 swc 는 transpile 반에 집중 — 그리고 보통 available 한 제일 빠른 TS-to-JS transformer.

compose 가능: transpilation 엔 swc, 번들링엔 esbuild. Vite 가 대략 이렇게 함, 위에 자기 TypeScript bit 더해서.

속도 안 중요한 곳

2026 교훈: 잘못된 레이어의 속도는 낭비. --experimental-strip-types 통해 소스 직접 실행하는 Node 서비스면, esbuild/swc 속도 안 중요 — 빌드 단계 자체 건너뛰었어. 100x 속도 향상이 안 돌리는 단계 위에 있어.

속도 win 사는 곳:
  • Frontend 빌드 (Vite 가 내부적으로 esbuild 씀 — 네 `vite build` 가 분 아닌 초에 끝남).
  • CLI 배포 번들 (esbuild 가 Node 가 자기 README 읽는 것보다 빨리 단일 파일 CLI 생성).
  • FaaS 배포 번들 (Lambda 함수가 더 작아지고 cold-start 더 빠름).
  • TypeScript 자체 컴파일러가 너무 느린 큰 monorepo 컴파일.
2026 의 빌드 안 필요한 백엔드 Node 서비스엔, 배포 타겟이 번들된 출력 요구할 때만 esbuild 설치. 그 외엔 의존성 절약.

플러그인 비용

esbuild 와 swc 는 *빠름*. 플러그인은 *느림*, 특히 변환마다 Go/Rust 바이너리로 callback 해야 하는 JavaScript 로 쓰인 것들. 흔한 anti-pattern: 속도 위해 esbuild 설치, 그 다음 webpack-시대 성능으로 되돌리는 10 개 JavaScript-side 플러그인 레이어. esbuild 와 빌드 느리면 플러그인 먼저 의심.

Pippa 의 고백

내 첫 Vite 프로젝트가 마법 같았어 — webpack 이 90 초 걸리던 거에서 vite build 가 2 초에 끝남. "Vite 가 빠르네" 라고 credit. 아빠가 밀어붙임: "node_modules/vite/dist/node 봐서 Go 바이너리 찾아." 거기 있었어 — esbuild 가 자기 플랫폼별 바이너리 출하; Vite 가 driving. Vite-as-Node-code 가 coordination 레이어; esbuild-as-Go-binary 가 실제 일. 프레이밍 shift 가 중요했어: Vite 플러그인 슬로다운 칠 때 "이 플러그인이 불필요하게 JS 로 callback 하나?" 봐야 한다는 거 알았고 — 보통 그랬어.

Code

직접 CLI 사용 — esbuild 와 swc·bash
# esbuild — direct CLI usage
npx esbuild src/cli.ts \
  --bundle \
  --platform=node \
  --target=node22 \
  --format=esm \
  --outdir=dist \
  --packages=external

# Result: dist/cli.mjs in seconds, deps stay in node_modules

# esbuild --watch for dev-time bundling
npx esbuild src/index.ts --watch --bundle --outdir=dist

# swc — transpile-only, no bundling
npx swc src --out-dir dist --strip-leading-paths
# Output: dist/*.js mirroring src/*.ts structure
빌드 스크립트에서 programmatic esbuild·javascript
// esbuild's Node API for build scripts
import { build, context } from 'esbuild';

// One-off build
await build({
  entryPoints: ['src/index.ts'],
  bundle: true,
  platform: 'node',
  target: 'node22',
  format: 'esm',
  outfile: 'dist/index.mjs',
  packages: 'external',
});

// Watch mode (for dev)
const ctx = await context({
  entryPoints: ['src/index.ts'],
  bundle: true,
  platform: 'node',
  format: 'esm',
  outfile: 'dist/index.mjs',
});
await ctx.watch();    // rebuilds on change, ~50ms per rebuild

External links

Exercise

어느 크기든 TypeScript 프로젝트 골라. Transpile-and-bundle path 셋 벤치마크: (a) tsc 단독 (순수 TypeScript 컴파일러), (b) esbuild --bundle, (c) npx tsx 로 소스 직접 실행. 각각 wall-clock 시간과 결과 node_modules 크기 기록. 숫자가 왜 frontend tooling 이 Go/Rust 로 옮겨갔는지 말해줄 거 — 그리고 백엔드가 이걸 필요로 하는지에 대해 놀랄 수 있어.
Hint
(a): time npx tsc -p tsconfig.json — TypeScript 가 순수 JS 로 도, 진짜 프로젝트엔 보통 30-60 초. (b): time npx esbuild ... --bundle — 같은 프로젝트에 우리 경험상 1 초 미만. (c): type-check-and-run 케이스엔 time npx tsx --type-check src/index.ts. 차이가 2x 가 아냐; 30-100x.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.