React UI 라이브러리를 위한 번들러 7종 비교
React UI 컴포넌트 라이브러리 패키지를 빌드하기 위해 7가지 번들러를 직접 테스트해 보았습니다. tsup부터 최신 Rust 기반 번들러인 rolldown까지 각각의 특성과 실제 빌드 결과를 정리했습니다.
테스트 환경
테스트에 사용한 패키지는 React와 MUI 기반의 UI 컴포넌트 라이브러리입니다. 모노레포 환경에서 Button이나 Card 그리고 DataTable 등 8개의 컴포넌트를 포함한 core 패키지를 대상으로 했습니다.
| 항목 | 내용 |
|---|---|
| 패키지 유형 | React + MUI 기반 UI 컴포넌트 라이브러리 |
| Entry | src/index.ts (단일 진입점) |
| Output Format | ESM + CJS (dual package) |
| External | React, ReactDOM, MUI, Emotion, 내부 workspace 패키지 |
빌드 결과 요약
번들 크기 비교
번들 크기 측면에서는 Vite가 23KB로 가장 우수한 결과를 보여주었습니다. Rollup과 tsup이 그 뒤를 이었고 rspack은 런타임 코드가 포함되어 상대적으로 큰 번들을 생성했습니다.
| 번들러 | ESM | CJS | 총 크기 | 순위 |
|---|---|---|---|---|
| vite | 14 KB | 9 KB | 23 KB | 🥇 1위 |
| rollup | 17 KB | 18 KB | 35 KB | 🥈 2위 |
| tsup | 18 KB | 21 KB | 39 KB | 🥉 3위 |
| rolldown | 17 KB | 23 KB | 40 KB | 4위 |
| tsdown | 17 KB | 23 KB | 40 KB | 5위 |
| esbuild | 20 KB | 25 KB | 45 KB | 6위 |
| rspack | 52 KB | 57 KB | 109 KB | 7위 |
빌드 시간 비교
빌드 속도에서는 esbuild가 압도적인 성능을 보여주었습니다. Go로 작성된 esbuild는 JS 빌드에 단 10ms만 소요되었습니다.
| 번들러 | 총 시간 | JS 빌드 | 순위 |
|---|---|---|---|
| esbuild | 1.58s | ~10ms | 🥇 1위 |
| tsdown | 1.84s | 853ms (DTS 포함) | 🥈 2위 |
| vite | 2.21s | 75ms | 🥉 3위 |
| rspack | 2.29s | 119ms | 4위 |
| rolldown | 2.37s | 18ms | 5위 |
| tsup | 2.88s | 113ms + 1.8s (DTS) | 6위 |
| rollup | 5.46s | 3.3s | 7위 |
📌 참고
총 시간에는 tsc를 통한 DTS 생성 시간이 포함되어 있습니다. tsup과 tsdown은 DTS를 내장 지원하므로 별도의 tsc 실행이 필요하지 않습니다.
번들러별 상세 비교
1. tsup
tsup은 esbuild를 기반으로 한 번들러입니다. 라이브러리 번들링에 특화되어 있으며 설정이 가장 간단합니다. DTS 생성이 내장되어 있어 별도 설정 없이 타입 정의 파일을 생성할 수 있습니다.
✅ 장점
- 설정이 가장 간단함
- DTS 생성 내장
- 라이브러리 번들링에 최적화
❌ 단점
- DTS 생성이 느림
// tsup.config.ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
external: ['react', '@mui/material', '@workspace/utils'],
});
2. esbuild
esbuild는 Go로 작성된 번들러로 압도적인 빌드 속도를 자랑합니다. 다만 DTS 생성을 지원하지 않아 별도로 tsc를 실행해야 합니다. ESM과 CJS를 동시에 출력하려면 빌드를 두 번 실행해야 합니다.
✅ 장점
- 가장 빠른 빌드 속도
- 간단한 API
❌ 단점
- DTS 미지원
- ESM/CJS 각각 빌드 필요
// esbuild.config.mjs
await esbuild.build({
entryPoints: ['src/index.ts'],
bundle: true,
format: 'esm',
external: ['react', '@mui/material/*', '@workspace/*'],
});
3. rollup
rollup은 JavaScript로 작성된 번들러로 라이브러리 번들링의 표준으로 자리잡았습니다. 작은 번들 크기와 풍부한 플러그인 생태계가 강점입니다. 다만 빌드 속도가 느리고 설정이 다소 복잡합니다.
✅ 장점
- 작은 번들 크기
- 풍부한 플러그인 생태계
- 라이브러리 번들링의 표준
❌ 단점
- 빌드 속도가 느림
- 설정이 복잡함
// rollup.config.mjs
export default {
input: 'src/index.ts',
output: { format: 'esm' },
external: [/^react/, /^@mui\/material/, /^@workspace\//],
plugins: [typescript(), resolve(), commonjs()],
};
4. vite (library mode)
Vite는 프로덕션 빌드 시 rollup을 사용합니다. rollup의 장점에 더 나은 개발 경험을 제공하며 이번 테스트에서 가장 작은 번들 크기를 기록했습니다.
✅ 장점
- 가장 작은 번들 크기
- 간단한 설정
- rollup의 장점 + 더 나은 DX
❌ 단점
- 라이브러리 모드 설정 필요
// vite.config.ts
export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
formats: ['es', 'cjs'],
},
rollupOptions: {
external: [/^react/, /^@mui\/material/, /^@workspace\//],
},
},
});
5. rspack
rspack은 Rust로 작성된 webpack 호환 번들러입니다. 빠른 빌드 속도와 webpack 플러그인 호환성이 강점입니다. 하지만 런타임 코드가 포함되어 번들 크기가 가장 컸습니다. 라이브러리보다는 애플리케이션 번들링에 적합합니다.
✅ 장점
- 빠른 빌드 속도
- webpack 플러그인 호환
❌ 단점
- 가장 큰 번들 크기
- 라이브러리 번들링에 최적화되지 않음
// rspack.config.ts
export default defineConfig({
entry: { index: './src/index.ts' },
output: { library: { type: 'module' } },
externals: [/^react/, /^@mui\/material/, /^@workspace\//],
});
6. rolldown
rolldown은 Rust로 작성된 rollup 호환 번들러입니다. JS 빌드에 18ms만 소요되는 매우 빠른 속도를 보여주었습니다. rollup 호환 API를 제공하므로 마이그레이션이 쉽습니다. 아직 베타 버전이라는 점이 아쉽습니다.
✅ 장점
- 매우 빠른 JS 빌드 (18ms)
- rollup 호환 API
- 작은 번들 크기
❌ 단점
- 아직 베타 버전
- DTS 미지원
// rolldown.config.mjs
import { defineConfig } from 'rolldown';
export default defineConfig([
{
input: 'src/index.ts',
output: { file: 'dist/index.mjs', format: 'esm' },
external: [/^react/, /^@mui\/material/, /^@workspace\//],
},
]);
7. tsdown
tsdown은 rolldown을 기반으로 한 번들러입니다. tsup과 거의 동일한 설정을 사용할 수 있어 tsup 사용자라면 쉽게 전환할 수 있습니다. DTS 생성이 내장되어 있으며 rolldown의 빠른 빌드 속도를 그대로 활용합니다.
✅ 장점
- tsup과 동일한 간단한 설정
- DTS 생성 내장
- rolldown 기반으로 빠름
❌ 단점
- 아직 초기 버전
// tsdown.config.ts
import { defineConfig } from 'tsdown';
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
external: ['react', /^@mui\/material/, /^@workspace\//],
outDir: 'dist',
});
종합 비교표
각 번들러의 특성을 5점 만점으로 평가했습니다.
| 기준 | tsup | esbuild | rollup | vite | rspack | rolldown | tsdown |
|---|---|---|---|---|---|---|---|
| 빌드 속도 | ★★★☆☆ | ★★★★★ | ★★☆☆☆ | ★★★★☆ | ★★★★☆ | ★★★★★ | ★★★★☆ |
| 번들 크기 | ★★★★☆ | ★★★☆☆ | ★★★★☆ | ★★★★★ | ★★☆☆☆ | ★★★★☆ | ★★★★☆ |
| 설정 간편함 | ★★★★★ | ★★★★☆ | ★★★☆☆ | ★★★★☆ | ★★☆☆☆ | ★★★★☆ | ★★★★★ |
| DTS 지원 | ★★★★★ | ★★☆☆☆ | ★★★☆☆ | ★★★☆☆ | ★★☆☆☆ | ★★☆☆☆ | ★★★★★ |
| 안정성 | ★★★★★ | ★★★★★ | ★★★★★ | ★★★★★ | ★★★★☆ | ★★★☆☆ | ★★★☆☆ |
권장 사항
용도별 추천
| 용도 | 추천 번들러 | 이유 |
|---|---|---|
| 라이브러리 번들링 (안정성) | tsup | 간단한 설정과 DTS 내장 그리고 검증된 도구 |
| 라이브러리 번들링 (성능) | tsdown | tsup 호환성과 rolldown 기반의 빠른 빌드 |
| 최소 번들 크기 | vite | 가장 작은 출력물 |
| 최고 빌드 속도 | esbuild / rolldown | 압도적으로 빠름 |
| webpack 마이그레이션 | rspack | 플러그인 호환성 |
| 복잡한 빌드 파이프라인 | rollup | 풍부한 플러그인 |
💡 결론
현재 시점에서는 tsup을 유지하는 것을 권장합니다. 라이브러리 번들링에 가장 적합하고 DTS 생성이 내장되어 있으며 안정적이고 검증된 도구입니다. 향후 rolldown이 정식 릴리즈되면 tsdown으로의 마이그레이션을 고려해볼 만합니다.
마이그레이션 가이드
tsup → tsdown 마이그레이션
tsdown은 tsup의 drop-in replacement를 목표로 설계되어 설정이 거의 동일합니다. 예상 소요 시간은 5~10분 정도입니다.
변경 사항
// 변경 전 (tsup.config.ts)
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
splitting: true,
sourcemap: true,
clean: true,
external: [
'react',
'react-dom',
'@mui/material',
'@emotion/react',
'@workspace/hooks',
'@workspace/utils',
],
treeshake: true,
});
// 변경 후 (tsdown.config.ts)
import { defineConfig } from 'tsdown';
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
sourcemap: true,
clean: true,
external: [
'react',
'react-dom',
/^@mui\/material/, // 하위 경로 포함을 위해 정규식 사용
/^@emotion\//,
/^@workspace\//, // 정규식으로 통합
],
outDir: 'dist',
});
주요 차이점
| 항목 | tsup | tsdown |
|---|---|---|
| import | from 'tsup' |
from 'tsdown' |
| splitting | 옵션으로 설정 | 기본 내장 (옵션 제거) |
| treeshake | 옵션으로 설정 | 기본 내장 (옵션 제거) |
| external | 문자열/정규식 | 정규식 권장 |
| 출력 파일명 | .js / .mjs | .cjs / .mjs |
rollup → rolldown 마이그레이션
rolldown은 rollup 호환 API를 제공하며 플러그인 없이 TypeScript를 기본 지원합니다. 예상 소요 시간은 10~20분 정도입니다.
// 변경 전 (rollup.config.mjs)
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
export default [
{
input: 'src/index.ts',
output: {
file: 'dist/index.mjs',
format: 'esm',
sourcemap: true,
},
external: [
'react',
'react-dom',
/^@mui\/material/,
'@emotion/react',
],
plugins: [
resolve(),
commonjs(),
typescript({ tsconfig: './tsconfig.json' }),
],
},
];
// 변경 후 (rolldown.config.mjs)
import { defineConfig } from 'rolldown';
export default defineConfig([
{
input: 'src/index.ts',
output: {
file: 'dist/index.mjs',
format: 'esm',
sourcemap: true,
},
external: [
/^react/,
/^@mui\/material/,
/^@emotion\//,
],
// plugins 불필요 - TypeScript, resolve, commonjs 기본 내장
},
]);
⚠️ 주의사항
rolldown과 tsdown은 아직 베타 버전입니다. 프로덕션 사용 전 충분한 테스트가 필요하며 1.0 정식 릴리즈까지 대기하는 것을 권장합니다. 또한 rolldown은 일부 rollup 플러그인과 호환되지 않을 수 있습니다.
마무리
React UI 라이브러리 번들링을 위한 7가지 번들러를 비교해 보았습니다. 각 번들러마다 장단점이 있으며 프로젝트의 요구사항에 따라 적절한 도구를 선택하면 됩니다.
안정성을 중시한다면 tsup을 추천합니다. 빌드 속도가 중요하다면 esbuild나 rolldown을 고려해볼 만합니다. 번들 크기 최적화가 필요하다면 vite의 라이브러리 모드가 좋은 선택입니다.
Rust 기반 번들러인 rolldown과 tsdown은 아직 베타이지만 매우 빠른 빌드 속도를 보여주고 있습니다. 정식 릴리즈 후에는 라이브러리 번들링의 새로운 표준이 될 가능성이 높습니다.
'je개발 회고' 카테고리의 다른 글
| [ 번들러 ] 모노레포 번들러 비교 (0) | 2025.12.22 |
|---|---|
| [ Git ] 회사에 맞는 브랜치 전략 (0) | 2025.12.22 |
| [ 데이터 품질 관리 ] (4) Frontend : Batching (4) | 2025.08.19 |
| [ 데이터 품질 관리 ] (3) Frontend : Zod 스키마와 API 검증 (3) | 2025.08.18 |
| [ 데이터 품질 관리 ] (2) Frontend : 아키텍쳐와 설계 철학 (3) | 2025.08.18 |