이 글은 누구를 위한 것인가
- Node.js 앱의 시작 시간과 처리량을 개선하고 싶은 팀
- Bun의 실제 성능과 Node.js 호환성 수준을 검토하는 개발자
- 번들러, 테스트 러너, 패키지 매니저를 단일 툴로 통합하려는 팀
들어가며
Bun은 JavaScriptCore 엔진 기반의 올인원 JS 런타임이다. Node.js 대비 시작 시간 4배 빠름, HTTP 처리량 3배 높음, 패키지 설치 10배 빠름을 주장한다. 2026년 현재 Node.js 호환성은 95% 이상이다.
이 글은 bluefoxdev.kr의 Bun 런타임 실전 가이드 를 참고하여 작성했습니다.
1. Bun vs Node.js 성능 비교
[벤치마크 (2026년 기준)]
HTTP 처리량 (간단한 JSON 응답):
Bun.serve(): ~180,000 req/s
Node.js HTTP: ~60,000 req/s
Hono on Bun: ~170,000 req/s
Express.js: ~45,000 req/s
시작 시간:
Bun: ~5ms
Node.js: ~50ms
패키지 설치 (node_modules 없는 상태):
bun install: ~0.5s
npm install: ~8s
pnpm install: ~3s
번들링 (중형 앱):
bun build: ~200ms
esbuild: ~300ms
webpack: ~5,000ms
[Bun 내장 기능]
번들러: bun build (esbuild 수준)
테스트: bun test (Jest 호환)
패키지 매니저: bun install (npm 호환)
SQLite: bun:sqlite (내장, 외부 의존성 없음)
.env 로딩: 자동 (dotenv 불필요)
TypeScript: 트랜스파일 내장 (ts-node 불필요)
[Node.js 호환성 주의사항]
__dirname, __filename: 지원
Worker Threads: 지원
Node.js crypto: 지원
일부 네이티브 애드온: 미지원 가능
node: 프로토콜 접두사: 지원
2. Bun HTTP 서버와 내장 기능 활용
// HTTP 서버 - Bun.serve()
const server = Bun.serve({
port: 3000,
async fetch(req) {
const url = new URL(req.url);
if (url.pathname === '/api/users' && req.method === 'GET') {
const users = await db.query('SELECT * FROM users').all();
return Response.json(users);
}
if (url.pathname === '/api/users' && req.method === 'POST') {
const body = await req.json();
const result = db.query('INSERT INTO users (name, email) VALUES (?, ?) RETURNING *')
.get(body.name, body.email);
return Response.json(result, { status: 201 });
}
return new Response('Not Found', { status: 404 });
},
error(error) {
return Response.json({ error: error.message }, { status: 500 });
},
});
console.log(`서버 실행: http://localhost:${server.port}`);
// 내장 SQLite - 외부 패키지 없음
import { Database } from 'bun:sqlite';
const db = new Database('app.db');
// 자동 타입 추론
db.run(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
// 준비된 쿼리 (성능 최적화)
const getUserById = db.query<{ id: number; name: string; email: string }, [number]>(
'SELECT id, name, email FROM users WHERE id = ?'
);
const user = getUserById.get(1); // 타입 안전
// 파일 I/O - Bun의 빠른 파일 API
const file = Bun.file('data.json');
const data = await file.json(); // fs 불필요
await Bun.write('output.json', JSON.stringify(data, null, 2));
// 스트리밍 파일 읽기
const stream = Bun.file('large.csv').stream();
for await (const chunk of stream) {
processChunk(chunk);
}
// .env 자동 로딩 (dotenv 불필요)
// .env 파일이 있으면 자동으로 process.env에 로드
console.log(process.env.DATABASE_URL); // 바로 사용
// WebSocket 서버
const wsServer = Bun.serve({
port: 3001,
fetch(req, server) {
if (server.upgrade(req)) return; // WebSocket 업그레이드
return new Response('WebSocket 서버', { status: 200 });
},
websocket: {
open(ws) {
console.log('클라이언트 연결');
ws.subscribe('chat'); // 채널 구독
},
message(ws, message) {
ws.publish('chat', message); // 전체 브로드캐스트
},
close(ws) {
ws.unsubscribe('chat');
},
},
});
// bun test - Jest 호환 테스트 러너
import { describe, it, expect, mock, beforeEach } from 'bun:test';
describe('UserService', () => {
let mockDb: ReturnType<typeof mock>;
beforeEach(() => {
mockDb = mock(() => ({ id: 1, name: 'Alice', email: 'alice@example.com' }));
});
it('사용자를 생성해야 한다', async () => {
const result = await createUser({ name: 'Alice', email: 'alice@example.com' });
expect(result.name).toBe('Alice');
expect(result.id).toBeNumber();
});
it('중복 이메일을 거부해야 한다', async () => {
await expect(
createUser({ name: 'Bob', email: 'alice@example.com' })
).rejects.toThrow('이미 존재하는 이메일');
});
});
// package.json 스크립트 대신 bun 직접 사용
// bun run dev → tsx 대신 bun으로 직접 실행
// bun test → jest 대신 내장 테스트 러너
// bun build src/index.ts --outdir dist → 번들링
# Node.js → Bun 마이그레이션 체크리스트
# 1. Bun 설치
curl -fsSL https://bun.sh/install | bash
# 2. 의존성 설치 (bun install은 package.json 호환)
bun install
# 3. 스크립트 실행 (ts-node/tsx 대체)
# 기존: npx ts-node src/index.ts
# Bun: bun src/index.ts
# 4. 개발 서버 (nodemon 대체)
# 기존: nodemon src/index.ts
# Bun: bun --hot src/index.ts (핫 리로드)
# 5. 호환성 확인
bun --bun src/index.ts # Bun API 우선 사용
# 6. 성능 벤치마크
bun ./benchmarks/http.ts
# Node.js 전용 패키지 확인 (native addon)
# node-gyp 의존성은 별도 확인 필요
grep -r "node-gyp\|bindings\|nan\|node-addon-api" node_modules/.bin/
마무리
Bun은 2026년 현재 실제 프로덕션에서 사용할 수 있는 수준이다. API 서버, CLI 도구, 스크립트 실행에서 즉각적인 성능 향상을 경험할 수 있다. 주의할 점은 네이티브 애드온(bcrypt, sharp 등)의 호환성이며, 이 경우 해당 패키지의 Bun 지원 여부를 먼저 확인해야 한다. 새 프로젝트라면 Bun을 기본으로 선택하고, 기존 Node.js 앱은 핵심 경로부터 점진적으로 전환하는 전략이 안전하다.