Bun 완벽 가이드 — Node.js보다 빠른 JavaScript 런타임
Bun의 설치, 벤치마크, 빌트인 번들러/테스트러너, Node.js·Deno와의 비교, 실전 프로젝트 셋업.
한 줄 요약: Bun은 JavaScript 런타임, 번들러, 패키지 매니저, 테스트 러너를 하나로 합친 올인원 도구로, Node.js보다 번들 설치 속도가 최대 30배, HTTP 처리가 최대 5배 빠르다. 단, Node.js와의 완전한 호환성은 아직 진행 중이다.
- Bun이 실제로 얼마나 빠른지 벤치마크 수치와 함께 이해하고 싶은 개발자
- Node.js 프로젝트를 Bun으로 마이그레이션하기 전에 호환성 이슈를 먼저 파악하려는 경우
- 빌트인 번들러, 테스트 러너를 별도 도구 없이 사용하고 싶은 경우
- Deno와 Bun 중 어떤 것을 선택해야 하는지 비교 기준이 필요한 경우
Bun이란 무엇인가 — 왜 만들어졌나
Bun은 Jarred Sumner가 만든 JavaScript/TypeScript 올인원 툴킷이다. 2023년 9월 v1.0이 출시됐고, 2026년 현재 v1.2+가 프로덕션에서 사용되고 있다.
Node.js 생태계의 고통 포인트는 파편화다. 런타임(Node.js), 번들러(webpack/vite), 테스트(Jest/Vitest), 패키지 매니저(npm/yarn/pnpm)를 각각 설치하고 설정해야 한다. Bun은 이 모든 것을 하나의 바이너리로 통합했다.
Bun의 핵심 구성
- 런타임: JavaScriptCore(Apple WebKit 엔진) 기반. V8(Chrome/Node.js)이 아닌 JSC를 채택해 시작 시간이 빠르다.
- 번들러:
bun build명령. esbuild 수준의 속도로 번들링. tree-shaking, minification 내장. - 패키지 매니저:
bun install. npm 레지스트리 호환. lockfile은bun.lockb(바이너리 형식). - 테스트 러너:
bun test. Jest 호환 API(describe,test,expect). 추가 패키지 설치 불필요.
설치 및 첫 프로젝트 셋업
Bun은 curl 스크립트 한 줄로 설치된다. macOS, Linux, WSL을 지원한다. Windows 네이티브 지원은 v1.1부터 추가됐다.
Bun 설치 — macOS / Linux / Windows# macOS / Linux / WSL curl -fsSL https://bun.sh/install | bash # Windows (PowerShell) powershell -c "irm bun.sh/install.ps1 | iex" # Homebrew (macOS) brew install oven-sh/bun/bun # 버전 확인 bun --version # 예시 출력: 1.2.4 # 새 프로젝트 초기화 bun init my-app cd my-app # 패키지 설치 (npm install과 동일) bun install # TypeScript 파일 직접 실행 (tsc 불필요) bun run index.ts # 개발 서버 (파일 변경 시 자동 재시작) bun --hot run index.ts
Bun HTTP 서버 — 빌트인 Bun.serve() API// index.ts const server = Bun.serve({ port: 3000, async fetch(req) { const url = new URL(req.url) if (url.pathname === '/') { return new Response('Hello from Bun!', { headers: { 'Content-Type': 'text/plain' } }) } if (url.pathname === '/api/data') { // SQLite 쿼리 (빌트인 bun:sqlite) const db = new Database('app.db') const rows = db.query('SELECT * FROM items LIMIT 10').all() return Response.json(rows) } return new Response('Not Found', { status: 404 }) }, error(err) { return new Response(`Error: ${err.message}`, { status: 500 }) } }) console.log(`Server running at http://localhost:${server.port}`)
벤치마크 — Node.js, Deno와 실제 성능 비교
공식 벤치마크와 커뮤니티 측정치를 종합한 수치다 (2024년 기준, 하드웨어/워크로드에 따라 달라질 수 있음).
| 항목 | Bun | Node.js 22 | Deno 2 |
|---|---|---|---|
| 패키지 설치 (1,000개) | 약 2~3초 | 약 30~60초 | N/A (npm 호환 별도) |
| HTTP 요청/초 (Hello World) | ~250,000 req/s | ~60,000 req/s | ~120,000 req/s |
| 스크립트 시작 시간 | ~5ms | ~50ms | ~20ms |
| SQLite 읽기 (10만 행) | ~0.3초 | ~1.5초 (better-sqlite3) | ~0.8초 |
| TypeScript 실행 | 직접 실행 (트랜스파일 없음) | --experimental-strip-types (v22+) | 직접 실행 |
※ 벤치마크 수치는 실행 환경과 워크로드에 따라 크게 달라진다. 공식 수치: bun.sh
빌트인 기능 — 번들러, 테스트 러너, SQLite
번들러 — bun build
esbuild보다 빠른 번들 속도를 목표로 한다. 브라우저, Node.js, Bun 타깃 모두 지원한다.
bun build — 프론트엔드 번들링# 단일 진입점 번들 bun build ./src/index.tsx --outdir ./dist --target browser --minify # 라이브러리 빌드 (ESM + CJS) bun build ./src/index.ts --outdir ./dist --target node --format esm bun build ./src/index.ts --outdir ./dist --target node --format cjs # 번들 결과 분석 bun build ./src/index.tsx --outdir ./dist --analyze
bun test — Jest 호환 테스트 작성// math.test.ts import { describe, test, expect, mock, beforeEach } from 'bun:test' function add(a: number, b: number) { return a + b } async function fetchUser(id: string) { const res = await fetch(`/api/users/${id}`) return res.json() } describe('add function', () => { test('두 수를 더한다', () => { expect(add(2, 3)).toBe(5) }) test('음수를 처리한다', () => { expect(add(-1, 1)).toBe(0) }) }) describe('fetchUser', () => { beforeEach(() => { // fetch 목킹 (bun:test 빌트인) global.fetch = mock(() => Promise.resolve(new Response(JSON.stringify({ id: '1', name: 'Alice' }))) ) }) test('사용자 데이터를 반환한다', async () => { const user = await fetchUser('1') expect(user.name).toBe('Alice') }) })
Node.js 호환성 이슈 — 프로덕션 전에 확인할 것들
Bun은 Node.js API 대부분을 지원하지만 100% 호환은 아니다. 마이그레이션 전에 반드시 확인해야 할 이슈들이 있다.
주요 호환성 이슈
- 네이티브 애드온 (.node 파일): N-API 기반 네이티브 모듈은 대부분 작동하지만 일부는 재컴파일이 필요하다.
bcrypt,sharp등은 Bun 전용 대안이 있다. - worker_threads: 지원하지만 Node.js와 API 차이가 있을 수 있다. Bun 자체 Worker API 사용을 권장.
- Node.js 레거시 API:
require('domain'), 일부util메서드는 스텁 구현 상태. - ESM/CJS 혼용: Bun은 두 형식을 모두 처리하지만,
__dirname,__filename은 ESM 컨텍스트에서import.meta.dir,import.meta.path로 대체해야 한다.
Bun을 언제 써야 하는가 — 실전 판단 기준
Bun의 속도 장점이 실제로 의미 있는 상황과 그렇지 않은 상황을 구분해야 한다.
Bun이 유리한 경우
- CLI 도구 개발: 시작 시간이 빠르므로 사용자 체감 속도가 크게 개선된다
- 스크립트 자동화:
bun run script.ts로 TypeScript 직접 실행 - API 서버 (새 프로젝트): Bun.serve() + Elysia 또는 Hono 조합이 고성능
- 빌드 파이프라인 속도 개선:
bun install만 적용해도 CI 시간이 단축된다
Node.js가 여전히 유리한 경우
- 네이티브 애드온 의존 프로젝트:
canvas,puppeteer등 - 엔터프라이즈 환경: 장기 LTS 지원, 광범위한 운영 검증
- Next.js, Remix 등 특정 프레임워크: 내부적으로 Node.js API를 많이 사용