Back

번들러부터 린터까지, 전부 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 한 번 돌리면 내부에서 일어나는 일:

  1. Babel이 코드를 AST로 파싱 → 변환 → 직렬화
  2. ESLint가 같은 코드를 또 파싱 → 규칙 검사
  3. Webpack/Rollup이 또또 파싱 → 모듈 해석 → 번들링
  4. Terser가 결과물을 또또또 파싱 → 압축

같은 코드를 네 번 넘게 파싱하는 거예요. 각자 다른 AST 포맷으로, 전부 싱글 스레드로, GC 멈춤 먹으면서. 이게 정상일 리가 없잖아요.

Rust는 이 문제를 언어 차원에서 해결해요

문제JavaScriptRust
속도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는 이제 정리할 때)

기능 비교

RolldownRspackesbuildWebpack
콜드 빌드⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
HMR⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
플러그인⭐⭐⭐⭐ (Rollup 호환)⭐⭐⭐⭐⭐ (Webpack 호환)⭐⭐⭐⭐⭐⭐⭐
트리 셰이킹⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
지금 쓸 수 있나RC1.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

당장 해볼 수 있는 거:

  1. 오늘: Oxlint 깔아보세요. 2분이면 됩니다.
  2. 이번 주: Vite 쓰신다면 vite@next로 올려보세요.
  3. 이번 달: Webpack 쓰신다면 사이드 프로젝트에서 Rspack 한번 돌려보세요.
  4. 이번 분기: 팀 차원에서 마이그레이션 로드맵 잡으세요.

Webpack이랑 Babel이 당장 사라지진 않아요. 하지만 성능 차이가 압도적이라서, 안 바꾸면 CI 비용도 더 나가고 개발 루프도 느려지고요. 같은 시간에 더 많이 만들 수 있는데 안 바꿀 이유가 없죠.

타이밍은 지금이에요.

RustJavaScriptViteRolldownOxcRspackBuild ToolsWeb DevelopmentPerformance

관련 도구 둘러보기

Pockit의 무료 개발자 도구를 사용해 보세요