번들러부터 린터까지, 전부 Rust로 갈아타는 중입니다
요즘 프론트엔드 쪽 뉴스 보면 느끼실 텐데, 빌드 도구 판이 완전히 뒤집어지고 있어요. 번들러, 린터, 트랜스파일러, 미니파이어—우리가 매일 쓰는 도구들이 하나씩 Rust로 갈아타고 있거든요.
"좀 빠르다" 수준이 아닙니다. 10배에서 100배.
Rolldown이 1.0 RC를 찍었고, Vite 8 베타에 기본 번들러로 올라갔어요. Oxlint는 ESLint 대비 50~100배 빠르고요. Rspack 2.0 프리뷰도 이번 달 나옵니다.
아직 Webpack 돌리고 계신 분들, 슬슬 진지하게 고민할 때예요.
근데 왜 하필 Rust?
JS로 만든 빌드 도구가 느린 건 당연합니다
생각해보면요. JavaScript는 브라우저에서 돌리려고 만든 언어잖아요. 그걸로 CPU 때려박는 컴파일 작업을 하고 있으니 느린 게 당연하죠.
npm run build 한 번 돌리면 내부에서 일어나는 일:
- Babel이 코드를 AST로 파싱 → 변환 → 직렬화
- ESLint가 같은 코드를 또 파싱 → 규칙 검사
- Webpack/Rollup이 또또 파싱 → 모듈 해석 → 번들링
- Terser가 결과물을 또또또 파싱 → 압축
같은 코드를 네 번 넘게 파싱하는 거예요. 각자 다른 AST 포맷으로, 전부 싱글 스레드로, GC 멈춤 먹으면서. 이게 정상일 리가 없잖아요.
Rust는 이 문제를 언어 차원에서 해결해요
| 문제 | JavaScript | Rust |
|---|---|---|
| 속도 | JIT 컴파일, V8 오버헤드 | 네이티브 바이너리, 제로 코스트 추상화 |
| 메모리 | GC가 언제 멈출지 모름 | 소유권 모델로 GC 자체가 없음 |
| 병렬 처리 | Worker thread 써도 직렬화 비용 | 진짜 멀티스레딩 |
| 파싱 | 도구마다 AST 따로 만듦 | AST 하나로 전부 공유 |
결과: 빌드 30초 → 2초. 린팅 10초 → 0.1초. 뻥 아니고 실측값이에요.
지금 누가 뭘 만들고 있나
┌─────────────────────────────────────────────────────────────┐
│ VoidZero (Evan You) │
│ Rust 기반 통합 JS 툴체인 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Vite │ │ Rolldown │ │ Oxc │ │ Vitest │ │
│ │ 개발 서버 │ │ 번들러 │ │ 파서/린터 │ │ 테스트 러너 │ │
│ │ │ │ │ │ 미니파이어│ │ │ │
│ └──────────┘ └──────────┘ └──────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌──────────────────────┐ ┌──────────────────────┐
│ Rspack (ByteDance) │ │ Biome (커뮤니티) │
│ Webpack 호환 번들러 │ │ 포매터 + 린터 │
└──────────────────────┘ └──────────────────────┘
이 흐름의 중심에 있는 건 VoidZero예요. Vue.js랑 Vite 만든 Evan You가 세운 회사인데, 아이디어가 심플합니다. "왜 도구마다 코드를 따로 파싱해? 한 번만 하면 되잖아."
Rolldown — Vite의 번들러가 드디어 하나로 통일됩니다
뭔데요
Rolldown은 Vite에서 esbuild(개발)와 Rollup(프로덕션)을 통째로 대체하는 Rust 번들러예요. 올해 1월에 1.0 RC 나왔고, API 안정화 됐습니다.
이게 왜 큰 건지
Vite 쓰시는 분들 아실 텐데, 지금까지 개발 서버는 esbuild, 프로덕션 빌드는 Rollup이었거든요. 이게 은근히 골치 아팠죠:
- 플러그인을 양쪽 다 맞춰야 하고
- 개발에서 잘 되는데 빌드하면 터지는 경우가 있고
- 디버깅할 때 어느 쪽 문제인지 추적이 귀찮고
Rolldown 하나면 이 문제가 다 사라져요.
얼마나 빠른데요
Rolldown 팀 공식 벤치마크:
React 앱 (JSX 10,000개):
Rollup 14.0초 → Rolldown 3.7초 (3.8배)
GitLab 모노레포:
Webpack 45.2초 → Rolldown 12.1초 (3.7배)
Excalidraw:
Webpack 24.6초 → Rolldown 1.5초 (16.4배)
써보려면
Vite 유저라면 진짜 간단해요:
npm install vite@next # 끝. Rolldown이 기본 번들러.
독립 실행도 됩니다:
// rolldown.config.js import { defineConfig } from 'rolldown'; export default defineConfig({ input: './src/index.ts', output: { dir: 'dist', format: 'esm', sourcemap: true }, resolve: { extensions: ['.ts', '.tsx', '.js', '.jsx'] }, });
Rollup 플러그인 API를 그대로 쓰니까 기존 플러그인도 거의 다 동작해요:
import { defineConfig } from 'rolldown'; import react from '@vitejs/plugin-react'; export default defineConfig({ input: './src/main.tsx', plugins: [react()], output: { dir: 'dist', format: 'esm' }, });
Oxc — 파서, 린터, 트랜스포머, 미니파이어를 하나로
VoidZero 스택에서 가장 야심 찬 프로젝트예요. 도구 하나가 아니라 통째로 언어 툴체인입니다:
- 파서: SWC보다 3배 빠름
- 린터 (Oxlint): ESLint보다 50~100배 빠름
- 트랜스포머: Babel보다 40배 빠름
- 미니파이어: Terser급 압축률, 네이티브 속도
핵심은 AST를 한 번만 만들고 전부 돌려쓴다는 거예요. 지금까지는 도구마다 AST를 새로 만들었는데, 그 낭비를 완전히 없앤 거죠.
Oxlint, 진짜 ESLint 대체할 수 있나?
숫자부터 보세요:
TypeScript 프로젝트 2,000개 파일 기준:
ESLint 9: 12.4초 → Oxlint: 0.13초 (95배)
메모리: ESLint ~450MB → Oxlint ~28MB (16배)
오타 아닙니다. 12초 vs 0.13초.
npm install -D oxlint npx oxlint .
기존 ESLint 지우지 말고 같이 돌려도 돼요:
{ "scripts": { "lint": "oxlint . && eslint .", "lint:fast": "oxlint ." } }
흔한 규칙은 Oxlint한테 맡기고, ESLint는 커스텀 플러그인용으로만 남겨두면 됩니다.
Rspack — Webpack 설정 그대로 가져가고 싶을 때
Rolldown이 Vite 쪽 대안이라면, Rspack은 Webpack 설정 그대로 쓰면서 빨라지는 쪽이에요. ByteDance에서 만들었고, webpack.config.js가 5년치 레거시인 팀에 딱 맞습니다.
솔직히 말하면요. 프로덕션에서 Webpack 돌리는 앱이 아직 수백만 개예요. 이걸 Vite로 재구성하는 게 현실적이지 않은 팀이 많죠. Rspack은 그런 팀을 위한 거예요.
얼마나 빠른데요
ByteDance 내부 프로젝트:
Webpack 5: 120초 → Rspack 1.7: 36초 (콜드빌드 70% 감소)
HMR: 8.2초 → 1.6초 (80% 감소)
써보려면
// rspack.config.js — webpack.config.js랑 거의 같죠? const { defineConfig } = require('@rspack/cli'); module.exports = defineConfig({ entry: './src/index.tsx', output: { path: __dirname + '/dist', filename: '[name].[contenthash].js', }, module: { rules: [ { test: /\.tsx?$/, use: { loader: 'builtin:swc-loader', // babel-loader 대신 내장 SWC options: { jsc: { parser: { syntax: 'typescript', tsx: true }, transform: { react: { runtime: 'automatic' } }, }, }, }, }, { test: /\.css$/, type: 'css' }, ], }, resolve: { extensions: ['.ts', '.tsx', '.js', '.jsx'] }, optimization: { splitChunks: { chunks: 'all' } }, });
Rspack 2.0 프리뷰 (2월 중)
- 빌드 간 캐시 유지: 콜드 스타트 더 줄어듦
- Module Federation 2.0: 마이크로 프론트엔드 강화
- 트리 셰이킹 개선: Rolldown 수준으로 올라옴
- Oxc 통합: 파싱이랑 변환을 Oxc로 처리
그래서 뭘 써야 하는데요?
상황별 추천
지금 쓰고 있는 거 → 갈아탈 곳
────────────────────────────────────────────────
Webpack + Babel + ESLint → Rspack + Oxlint (설정 거의 안 바꿔도 됨)
→ Vite 8 + Rolldown (새로 구성 가능하면)
Vite + Rollup + ESLint → Vite 8 + Rolldown + Oxlint (업그레이드만)
esbuild 직접 구성 → Rolldown
Create React App → Vite 8 (CRA는 이제 정리할 때)
기능 비교
| Rolldown | Rspack | esbuild | Webpack | |
|---|---|---|---|---|
| 콜드 빌드 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ |
| HMR | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| 플러그인 | ⭐⭐⭐⭐ (Rollup 호환) | ⭐⭐⭐⭐⭐ (Webpack 호환) | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| 트리 셰이킹 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| 지금 쓸 수 있나 | RC | 1.7 안정 | 안정 | 안정 |
마이그레이션, 이 순서로 하세요
1단계: 린터부터 (가장 안전하고 효과 큼)
npm install -D oxlint
{ "scripts": { "lint": "oxlint . && eslint .", "lint:ci": "oxlint ." } }
기존 코드 안 건드리고 CI에 추가만 하면 돼요. 리스크 제로.
2단계: 번들러 교체
Vite 쓴다면:
npm install vite@next npm run build && npm run preview # 스테이징에서 확인
Webpack 쓴다면:
npm install -D @rspack/core @rspack/cli # webpack.config.js → rspack.config.js 이름만 바꾸고 # babel-loader → builtin:swc-loader 교체 npx rspack build
3단계: 수치로 확인
마이그레이션 전후 빌드 시간은 꼭 기록해두세요:
// build-benchmark.mjs import { performance } from 'perf_hooks'; import { execSync } from 'child_process'; const runs = 5; const times = []; for (let i = 0; i < runs; i++) { execSync('rm -rf dist .cache node_modules/.cache'); const start = performance.now(); execSync('npm run build', { stdio: 'pipe' }); times.push(performance.now() - start); } const avg = times.reduce((a, b) => a + b) / times.length; console.log(`평균: ${(avg / 1000).toFixed(2)}s`);
갈아탈 때 조심할 점
플러그인 호환
아직 Rust 대응이 없는 Webpack 로더들이 있어요:
sass-loader→ Rspack 내장 sass 지원이나builtin:lightningcss-loader로 대체- 사내 Babel 플러그인 → 새로 짜야 할 수도 있음
번들 결과물 차이
미세하게 다를 수 있으니까 번들 사이즈랑 동작 확인은 꼭 하세요.
CI 캐시
도구 바뀌면 캐시 키도 업데이트해야 합니다:
- uses: actions/cache@v4 with: path: | node_modules/.cache .rspack-cache key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}
앞으로의 일정
지금 (2026 Q1)
- ✅ Rolldown 1.0 RC 출시
- ✅ Vite 8 베타에 Rolldown 기본 탑재
- 🔜 Rspack 2.0 프리뷰
2026 Q2
- Rolldown 1.0 정식 릴리스 예상
- Oxlint 규칙이 ESLint 코어 수준까지 확대
2026 하반기
- VoidZero 풀스택 통합 (Vite + Rolldown + Oxc + Vitest)
- TypeScript를 별도
tsc없이 번들러 안에서 처리
궁극적으로 vite build 한 줄이면 파싱, 린팅, 변환, 번들링, 압축, 테스트가 한 번에. AST 하나, 패스 하나, 낭비 제로.
정리
JS 빌드 도구의 Rust 전환은 일시적인 유행이 아니에요:
- 빌드 속도: 4~16배
- 린팅 속도: 50~100배
- 메모리 사용량: 1/10~1/16
당장 해볼 수 있는 거:
- 오늘: Oxlint 깔아보세요. 2분이면 됩니다.
- 이번 주: Vite 쓰신다면
vite@next로 올려보세요. - 이번 달: Webpack 쓰신다면 사이드 프로젝트에서 Rspack 한번 돌려보세요.
- 이번 분기: 팀 차원에서 마이그레이션 로드맵 잡으세요.
Webpack이랑 Babel이 당장 사라지진 않아요. 하지만 성능 차이가 압도적이라서, 안 바꾸면 CI 비용도 더 나가고 개발 루프도 느려지고요. 같은 시간에 더 많이 만들 수 있는데 안 바꿀 이유가 없죠.
타이밍은 지금이에요.
관련 도구 둘러보기
Pockit의 무료 개발자 도구를 사용해 보세요