개인정보처리방침© 2026 DEV BAK - 기술블로그. All rights reserved.
DEV BAK - 기술블로그
frontend

Vite 8 + Rolldown: 이중 번들러 통합으로 프로덕션 빌드 시간을 87% 단축한 원리

(Vite 8 Rolldown migration | build speed)

46초짜리 빌드가 6초로 줄었다는 말을 처음 들었을 때 솔직히 반신반의했습니다. 벤치마크 숫자는 늘 현실보다 좋으니까요. 그런데 Linear, GitLab, Ramp 같은 실제 프로덕션 코드베이스에서 속속 같은 결과가 나오기 시작했습니다. Linear의 경우 19,000개 모듈 규모의 코드베이스에서 46초 → 6초로 줄어든 것이 공개 사례입니다. 2026년 3월에 정식 출시된 Vite 8은 단순한 버전 업그레이드가 아닙니다. 빌드 파이프라인의 구조 자체를 바꿨고, 그 변화가 숫자로 고스란히 드러나고 있습니다.

이 글은 Vite를 이미 사용하고 있는 프론트엔드 개발자가 주요 독자입니다. 빌드 속도 문제에 관심 있는 분이라면 개념 섹션까지도 충분히 읽을 수 있습니다. 마이그레이션을 고민 중이거나 CI 빌드 비용이 부담되는 분들께 도움이 됩니다.


핵심 개념

이중 번들러 구조, 왜 문제였나

Vite 7까지의 구조를 간단히 그려보면 이렇습니다.

개발 서버 → esbuild (의존성 사전 번들) + Vite 자체 ESM 서버
프로덕션 빌드 → Rollup

개발 중에는 esbuild가 node_modules를 미리 번들하고, 프로덕션 빌드는 Rollup이 담당했습니다. 두 도구는 동작 방식이 달라서 "개발에서는 멀쩡했는데 빌드하면 터진다"는 상황이 종종 생겼습니다. 저도 이런 상황을 실무에서 몇 번 겪었는데, 원인을 추적하다 보면 결국 esbuild와 Rollup의 트리 쉐이킹 동작 차이였던 경우가 꽤 있었습니다.

Vite 8은 이 두 역할을 Rolldown 하나로 통합했습니다. 속도뿐 아니라 오랜 구조적 약점이었던 dev/prod 번들러 불일치도 함께 해결됩니다.

Rolldown은 무엇인가

Rolldown은 Evan You(Vue.js 창시자)가 창립한 VoidZero가 Rust로 개발한 JavaScript/TypeScript 번들러입니다. Rollup과 호환되는 플러그인 API를 유지하면서 Rust 네이티브 속도를 구현합니다.

내부 파이프라인을 보면 파싱 → 트랜스파일 → 코드 최적화까지 전 과정을 Oxc가 처리합니다. Oxc는 단순한 컴파일러가 아니라 파서·린터·트랜스파일러·최소화기를 하나로 묶은 Rust 기반 툴킷입니다. CSS 최소화는 기존 esbuild에서 Lightning CSS(역시 Rust)로 교체됐습니다.

Rolldown 내부 파이프라인
──────────────────────────────────────
소스 코드 입력
  └─▶ Oxc 파서 (AST 생성)
        └─▶ Oxc 트랜스파일러 (TS/JSX → JS)
              └─▶ Rolldown 링커 (청크 분할·트리 쉐이킹)
                    └─▶ Oxc 최소화기
                          └─▶ Lightning CSS (CSS 처리)
                                └─▶ 최종 번들 출력
──────────────────────────────────────

VoidZero 팀이 Rolldown과 Oxc를 직접 개발하고, Vite 핵심 기여자 다수가 VoidZero 소속이라는 점이 중요합니다. 이전에는 esbuild, Rollup, Babel이 각각 별도 팀에 의해 운영됐고, 이 파편화된 구조가 통합과 최적화의 걸림돌이었습니다. Vite 8은 이 수직 통합 툴체인 전략의 가장 가시적인 결실입니다.

얼마나 빠른가

번들러 빌드 시간 비고
Rolldown 1.61초 공식 벤치마크, 19,000 모듈 기준
Rollup 40.10초 동일 조건
개선 배율 약 25배

기업 실측 사례도 비슷한 추세입니다.

기업 이전 이후 개선율
Linear 46초 6초 87% 단축
GitLab 2분 30초 22초 ~85% 단축
Ramp — — 57% 단축
Beehiiv — — 64% 단축

수치마다 측정 조건이 다르니 직접 비교는 어렵지만, 규모 있는 코드베이스일수록 효과가 두드러진다는 공통점은 분명합니다.


실전 적용

예시 1: Vite 7 상태에서 Rolldown 먼저 검증하기

Vite 8로 바로 올리기 부담스럽다면 rolldown-vite 패키지를 통해 Vite 7 설정을 유지하면서 Rolldown 번들러만 먼저 테스트해볼 수 있습니다. 번들러 이슈가 생겼을 때 Vite API 변경 탓인지 Rolldown 탓인지 헷갈리지 않으려면 이 단계를 거치는 것이 훨씬 편합니다. 저도 처음에 이 단계를 건너뛰었다가 플러그인 이슈와 번들러 이슈가 뒤섞여서 꽤 고생했습니다.

가장 간단한 방법은 vite를 rolldown-vite로 alias 처리하는 것입니다.

bash
# 가장 간단한 방법: alias 설치
pnpm add vite@npm:rolldown-vite

조금 더 명시적으로 관리하고 싶다면 pnpm.overrides를 활용할 수 있습니다.

bash
pnpm remove vite
pnpm add -D rolldown-vite
json
// package.json
{
  "devDependencies": {
    "rolldown-vite": "^8.0.0"
  },
  "pnpm": {
    "overrides": {
      "vite": "npm:rolldown-vite@*"
    }
  }
}

이 상태로 pnpm build를 돌려보면 Rolldown이 번들러 역할을 하면서 Vite 7 설정이 그대로 유지됩니다. 빌드 결과물과 런타임에서 이상이 없다면 Vite 8 업그레이드로 넘어가는 것을 권장합니다.

예시 2: Vite 8 정식 업그레이드

Rolldown 검증이 끝났다면 Vite 8로 올리는 작업은 생각보다 간단합니다.

bash
pnpm add -D vite@^8.0.0

주요 변경 사항 중 가장 손이 많이 가는 건 설정 키 이름 변경입니다.

typescript
// vite.config.ts — Vite 7
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
        },
      },
    },
  },
})
typescript
// vite.config.ts — Vite 8
export default defineConfig({
  build: {
    rolldownOptions: {   // ← rollupOptions에서 변경
      output: {
        advancedChunks: {  // ← manualChunks보다 패턴 기반 매칭이 유연
          groups: [
            { name: 'vendor', test: /node_modules/ },
            { name: 'ui', test: /src\/components/ },
          ],
        },
      },
    },
  },
})

advancedChunks는 manualChunks보다 패턴 기반 매칭이 유연합니다. 수백 개의 청크를 관리하던 프로젝트에서는 설정 코드 자체가 줄어드는 효과도 있습니다.

변경 항목 Vite 7 Vite 8 비고
번들러 esbuild + Rollup Rolldown 자동 전환
CSS 최소화 esbuild Lightning CSS 명시적 재설정 가능
청크 설정 키 rollupOptions rolldownOptions 자동 변환 지원
import.meta.hot.accept URL 전달 가능 id로 변경 필요 수동 수정

제가 마이그레이션에서 가장 신경 썼던 건 CSS 최소화 출력 변경이었습니다. Lightning CSS와 esbuild의 CSS 처리 결과가 미묘하게 다를 수 있어서, 기존 동작을 유지하고 싶다면 아래처럼 명시적으로 설정할 수 있습니다.

typescript
// vite.config.ts — Lightning CSS 대신 esbuild CSS 최소화 유지
export default defineConfig({
  css: {
    transformer: 'postcss',  // Lightning CSS 비활성화
  },
  build: {
    cssMinify: 'esbuild',
  },
})

예시 3: Full Bundle Mode — dev/prod 불일치 원천 차단

Rolldown 통합 덕분에 새롭게 쓸 수 있게 된 기능 중 하나가 Full Bundle Mode입니다. 개발 서버에서도 Rolldown이 번들을 생성하도록 해서 dev/prod 결과물 간 불일치를 원천 차단할 수 있습니다.

typescript
// vite.config.ts — Full Bundle Mode 활성화
export default defineConfig({
  dev: {
    bundleMode: 'bundle',  // 기본값: 'module' (기존 ESM 방식)
  },
})

공식 발표 기준으로 기존 ESM 방식 대비 네트워크 요청이 크게 감소합니다. 수천 개 모듈을 가진 모노레포에서 dev 서버 첫 화면 로딩이 체감상 빨라지는 것을 느낄 수 있습니다.

다만 몇 가지 특성 변화는 미리 알아두면 좋습니다. HMR 응답 방식이 ESM 개별 모듈 교체 방식과 달라지고, 첫 번들 생성 시 초기 빌드 부하가 약간 증가합니다. dev와 prod 결과를 최대한 일치시키고 싶은 팀에게 적합하고, 빠른 HMR 피드백 루프가 중요한 팀은 기본값(module)을 유지하는 것도 충분한 선택입니다.


장단점 분석

장점

항목 내용
빌드 속도 공식 벤치마크(19,000 모듈) 기준 Rollup 대비 약 25배; Linear 사례(46초 → 6초) 기준 87% 단축
번들러 일관성 dev/prod 동일 번들러 → 빌드 불일치 버그 구조적 제거
플러그인 호환성 Rollup/Vite 플러그인 API와 거의 완전 호환, 생태계 충격 최소화
HMR 개선 대형 프로젝트 dev 서버 시작 3배 빠름, 전체 리로드 40% 단축
신규 기능 Module Federation, 모듈 수준 영속 캐시, 유연한 청크 분할(advancedChunks)

단점 및 주의사항

항목 내용 대응 방안
API 명칭 변경 rollupOptions → rolldownOptions 자동 변환 후 장기적으로 수동 업데이트
Extglob 패턴 미지원 기존 rollupOptions에서 glob 확장 패턴을 쓰고 있었다면 Rolldown에서 조용히 실패할 수 있음 일반 정규식 패턴으로 대체
TypeScript legacy namespace 오래된 엔터프라이즈 코드베이스나 Angular 레거시처럼 namespace 문법을 광범위하게 쓰는 경우 부분적으로 영향 받을 수 있음 릴리즈 노트 확인 후 우회 패턴 적용
import.meta.hot.accept URL 전달 불가, id 기반으로 변경 필요 id 기반으로 교체
CSS 최소화 변경 Lightning CSS 기본값 전환으로 출력이 미묘하게 달라질 수 있음 기존 동작 유지 시 명시적 설정
소규모 프로젝트 빌드가 이미 수 초 미만인 경우 체감 효과 제한적 속도보다 dev/prod 일관성 이점에 집중

Lightning CSS: Mozilla가 개발하고 Parcel 팀이 기여한 Rust 기반 CSS 파서/변환기/최소화기입니다. autoprefixer, CSS Modules, 최신 CSS 문법 다운레벨링을 하나의 도구로 처리합니다.

Module Federation: 여러 독립 빌드된 앱이 런타임에 서로의 모듈을 공유하는 마이크로 프론트엔드 기법입니다. Webpack 5에서 처음 주목받았고, Rolldown 1.0 stable에서 공식 지원이 추가됐습니다.

실무에서 가장 흔한 실수

저는 처음에 격리 단계를 건너뛰었다가 플러그인 이슈랑 번들러 이슈가 뒤섞여서 이틀을 날렸습니다. 그 경험을 바탕으로 자주 만나는 함정 세 가지를 정리해봤습니다.

  1. rolldown-vite 중간 단계를 건너뛰고 Vite 8 직행하기 — 번들러 이슈와 Vite API 변경 이슈가 뒤섞이면 원인 추적이 어려워집니다. 규모가 크거나 플러그인이 많은 프로젝트일수록 격리 단계가 빛을 발합니다.
  2. CSS 최소화 출력 검증 없이 배포하기 — Lightning CSS와 esbuild의 CSS 처리 결과가 미묘하게 다를 수 있습니다. pnpm build 후 주요 페이지 스타일을 시각적으로 확인해보시면 좋습니다.
  3. Extglob 패턴을 rolldownOptions에 그대로 옮기기 — 기존 rollupOptions에서 glob 확장 패턴을 쓰고 있었다면 마이그레이션 전 패턴 목록을 점검해보시면 좋습니다. 지원되지 않는 패턴은 에러 없이 조용히 무시될 수 있습니다.

마치며

당신의 다음 PR이 CI 파이프라인에서 수십 초를 돌려줄 수 있습니다. Vite 8 + Rolldown의 진짜 의미는 속도 숫자 그 자체보다, 오랫동안 Vite의 구조적 약점이었던 이중 번들러 불일치를 제거하면서 동시에 극적인 성능 향상까지 이뤄냈다는 데 있습니다.

지금 바로 시작해볼 수 있는 3단계입니다.

  1. Rolldown 격리 테스트: 기존 프로젝트에서 pnpm add vite@npm:rolldown-vite로 번들러만 교체한 뒤 pnpm build를 돌려봅니다. Vite 7 설정을 그대로 두고 빌드 결과와 속도만 먼저 비교해볼 수 있습니다.
  2. Vite 8 업그레이드: 격리 테스트에서 이상이 없다면 pnpm add -D vite@^8.0.0으로 업그레이드한 뒤 rollupOptions → rolldownOptions 키 변경과 import.meta.hot.accept 코드를 점검합니다.
  3. 빌드 시간 전후 비교: CI 파이프라인 로그에서 빌드 시간을 미리 기록해두고, 업그레이드 후 수치를 비교해봅니다. 미들~라지 규모 프로젝트에서 체감 가능한 차이가 납니다.

참고 자료

  • Vite 8.0 is out! | vite.dev
  • Vite 8 Beta: The Rolldown-powered Vite | vite.dev
  • Vite 8.1 is out! | vite.dev
  • Migration from v7 | vite.dev
  • Announcing Rolldown 1.0 | voidzero.dev
  • Announcing Rolldown-Vite | voidzero.dev
  • Introduction | rolldown.rs
  • Vite team claims 10-30x faster builds with Rolldown | The Register
  • Vite Version 8: Unified Rust-Based Bundler and Up to 30x Faster Builds | InfoQ
  • Testing out Vite 8 on SPA: Vite 8 is 5x faster | Peterbe.com
  • Rust Is Eating the JavaScript Toolchain | DEV Community
  • rolldown/rolldown | GitHub
  • vitejs/rolldown-vite | GitHub
#Vite#Rolldown#번들러#Rust#빌드최적화#Oxc#LightningCSS#트리쉐이킹#ModuleFederation#마이크로프론트엔드
공유하기

목차

핵심 개념이중 번들러 구조, 왜 문제였나Rolldown은 무엇인가얼마나 빠른가실전 적용예시 1: Vite 7 상태에서 Rolldown 먼저 검증하기예시 2: Vite 8 정식 업그레이드예시 3: Full Bundle Mode — dev/prod 불일치 원천 차단장단점 분석장점단점 및 주의사항실무에서 가장 흔한 실수마치며참고 자료

추천 포스트

RSC 없이 DB 직접 호출부터 스트리밍까지 — TanStack Start와 Next.js, 풀스택 경계가 어디서 갈리는가
frontend

RSC 없이 DB 직접 호출부터 스트리밍까지 — TanStack Start와 Next.js, 풀스택 경계가 어디서 갈리는가

Next.js 13 App Router가 나왔을 때 솔직히 많이 흔들렸습니다. 를 붙였다 떼었다 하면서 "나만 이상한 건가" 싶은 불안감, 서버 컴포넌트 안에서 를 쓰려다 런타임 에러를 맞닥뜨리는 경험. React와 Next.js를 어느 정도 써온 분이라면 한 번쯤 공감할 겁니다. 그 ...

2026년 06월 26일읽는 데 27분
React Compiler 1.0으로 useMemo 400줄을 지웠더니 TBT가 15% 줄었다
frontend

React Compiler 1.0으로 useMemo 400줄을 지웠더니 TBT가 15% 줄었다

컴파일러에 메모이제이션을 넘기기 전에 알아야 할 것 솔직히 말하면, 처음 를 배웠을 때 저도 남용했습니다. "비싼 연산이면 다 걸어야 하는 거 아닌가?" 하는 마음에 컴포넌트마다 와 을 도배했고, 어느 순간 코드의 절반이 최적화 힌트로 가득 찬 모습을 마주했습니다. 기능 코드보다 ...

2026년 06월 26일읽는 데 18분
ESLint vs Biome vs Oxlint — 2026년 프론트엔드 린팅 도구의 속도·생태계·마이그레이션 비용 비교
frontend

ESLint vs Biome vs Oxlint — 2026년 프론트엔드 린팅 도구의 속도·생태계·마이그레이션 비용 비교

린터(linter)는 코드를 실행하기 전에 잠재적 버그, 나쁜 패턴, 스타일 불일치를 잡아주는 도구입니다. CI 파이프라인에서 린팅이 없으면 리뷰에서 걸렸을 실수들이 프로덕션까지 가는 경험, 한 번쯤 해보셨을 겁니다. 솔직히 저도 "ESLint면 충분하지"라고 생각하며 꽤 오랫동안...

2026년 06월 26일읽는 데 22분
CSS Anchor Positioning으로 Popper.js 제거하기 — 브라우저가 직접 처리하는 플로팅 UI
frontend

CSS Anchor Positioning으로 Popper.js 제거하기 — 브라우저가 직접 처리하는 플로팅 UI

프론트엔드를 하다 보면 어느 순간 이런 생각을 하게 됩니다. "버튼 아래에 드롭다운 하나 붙이는 게 왜 이렇게 복잡하지?" 몇 년 전 팀 내 디자인 시스템을 처음 만들 때, Floating UI 셋업과 뷰포트 플립 로직 디버깅에 하루를 통째로 날린 적이 있었습니다. 지금 돌아보면 그 복...

2026년 06월 26일읽는 데 21분
EAA 발효 후 프론트엔드 접근성 점검 체크리스트 15가지 (유럽 접근성법 WCAG 2.1 AA 기준)
frontend

EAA 발효 후 프론트엔드 접근성 점검 체크리스트 15가지 (유럽 접근성법 WCAG 2.1 AA 기준)

2025년 6월 28일, 슬랙에서 흘러온 메시지를 보다가 멈췄습니다. "EAA 발효됐는데, 우리 서비스 괜찮아?" 처음엔 "EU 법이니까 유럽에서 직접 사업하는 회사 얘기겠지" 싶었는데, 역외 적용 조항을 읽고 나서 생각이 달라졌습니다. EU 고객에게 서비스를 제공하는 기업이라면 본사가...

2026년 06월 26일읽는 데 26분
엣지 MFE 오케스트레이션으로 TTFB를 줄이는 Cloudflare Workers 구현법
frontend

엣지 MFE 오케스트레이션으로 TTFB를 줄이는 Cloudflare Workers 구현법

솔직히 처음 마이크로 프론트엔드(MFE) 이야기를 들었을 때, "팀마다 독립 배포가 된다고? 좋아 보이는데, 그럼 사용자 브라우저에서 각자 번들을 다 받아야 하는 거 아냐?" 하는 생각부터 들었습니다. 클라이언트 사이드 컴포지션의 고질적인 문제, 그러니까 여러 MFE의 JS 번들이 순차...

2026년 06월 23일읽는 데 23분