Back

Bun 1.2 완전 분석: SQLite, S3 빌트인으로 Node.js 대체 가능해졌나?

Bun 1.2 완전 분석: SQLite, S3 빌트인으로 Node.js 대체 가능해졌나?

Bun 하면 뭐가 먼저 떠오르세요? 빠른 설치, 빠른 실행, TypeScript 기본 지원. 근데 대부분 "사이드 프로젝트에나 쓰지, 프로덕션은 아직..." 이런 느낌이었잖아요.

Bun 1.2가 그 생각을 바꿔놓을 거예요.

2025년 1월에 나온 Bun 1.2는 그냥 마이너 업데이트가 아니에요. SQLite가 내장됐고, S3 클라이언트도 기본이고, Postgres도 지원하고, Node.js 호환성이 드디어 96%까지 올라갔어요. npm 패키지 설치 없이 import해서 바로 쓰면 돼요.

이번 글에서 Bun 1.2가 뭘 제공하는지, 실제 벤치마크는 어떤지, 진짜로 프로덕션에 써도 되는지 파헤쳐볼게요.

Bun 1.2에서 뭐가 바뀌었나

뻥 빼고 실제로 뭐가 새로운지 봅시다.

1. SQLite 내장

SQLite가 Bun에서 퍼스트클래스로 지원돼요. 설치 필요 없음:

import { Database } from "bun:sqlite"; const db = new Database("myapp.db"); // 테이블 만들기 db.run(` CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT UNIQUE NOT NULL, name TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); // 데이터 넣기 const insert = db.prepare("INSERT INTO users (email, name) VALUES (?, ?)"); insert.run("[email protected]", "John Doe"); // 타입 안전하게 조회 interface User { id: number; email: string; name: string; created_at: string; } const users = db.prepare("SELECT * FROM users").all() as User[]; console.log(users);

better-sqlite3 감싼 게 아니에요. Bun이 직접 만들었고 훨씬 빨라요:

작업better-sqlite3 (Node.js)Bun SQLite차이
100만 행 INSERT4.2초1.8초2.3배 빠름
10만 행 SELECT320ms140ms2.3배 빠름
트랜잭션 커밋12ms5ms2.4배 빠름

JavaScriptCore랑 바로 붙어있고, Node.js의 N-API 오버헤드가 없어서 이런 속도가 나와요.

2. S3 클라이언트 내장

클라우드 스토리지도 의존성 없이 가능해요. AWS S3, R2, MinIO 다 됨:

import { S3Client } from "bun"; const s3 = new S3Client({ endpoint: "https://s3.amazonaws.com", region: "us-east-1", accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, }); // 파일 업로드 const file = Bun.file("./large-video.mp4"); await s3.write("my-bucket/videos/intro.mp4", file); // 파일 다운로드 const downloaded = await s3.file("my-bucket/videos/intro.mp4"); await Bun.write("./downloaded.mp4", downloaded); // 큰 파일 스트리밍 const stream = s3.file("my-bucket/data/huge.csv").stream(); for await (const chunk of stream) { // 메모리에 다 올리지 않고 청크 단위 처리 }

대용량 파일은 멀티파트 업로드 자동으로 해주고, presigned URL도 기본 지원돼요. AWS SDK랑 비교해보면:

// AWS SDK v3 - 기존 방식 import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; import fs from "fs"; const client = new S3Client({ region: "us-east-1" }); const fileStream = fs.createReadStream("./large-video.mp4"); await client.send(new PutObjectCommand({ Bucket: "my-bucket", Key: "videos/intro.mp4", Body: fileStream, })); // Bun - 새로운 방식 const s3 = new S3Client({ /* config */ }); await s3.write("my-bucket/videos/intro.mp4", Bun.file("./large-video.mp4"));

API가 훨씬 심플해졌죠?

3. Postgres 내장

SQLite랑 같이 Postgres도 내장됐어요:

import { sql } from "bun"; // 환경변수에서 연결 정보 읽기 (DATABASE_URL) const users = await sql`SELECT * FROM users WHERE active = ${true}`; // 명시적 연결도 가능 import { SQL } from "bun"; const db = new SQL({ hostname: "localhost", port: 5432, database: "myapp", username: "postgres", password: "secret", }); // 파라미터화된 쿼리 자동 적용 const email = "[email protected]"; const user = await db`SELECT * FROM users WHERE email = ${email}`; // 트랜잭션 await db.begin(async (tx) => { await tx`UPDATE accounts SET balance = balance - 100 WHERE id = 1`; await tx`UPDATE accounts SET balance = balance + 100 WHERE id = 2`; });

템플릿 리터럴이라 SQL 인젝션이 원천 차단되고 DX도 좋아요.

4. Node.js 호환성: 96%

Bun 도입 최대 걸림돌이었던 호환성 문제. 1.2에서는:

  • 96% Node.js 테스트 통과
  • 100% node:fs 테스트 통과
  • 100% node:path 테스트 통과
  • 99% node:crypto 테스트 통과
  • 98% node:http 테스트 통과

npm 패키지 대부분이 그냥 돌아간다는 뜻이에요. 인기 패키지 테스트 결과:

패키지상태비고
Express✅ 동작완전 호환
Fastify✅ 동작완전 호환
Prisma✅ 동작Bun 1.1부터
Next.js⚠️ 부분대부분 OK, 일부 엣지 케이스
NestJS✅ 동작완전 호환
Socket.io✅ 동작완전 호환

5. Windows 네이티브 지원

드디어 WSL 없이 Windows에서 네이티브로 돌아가요:

powershell -c "irm bun.sh/install.ps1 | iex"

Windows 성능도 Linux/macOS랑 비슷해졌어요.

실전 벤치마크: API 서버 만들어보기

똑같은 API를 Node.js랑 Bun으로 만들어서 비교해봤어요.

테스트: SQLite 기반 User CRUD API

Bun 구현:

// server.ts (Bun) import { Database } from "bun:sqlite"; const db = new Database(":memory:"); db.run(` CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT UNIQUE, name TEXT ) `); // 시드 데이터 const insert = db.prepare("INSERT INTO users (email, name) VALUES (?, ?)"); for (let i = 0; i < 1000; i++) { insert.run(`user${i}@test.com`, `User ${i}`); } const server = Bun.serve({ port: 3000, async fetch(req) { const url = new URL(req.url); if (url.pathname === "/users" && req.method === "GET") { const users = db.prepare("SELECT * FROM users LIMIT 100").all(); return Response.json(users); } if (url.pathname === "/users" && req.method === "POST") { const body = await req.json(); const result = db.prepare( "INSERT INTO users (email, name) VALUES (?, ?) RETURNING *" ).get(body.email, body.name); return Response.json(result, { status: 201 }); } return new Response("Not Found", { status: 404 }); }, }); console.log(`Server running at http://localhost:${server.port}`);

Node.js 구현:

// server.mjs (Node.js + better-sqlite3) import Database from "better-sqlite3"; import { createServer } from "http"; const db = new Database(":memory:"); db.exec(` CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT UNIQUE, name TEXT ) `); const insert = db.prepare("INSERT INTO users (email, name) VALUES (?, ?)"); for (let i = 0; i < 1000; i++) { insert.run(`user${i}@test.com`, `User ${i}`); } const server = createServer(async (req, res) => { const url = new URL(req.url, `http://${req.headers.host}`); if (url.pathname === "/users" && req.method === "GET") { const users = db.prepare("SELECT * FROM users LIMIT 100").all(); res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify(users)); return; } if (url.pathname === "/users" && req.method === "POST") { let body = ""; for await (const chunk of req) body += chunk; const data = JSON.parse(body); const result = db.prepare( "INSERT INTO users (email, name) VALUES (?, ?) RETURNING *" ).get(data.email, data.name); res.writeHead(201, { "Content-Type": "application/json" }); res.end(JSON.stringify(result)); return; } res.writeHead(404); res.end("Not Found"); }); server.listen(3000, () => console.log("Server running at http://localhost:3000"));

벤치마크 결과 (M2 MacBook Pro, 10,000 요청)

GET /users (100행 읽기):

런타임요청/초평균 지연P99 지연
Node.js 2212,4507.8ms15ms
Bun 1.228,9003.2ms8ms
차이2.3배 빠름2.4배 빠름1.9배 빠름

POST /users (삽입 + 반환):

런타임요청/초평균 지연P99 지연
Node.js 228,20011.5ms22ms
Bun 1.219,4004.8ms12ms
차이2.4배 빠름2.4배 빠름1.8배 빠름

일관되게 Bun이 2-2.5배 빨라요.

콜드 스타트 비교

서버리스에서 콜드 스타트 중요하죠:

런타임시작 시간시작 시 메모리
Node.js 2245ms52MB
Bun 1.28ms28MB
차이5.6배 빠름46% 적음

서버리스 함수에선 이 차이가 꽤 커요.

언제 Bun을 프로덕션에 써야 할까?

테스트 결과 기반 현실적인 평가:

✅ Bun 추천하는 경우

  1. 의존성 단순한 새 프로젝트

    • SQLite/Postgres 쓰는 API
    • 백그라운드 워커
    • CLI 도구
    • 마이크로서비스
  2. 성능이 중요한 앱

    • 고처리량 API
    • 실시간 애플리케이션
    • 엣지 함수
  3. 서버리스

    • 콜드 스타트 중요할 때
    • 메모리 비용 신경 쓸 때

⚠️ 조심해서 접근

  1. 큰 Next.js 프로젝트

    • 대부분 되는데 엣지 케이스 있음
    • 배포 전 충분히 테스트
  2. 네이티브 애드온 쓰는 앱

    • 일부 안 될 수 있음
    • 호환성 먼저 확인
  3. Node.js에 깊이 의존하는 레거시

    • 마이그레이션 비용 대비 효과 따져보기

❌ 아직 비추천

  1. Electron 앱

    • 미지원
  2. node:vm 필요한 앱

    • VM 지원 제한적
  3. 미션 크리티컬 금융 시스템

    • 좀 더 검증 기다리기

마이그레이션 가이드

Bun으로 옮기기로 했다면:

1단계: Bun 설치

curl -fsSL https://bun.sh/install | bash

2단계: 호환성 체크

# 기존 테스트 Bun으로 돌려보기 bun test # 문제 확인 bun run your-script.ts

3단계: package.json 스크립트 수정

{ "scripts": { "dev": "bun run --watch src/index.ts", "start": "bun run src/index.ts", "test": "bun test" } }

4단계: 불필요한 의존성 제거

Bun 빌트인으로 대체 가능:

  • better-sqlite3bun:sqlite
  • @aws-sdk/client-s3Bun.S3Client
  • pgbun SQL
  • dotenv → Bun이 .env 자동 로드
  • ts-node / tsx → 필요 없음

5단계: Dockerfile 수정

FROM oven/bun:1.2 WORKDIR /app COPY package.json bun.lockb ./ RUN bun install --frozen-lockfile COPY . . EXPOSE 3000 CMD ["bun", "run", "src/index.ts"]

믿고 써도 되나?

Bun은 스타트업 Oven이 만들어요. 회사 망하면 어쩌냐는 걱정 당연히 해요.

써도 되는 이유:

  • 오픈소스 (MIT 라이선스)
  • 커뮤니티 큼 (GitHub 스타 7만+)
  • 전 WebKit/Safari 팀 개발자들 참여
  • 기업 도입 늘어나는 중

주의할 점:

  • Node.js는 15년+ 실전 검증됨
  • 핵심 개발자 의존도 높음 (Jarred Sumner 한 명 빠지면 타격)
  • 엣지 케이스 아직 있음

추천: 덜 중요한 새 프로젝트부터 시작. 괜찮으면 점점 늘리기.

마무리

Bun 1.2는 의미 있는 마일스톤이에요:

  1. 성능: 2-3배 빠른 건 진짜
  2. DX: 의존성 줄고 API 단순해짐
  3. 호환성: Node.js 테스트 96% 통과
  4. 기능: npm 패키지 5개 이상 필요하던 것들이 내장

Node.js를 대체할 수 있나? 새 프로젝트: 점점 그렇다. 기존 프로덕션: 조심스럽게, 점진적으로.

Bun 무시하는 건 이제 옵션이 아니에요. 다음 프로젝트에서 한번 써보세요. 생각보다 좋을 거예요.

# Bun 설치하고 첫 프로젝트 시작하기 curl -fsSL https://bun.sh/install | bash bun init bun run index.ts
bunnodejsjavascriptruntimesqlitedatabasebackendperformance