- Published on
Bun 회고 2026 — 1.0 GA의 약속 vs 현실, 런타임·번들러·패키지 매니저·테스트 러너·셸까지 (Bun 2 시점에서 본 솔직한 평가)
- Authors

- Name
- Youngju Kim
- @fjvbn20031
프롤로그 — 2023년의 약속, 2026년의 청구서
2023년 9월, Bun 1.0이 GA로 나왔을 때의 분위기를 기억한다. 데모는 인상적이었다. bun install은 npm install보다 25배 빨랐고, bun test는 Jest보다 13배 빨랐고, bun run은 Node보다 4배 빨랐다. Twitter에는 그 차트들이 도배됐다. "이제 Node는 끝났다"는 의견과 "또 다른 Yarn 1.0 모먼트일 뿐"이라는 의견이 반반이었다.
2026년 5월. 청구서를 받을 시간이다.
Bun은 약속을 절반쯤 지켰다. 그러나 그 절반은 우리가 기대했던 절반과는 다른 절반이다.
bun install은 정말 빠르다 — 약속대로. bun test도 빠르다. Bun.serve도 진짜로 가볍고 빠르다. 그러나 운영 환경에서 Node를 대체했다는 시나리오는 흔하지 않다. 2026년 중반의 진짜 그림은 이렇다:
- 개발 도구로서의 Bun은 광범위하게 쓰인다 —
bun install,bun test, Bun shell. CI 시간이 절반으로 준다. - 런타임으로서의 Bun은 여전히 niche다 — Bun.serve로 만든 작은 API 게이트웨이, Edge 워커, 내부 도구. 대규모 모놀리스가 Bun으로 갈아탔다는 얘기는 거의 없다.
- Node 22+가 의외로 잘했다 —
node --experimental-strip-types,node:test,node --watch, native fetch. Node가 Bun이 던진 공을 받아서 자기 코트에서 답했다.
이 글은 1.0 GA 이후 2년 반을 honest retrospective로 정리한다. 무엇이 over-deliver했고, 무엇이 broken promise였고, 어느 자리에 Bun이 맞고 어느 자리에 Node가 여전히 옳은지.
1장 · Bun 런타임 — Zig + JavaScriptCore의 약속
약속
Bun은 시작부터 세 가지 베팅을 했다.
- Zig로 다시 쓴다 — V8 위에서 도는 Node와 달리, 런타임 자체를 Zig로 작성해 시작 시간과 메모리 풋프린트를 줄인다.
- V8이 아니라 JavaScriptCore(JSC) — Safari가 쓰는 엔진. 시작 시간과 메모리에서 V8보다 가볍다는 일반적인 평가.
- Node API 호환 —
fs,http,path,crypto등 Node의 모듈을 그대로 지원한다. 즉, "Node 코드를 그대로 갖다 붙여도 돈다"는 약속.
이 세 가지 조합으로 Bun은 "Node를 갈아낼 수 있는 드롭인 대체"를 노렸다.
현실 — 런타임 속도
벤치마크는 일관되게 Bun이 Node보다 빠르다고 말한다. 그러나 어디서 빠른가가 중요하다.
시작 시간 (cold start, "console.log"):
Node 22: 35~60ms
Bun 1.2: 10~20ms
Deno 2: 25~40ms
HTTP 처리량 (단순 에코, single core):
Node 22 (http): 80k req/s
Node 22 (uWebSockets) 280k req/s
Bun.serve: 250~310k req/s
Hono on Bun: 220~280k req/s
Deno serve: 200~240k req/s
SQLite 쿼리 (1M rows, simple select):
better-sqlite3 (Node): 4.2s
bun:sqlite: 1.6s
빠르긴 하다. 그런데 차이의 모양을 보자.
- 시작 시간 2~3x: AWS Lambda 같은 cold-start 민감 워크로드에서 의미 있다. 일반 long-running 서버에서는 무의미하다.
- HTTP 처리량: Node가 기본
http모듈을 쓰지 않고 uWebSockets나 fastify를 쓰면 그 차이가 크게 좁아진다. 공정한 비교는 "기본 vs 기본"이 아니라 "최적화된 vs 최적화된"이다. - SQLite: 진짜 차이가 큰 영역.
bun:sqlite는 FFI로 SQLite를 직접 호출해서 N+1을 깎는 구조. 이건 분명한 win.
핵심: Bun이 빠른 이유는 "JS 실행이 빠르다"가 아니라 "I/O와 native 인터페이스가 가볍다"는 쪽이다. 그래서 CPU-bound JS 코드에서는 Node와 큰 차이가 없는 경우가 많다.
현실 — Node 호환성
Bun은 1.0 시점에 "Node 호환률 90%+"를 광고했다. 2026년 현재의 체감은 이렇다.
| 영역 | 호환 상태 | 사용 가능? |
|---|---|---|
fs, path, os, util | 거의 완벽 | 예 |
http, https, url | 거의 완벽 | 예 |
crypto | 대부분 OK, 일부 legacy API에서 차이 | 예 |
child_process | 대부분 OK | 예 |
worker_threads | OK | 예 |
cluster | 부분 지원, edge case에서 차이 | 주의 |
| Native addons (N-API) | 광범위 지원, 일부 미지원 모듈 존재 | 예 (대부분) |
vm 모듈 | 일부 누락 (특정 옵션) | 주의 |
inspector (debugger 프로토콜) | 부분 지원 | 주의 |
async_hooks | 부분 지원 — APM 도구 호환 이슈 | 주의 |
process.binding 내부 API | 미지원 (의도적) | 아니오 |
작은 서비스에서는 거의 문제가 없다. 그러나 APM(Application Performance Monitoring) 에이전트, OpenTelemetry auto-instrumentation, legacy native addon 같은 곳에서 여전히 깨진다. New Relic, Datadog 등 메이저 APM은 2025년 말이 되어서야 Bun을 공식 지원했고, 일부 instrumentation은 여전히 partial이다.
"Node 코드를 그대로 옮겨도 돈다"는 작은 코드베이스에서는 사실이고, 큰 코드베이스에서는 절반쯤 사실이다. 깨지는 것은 비즈니스 코드가 아니라 **주변 인프라(tracing, profiler, debugger)**다.
2장 · bun install — 가장 명확한 win
여러 영역 중 가장 의심의 여지가 적은 win은 bun install이다.
벤치마크
hot cache, mid-size repo (약 800개 deps):
npm install: 18s
yarn install: 9s
pnpm install: 5s
bun install: 1.6s
cold cache, 같은 repo:
npm install: 65s
yarn install: 35s
pnpm install: 18s
bun install: 7s
bun install은 Rust로 쓰인 cargo나 Go의 module resolver 수준의 속도를 JS 생태계에 가져왔다. 이건 dev 경험의 진짜 차이다 — CI에서 bun install은 매번 5~10초로 끝나고, 로컬에서 lockfile이 변경됐을 때 다시 깔리는 시간이 사람의 인내심을 시험하지 않는다.
lockfile 전쟁의 짧은 역사
처음 1.0이 나왔을 때 bun.lockb는 바이너리 lockfile이었다. 빠른 파싱이 목표였지만, PR 리뷰에서 diff를 볼 수 없다는 큰 문제가 있었다. 2024~2025년에 걸쳐 커뮤니티가 강하게 항의했고, Bun은 결국 bun.lock(텍스트, JSON-superset 형식)을 도입했다. 2026년 현재, 새 프로젝트는 텍스트 lockfile이 디폴트다. 옛 프로젝트는 bun.lockb를 그대로 쓰는 경우도 있다.
교훈: DX 베팅에서 한쪽 면(속도)만 보고 다른 면(diff 가능성, code review)을 무시하면 커뮤니티가 돌려보낸다. Bun 팀은 이걸 인정하고 빠르게 수정했고, 그건 평가받을 만하다.
어디서 흔히 쓰이나
bun install은 런타임을 Bun으로 바꾸지 않고도 도입할 수 있다. CI에서 bun install + npm run build/node server.js 조합이 매우 흔하다.
- Vercel·Netlify 같은 platform은
bun install을 빌드 단계에서 옵션으로 제공. - Next.js, SvelteKit, Astro 등 메이저 프레임워크는
bun install로 dep을 깔아도 정상 빌드. - Docker 이미지에서
oven/bun베이스 + Node runtime 조합으로 빌드 시간 절반.
가장 안전한 first-step Bun 도입 — 그리고 가장 흔한 도입 — 이 bun install이다.
3장 · bun test — 빠르지만 채택률은 mixed
약속
bun test는 Jest API 호환(혹은 가까운)을 표방하며, Jest보다 훨씬 빠르고, transform/transpile 설정 없이 TypeScript를 그대로 돌린다.
현실
벤치마크상 Bun test는 Jest보다 310x 빠르다. Vitest와는 13x 차이 (Vitest가 빠를 때도 있고 Bun이 빠를 때도 있음, suite 모양에 따라). 그러나 채택률은 mixed다.
| 도구 | 2026 mid 채택률 (느낌) | 강점 |
|---|---|---|
| Jest | 여전히 1위 (legacy 무게가 큼) | 생태계, 플러그인, 안정성 |
| Vitest | 빠르게 2위 추월 중 | Vite 통합, ESM-native, watch UX |
| Bun test | 3위, 신규 프로젝트에 흔함 | 속도, 무설정 TS |
Node test (node:test) | 점점 늘어남 | dependency 없음, official |
Bun test가 메인 stack을 차지하지 못한 이유는 몇 가지다.
- Jest의 plugin/ecosystem: snapshot serializer, custom matchers, jest-axe, jest-extended 등 수많은 플러그인. Bun test에 다 옮겨오기까지 시간이 걸렸다.
- mock 시스템의 차이:
jest.mock()호환은 점점 좋아지고 있지만 edge case에서 차이가 있다. - monorepo 통합: Turborepo·Nx 같은 monorepo 도구의 Jest/Vitest 통합이 더 매끄럽다.
Bun test는 신규 단일 패키지 프로젝트에서 가장 자주 쓰인다. 큰 monorepo에서는 여전히 Vitest 우세.
4장 · Bun bundler — esbuild의 자리에 도전했지만
약속
Bun에는 내장 bundler가 있다 — bun build. esbuild에 영감을 받았다고 공언하고, 더 빠르다고 광고했다.
현실 — bundler 풍경 2026
2026년의 JS 번들러 풍경은 1.0 시점보다 훨씬 복잡해졌다.
| 번들러 | 위치 | 특징 |
|---|---|---|
| esbuild | 여전히 dominant | 가장 작은 표면적, 가장 안정 |
| Vite (Rollup) | dev server 표준 | HMR, plugin 생태계 |
| Rolldown | Vite의 다음 단계 | Rust 기반, esbuild보다 빠를 수 있음 |
| Turbopack | Next.js의 default | Vercel 베팅, Webpack 후속 |
| Bun bundler | niche, 주로 Bun 생태계 안 | 속도, 무설정 TS, Bun runtime과 통합 |
| swcpack | swc의 bundler 분기 | Vercel 전 generation |
Bun bundler는 빠르긴 빠르다. 그러나 plugin 생태계가 esbuild나 Rollup보다 한참 작다. PostCSS·SVGR·MDX 같은 영역에서 esbuild plugin을 그대로 못 쓰는 경우가 많다 (Bun이 esbuild의 plugin API를 호환하려 노력하긴 한다).
Bun bundler는 Bun 생태계 안의 default로는 합리적이다. Bun.serve로 만든 작은 SPA, Bun-only CLI 도구의 dist. 그러나 esbuild를 대체하는 industry-wide standard로 자리잡지는 못했다. 그 자리는 Rolldown이 노리고 있다.
5장 · Bun.serve() — 웹 프레임워크 자리의 싸움
약속
Bun.serve는 "express 없이도 빠르게 HTTP 서버 짤 수 있다"는 약속이다. Fastify 수준의 처리량을 표준 라이브러리에서.
코드 — 30초로 보는 Bun.serve
// server.ts
import { serve } from "bun";
serve({
port: 3000,
async fetch(req) {
const url = new URL(req.url);
if (url.pathname === "/hello") {
return new Response("hi");
}
if (url.pathname === "/echo" && req.method === "POST") {
const body = await req.json();
return Response.json({ ok: true, body });
}
return new Response("not found", { status: 404 });
},
});
console.log("listening on http://localhost:3000");
Web standard Request/Response API를 쓰는 게 핵심이다. Cloudflare Workers·Deno와 같은 패러다임 — Bun을 거기 줄 세웠다.
현실 — Hono의 부상
Bun.serve는 빠르다. 그러나 그 위에 router·middleware·validation을 얹어야 진짜 앱이 된다. 2026년의 사실상의 표준은 Hono다.
// hono on bun
import { Hono } from "hono";
const app = new Hono();
app.get("/hello", (c) => c.text("hi"));
app.post("/users", async (c) => {
const body = await c.req.json();
return c.json({ id: 1, ...body });
});
export default { fetch: app.fetch, port: 3000 };
Hono는 Bun, Deno, Cloudflare Workers, Vercel Edge, Node 모두에서 같은 코드로 돈다. 즉, Hono를 쓰면 runtime 선택을 미루거나 바꿀 수 있다. 이게 큰 셀링 포인트다. Bun.serve에 직접 묶이는 코드보다 Hono+Bun 조합이 운영적으로 더 안전하다.
Bun.serve는 좋다. 그러나 그 위에서 실제로 빌드할 때 사람들이 Hono를 더 자주 고른다. Bun은 Hono를 부정하지 않는다 — Hono를 Bun.serve의 정식 라우터로 추천하는 분위기.
6장 · bun:sqlite — 가장 over-deliver한 것
여러 기능 중 가장 기대 이상으로 좋았던 것을 하나만 꼽으라면 bun:sqlite다.
왜 좋은가
Node에서 SQLite를 쓰려면 better-sqlite3(native addon) 또는 sqlite3(async)를 깐다. 둘 다 설치 단계에서 native build를 거치고, 플랫폼 간 호환성 문제가 종종 생긴다. bun:sqlite는 런타임이 SQLite를 직접 가지고 있다 — 설치 단계 build 없음, SDK처럼 import해서 바로 쓴다.
코드
// sqlite.ts
import { Database } from "bun:sqlite";
const db = new Database("app.db");
db.run(`
CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
created_at INTEGER NOT NULL
)
`);
const insert = db.prepare(
"INSERT INTO posts (title, created_at) VALUES (?, ?)"
);
const tx = db.transaction((rows: { title: string; ts: number }[]) => {
for (const r of rows) insert.run(r.title, r.ts);
});
tx([
{ title: "first", ts: Date.now() },
{ title: "second", ts: Date.now() },
]);
const recent = db
.query("SELECT id, title FROM posts ORDER BY id DESC LIMIT 10")
.all() as { id: number; title: string }[];
console.log(recent);
prepared statement, transaction, named parameter — 모두 동기 API. Bun과 SQLite가 한 프로세스 안에 같이 있어서 FFI 비용이 없다.
어디서 쓰나
- 로컬 데이터 캐시 — CLI 도구의 메타데이터 저장, 작은 서비스의 임시 저장소.
- embedded analytics — 작은 보드 디스플레이, 미니 BI.
- 테스트 DB — Postgres 대신 in-memory SQLite로 통합 테스트.
- 에이전트의 메모리 — AI 에이전트가 자기 컨텍스트/메모리를 SQLite에 저장하는 패턴이 흔하다.
bun:sqlite는 Bun을 "다음 세대 scripting 환경"으로 만든다. Python의sqlite3표준 라이브러리 자리를 JS 생태계에 가져왔다.
7장 · Bun shell ($) — 약속 이상이었던 또 하나
약속
zx(Google의 JS 셸 도구)에 영감을 받은, 타입 안전한 셸 명령어. 단, zx는 Node 위에 서드파티로 도는 반면 Bun shell은 런타임에 내장.
코드 — pipeline 예시
// shell.ts
import { $ } from "bun";
const files = await $`ls -1 src`.text();
console.log(files);
// 파이프와 redirect
const wc = await $`cat package.json | wc -l`.text();
console.log("lines in package.json:", wc.trim());
// 안전한 변수 보간 (shell injection 안전)
const target = "components";
await $`mkdir -p dist/${target}`;
// 실패 시 throw
try {
await $`exit 1`;
} catch (e) {
console.log("caught exit code:", e.exitCode);
}
// 환경 변수
const home = (await $`echo $HOME`.text()).trim();
console.log("home:", home);
핵심은 두 가지다.
- shell injection 안전성 —
${target}같은 JS interpolation은 자동 escape된다.os.system(...)류의 잘못된 패턴이 처음부터 막힌다. - TypeScript 통합 — IDE가 자동 완성과 타입 정보를 제공.
현실 — 누가 쓰나
Bun shell은 빌드 스크립트, dev tool의 사실상 표준 자리로 빠르게 올라왔다. 옛날에 package.json의 "scripts"에 길게 적던 명령을 scripts/build.ts로 옮기고, Bun shell로 짠다.
- make의 자리를 일부 가져갔다.
- shell script의 가독성 문제(quoting hell, special character escape)를 해결.
- cross-platform — Bun shell은 Windows에서도 같은 코드로 동작 (POSIX 흉내).
Bun shell은 Bun을 안 쓰는 사람도 Bun을 깔게 만드는 기능이다. shell script가 길고 fragile해질 때,
bun + $이 나타난다.
8장 · bunfig.toml, executable bundles, 그 외
bunfig.toml
Bun의 설정 파일. registry, install behavior, test runner 옵션, JSX 변환 옵션 등을 한 파일에.
# bunfig.toml
[install]
registry = "https://registry.npmjs.org/"
production = false
[install.cache]
dir = "~/.bun/install/cache"
[test]
preload = ["./test/setup.ts"]
[run]
silent = false
[loader]
".ts" = "tsx"
package.json의 일부 영역(scripts, deps)을 침범하지 않고, Bun 특화 설정만 모은다. 좋은 분리.
Executable bundles — bun build --compile
bun build --compile --target=bun-linux-x64 ./cli.ts --outfile mycli
JavaScript 코드를 단일 실행 파일로 패키징. Bun 런타임이 그 안에 같이 들어간다. 결과 파일 ~70MB 정도, 그러나 의존성 없이 실행 가능.
비교 대상:
- Node 22:
node --experimental-sea-config(Single Executable Application) — 비슷한 기능, 더 manual. - Deno 2:
deno compile— 안정적인 동등 기능. - pkg (vercel): legacy 도구, 더 이상 활발하지 않음.
Bun의 --compile은 빠른 시작(Bun의 cold start advantage가 적용)과 무의존 배포를 한 번에 준다. CLI 도구 만드는 사람들이 자주 쓴다.
그 외
- Bun watch (
bun --watch) — Node의--watch와 동등, 더 빠른 재시작. - Bun macros — 빌드 시점에 JS를 실행해서 결과를 인라인. 정적 데이터 패치.
- Bun lockfile auditing — 보안 advisory 통합.
9장 · Node 22+의 반격 — Bun이 던진 공을 Node가 받았다
Bun의 가장 큰 기여 중 하나는 Node의 진화를 가속화한 것이다. 2023년 1.0 시점에 Node가 "느리고 옛날 짜고 무거운" 이미지였다면, 2026년의 Node는 진짜로 빠르고 modern해졌다. 일부는 Bun이 노린 약점을 직접 막은 것이다.
| Bun이 자랑한 것 | Node의 답 |
|---|---|
| 무설정 TS | node --experimental-strip-types (Node 22) → Node 24에서 stable. .ts 파일을 직접 실행. |
| 내장 test runner | node:test 모듈 + node --test. 2024년 이후 stable, mock 지원도 들어옴. |
| native fetch | Node 18부터 stable. 더 이상 node-fetch 안 깔아도 됨. |
| watch mode | node --watch. nodemon 안 써도 됨. |
| 환경변수 파일 | node --env-file .env. dotenv 안 써도 됨. |
| Single executable app | node --experimental-sea-config. |
| 코어 모듈 import | node:fs, node:path prefix. |
Bun의 가장 큰 영향은 "Bun을 깔게 만든 것"이 아니라, "Node를 자극해서 Node가 좋아지게 만든 것"이다. 모든 JS 개발자가 그 혜택을 본다, Bun을 쓰지 않더라도.
Node 22+는 cold start가 여전히 Bun보다 느리고, install 속도는 npm이라 한참 느리지만, dev 경험의 격차는 극적으로 좁혀졌다.
10장 · Deno 2와의 비교 — Node 호환 모드를 푼 또 다른 옵션
Deno도 2024년 Deno 2를 출시하며 큰 방향 전환을 했다. Node 호환 모드를 적극적으로 켜고, package.json을 native하게 지원하고, npm 모듈을 import 가능하게 만들었다.
2026년 시점에서 Bun vs Deno 2를 단순화하면:
| 축 | Bun | Deno 2 |
|---|---|---|
| 런타임 속도 | 가장 빠름 | Bun보다 약간 느리지만 충분 |
| Node 호환 | 광범위, 일부 영역 약함 | Deno 2에서 크게 개선, 안정적 |
| 권한 모델 | Node와 같은 "모든 권한" | 기본 deny — 명시적 permission flag |
| 표준 라이브러리 | 비교적 작음 | 풍부, 잘 정리됨 (@std) |
| TS 지원 | 무설정, 빠름 | 무설정, type check도 함 |
| 보안 stance | 빠름 우선 | 안전 우선 (sandboxing) |
| 패키지 매니저 | bun install | deno install (jsr.io 또는 npm:) |
Deno 2는 security 우선의 stance, Bun은 속도 우선의 stance. 그러나 실제 사용 시 둘 다 점점 비슷해지고 있다 — Node 호환은 양쪽 다 가능. Deno의 --allow-net, --allow-read 같은 권한 flag는 production 보안에서 차별점이 있지만, dev 경험에서는 마찰을 추가한다.
사용자의 운영 환경이 고보안 prod (예: 정부 시스템, 금융) 이라면 Deno 2가 유리. 개발 도구/CI/일반 웹 서비스라면 Bun이 dev 경험에서 우세. 회사 전체 표준 런타임이라면 여전히 Node가 default.
11장 · Broken promises — 약속을 지키지 못한 영역
이 글의 핵심 절. 어디서 Bun이 약속을 지키지 못했나.
11.1 "Node를 drop-in 대체"라는 narrative
광고 문구는 그렇게 시작했다. 그러나 실제로는 legacy enterprise 코드베이스에서 native addon, APM agent, custom debugger, complex cluster 사용, 등으로 Bun이 못 도는 경우가 종종 있다. "drop-in"이 가능한 건 작은 코드베이스다.
11.2 Windows 지원
1.0 시점에 Windows 지원은 가장 큰 broken promise였다. 처음 1년은 Linux/macOS만 본격 지원했고, Windows는 WSL을 권장했다. 2024년 후반부터 native Windows 지원이 추가됐지만, 2026년 mid 시점에도 일부 모듈은 Windows에서 edge case가 있다.
11.3 안정성 (1.0 직후의 시기)
1.0 GA 직후 6개월은 production에서 "이상한 메모리 누수", "OOM kill", "race condition" 등의 보고가 적지 않았다. 회사 단위로 운영하던 곳들이 Node로 되돌아간 사례가 있다. 2025년 들어 안정성은 크게 좋아졌지만, 첫 GA의 충격은 평판에 영구적인 흔적을 남겼다.
11.4 ecosystem maturity (관측성·monitoring)
Bun의 약한 곳: APM agent의 instrumentation. New Relic·Datadog·Dynatrace 등 메이저 APM이 Node를 위해 쌓아온 deep instrumentation을 Bun에서 똑같이 받기까지 2년 이상 걸렸다. 이건 운영 팀이 Bun을 채택하지 못하게 만드는 큰 이유다 — "보이지 않는 production은 production이 아니다".
11.5 가끔 깨지는 Node API
fs.readFile의 callback 시그니처, process.binding의 내부 의존, worker_threads의 일부 edge case — 점점 좁아지지만 0이 되지 않은 차이들. 큰 라이브러리(예: TypeScript 컴파일러 일부 path)가 Bun에서만 살짝 다르게 도는 경우가 있다.
12장 · Over-delivered — 약속 이상이었던 영역
균형을 위해, Bun이 기대 이상으로 잘한 것들도 정리한다.
12.1 Bun shell
위에서 다뤘다. 9장에 적은 대로, Bun shell은 본인 약속을 넘어 산업 default가 된 도구다.
12.2 bun install 속도와 안정성
처음 광고된 25x는 측정 시나리오에 따라 달랐지만, 일관되게 빠른 install은 약속을 잘 지켰다. cold cache, hot cache, lockfile diff 같은 작업이 다 합리적인 속도.
12.3 bun:sqlite
6장에서 다뤘다. 약속에 없던 기능이지만 만들어서 좋은 결과.
12.4 cold start
Lambda·Cloudflare Workers 같은 serverless 환경에서 Bun의 cold start advantage가 운영적으로 의미 있는 차이를 만들었다. 처음 광고 때보다 더 큰 use case가 됐다.
12.5 Bun 팀의 응답성
issue가 보고되면 빠르게 반응. lockfile 형식 전환, Windows 지원, Node API 추가 — 커뮤니티 피드백을 진지하게 반영했다. 이건 평가받을 만하다.
13장 · 누가 production에서 Bun을 쓰나 — 2026 mid 스냅숏
운영에서 Bun을 본격 채택한 회사들의 패턴.
케이스 A — 작은 API 게이트웨이 / Edge function
- fly.io 위의 작은 Bun.serve 인스턴스로 라우팅·인증·rate limit만 처리.
- Cloudflare Workers는 Bun이 아니라 자체 V8 isolate를 쓰지만, 로컬 dev에서 Wrangler 대신 Bun.serve로 mock 서버를 띄우는 패턴이 흔하다.
케이스 B — CLI 도구
- Bun으로 CLI를 만들고,
bun build --compile로 단일 실행 파일로 배포. 사용자는 Bun을 깔지 않아도 됨. - Prisma 같은 일부 CLI가 Bun으로 일부 컴포넌트를 작성.
케이스 C — 내부 도구·dev tool
- 회사 내 dashboard, deploy 자동화, CI helper. Bun.serve +
bun:sqlite로 만든 작은 운영 도구가 매우 흔하다.
케이스 D — AI 에이전트 런타임
- AI 에이전트의 sandbox 런타임으로 Bun을 쓰는 패턴이 증가. 빠른 cold start + bun:sqlite로 메모리 + Bun shell로 도구 실행 조합. e2b·Modal 등 일부 AI infra에서 Bun runner 옵션을 제공.
케이스 E — 매우 적게 — 대규모 모놀리스
- 거의 없다. 대규모 trad. 모놀리스가 Bun으로 갈아탔다는 공개 사례는 손에 꼽는다. 위험 대비 보상이 매력적이지 않고, APM·debugger 생태계의 압박이 크다.
명시적으로 언급된 사례 (공개 글 기준)
- Vercel: 자사 일부 빌드 도구, edge function의 일부 워크플로우에서 Bun을 채택.
- Mintlify: 문서 빌더 일부에서 Bun.
- Codeium / Replit / Glitch: 사용자 실행 환경의 일부 옵션으로 Bun.
- 다수의 startup: 초기 API의 단일 인스턴스로 Bun.serve+Hono.
14장 · 의사결정 — 어디서 Bun이 맞고, 어디서 Node가 맞나
Honest take.
Bun이 맞는 곳
- CI 속도가 중요한 dev 작업 —
bun install+bun test만으로도 의미 있는 win. - CLI 도구 —
bun build --compile로 단일 파일 배포, 빠른 시작. - Edge/serverless — cold start 이득.
- scripting / dev tooling — Bun shell.
- SQLite 헤비한 작은 서비스 —
bun:sqlite의 성능. - 새 프로젝트, 외부 의존성 적음 — 호환 이슈 만나기 어려움.
Node가 여전히 맞는 곳
- 대규모 enterprise 모놀리스 — APM, custom debugger, native addon ecosystem 압도적.
- legacy 코드베이스의 운영 안정성 — 변경 위험이 보상보다 큼.
- deep observability가 필수인 production — Datadog/NR auto-instrumentation의 완성도.
- regulatory가 까다로운 환경 — Node가 audit·CVE 채널이 잘 정비됨.
- 회사 표준 런타임 — 사람을 뽑고 가르치기 쉬움.
Deno 2가 맞는 곳
- 고보안 환경 — permission model이 운영적으로 의미 있는 곳.
- 표준 라이브러리 중심의 개발 —
@std의 안정성. - 새 프로젝트지만 Node 호환은 원함 — Deno 2의 npm compat이 잘 됨.
세 런타임은 더 이상 zero-sum이 아니다. 한 회사 안에서 Bun (dev tooling/CI/CLI), Node (메인 서비스), Deno (고보안 부분)을 섞어 쓰는 경우가 늘고 있다. "어느 하나가 다 이긴다"는 narrative는 2026년에 더 이상 통하지 않는다.
에필로그 — 약속, 청구서, 그리고 다음 라운드
Bun 1.0 GA에서 2년 반. 정리하자면:
Bun은 "Node를 한 번에 갈아내는" 약속을 지키지 못했다. 그러나 "JS 생태계를 빠르게 만드는" 약속은 (Bun 안에서, 그리고 Node에 자극을 줘서) 지켰다. 그 결과 모든 JS 개발자가 더 좋은 도구를 쓰게 됐다 — Bun을 채택하든 안 하든.
기억할 점:
- Bun = 런타임이 아니라 toolkit으로 생각하는 사람이 만족도가 높다.
bun install,bun test, Bun shell,bun build --compile을 각각 골라 쓰고, 런타임 채택은 천천히. - Node 22+는 진짜 좋아졌다. "옛날 Node"의 인상을 가지고 있다면 한 번 다시 보자.
- Deno 2는 잊지 마라. 보안/표준 중심의 운영에 적합한 옵션.
- APM 호환은 여전히 한 발 늦다. production 갈 거면 미리 확인.
- Windows는 점점 좋아지지만 1급 시민이 된 지는 얼마 안 됐다.
채택 체크리스트 (Bun을 도입하기 전)
- 우리 APM (NR/DD/Sentry/...)이 Bun을 공식 지원하나? instrumentation은 어느 수준인가?
- 우리가 의존하는 native addon (sharp, node-canvas, ...)이 Bun에서 도나?
- 우리 CI가 Bun을 빌드 단계에서 받을 수 있나? Docker base image는?
- 우리 사람들이 Bun 디버깅에 적응할 시간이 있나? (Chrome DevTools 프로토콜 호환의 한계 이해)
- 어디서 Bun을 도입할 건가? (단계: lockfile만 → install만 → test/scripts → CLI → 작은 서비스 → 메인 서비스)
- rollback 시나리오는? Bun→Node 되돌리기 비용은?
흔한 anti-pattern
- "Node 코드를 그대로 Bun으로 배포"하고 비기능 요구사항(관측성)을 잊는다.
- CI 속도 개선이 매력적이라 production 런타임까지 한 번에 바꾼다. 둘은 분리할 수 있고, 분리해야 안전하다.
- Bun shell을 너무 무겁게 쓴다 — 한 줄 명령은 그냥
child_process.spawnSync도 OK. bun:sqlite를 production primary DB로 쓴다. SQLite는 어디까지나 단일 노드 데이터 — Postgres 자리에 두지 마라.- 벤치마크 차트를 그대로 믿는다. 본인 워크로드에서 측정해보자. "1k qps에서 빠른 게 100k qps에서도 빠른가"는 다른 질문이다.
다음 글 예고
- "Hono 가이드 2026 — runtime-agnostic 웹 프레임워크 (Bun·Deno·Workers·Vercel·Node)" — 한 코드베이스로 다섯 런타임에서 도는 패턴.
- "Node 22~24의 진화 — strip-types, node:test, --watch, --env-file이 바꾼 dev experience" — Bun을 안 써도 받는 혜택들.
- "Deno 2 retrospective" — Deno 2의 Node 호환 베팅이 1년 뒤 어떻게 됐는지.
참고 / References
Bun 공식 자료
- Bun 공식 사이트 — https://bun.sh/ — 최신 버전, 변경 사항.
- Bun docs — https://bun.sh/docs — 런타임·번들러·테스트·셸 전체.
- Bun GitHub — https://github.com/oven-sh/bun — issue·release notes.
- Bun blog (releases) — https://bun.sh/blog — 메이저 버전별 변경 사항.
Node.js
- Node.js 공식 — https://nodejs.org/
node:test문서 — Node 22+ 기준의 native test runner.- Node strip-types 제안 (TC39 type annotations) — TypeScript erasable syntax와의 관계.
Deno
- Deno 공식 — https://deno.com/
- Deno 2 announcement — Node 호환 베팅과 npm: 지원.
벤치마크와 비교 글
- "Bun vs Node vs Deno: HTTP performance" — 여러 커뮤니티 벤치마크 (워크로드별 결과 다름, 본인 워크로드 측정 권장).
- TechEmpower Web Framework Benchmarks — Bun·Node·Deno 위 프레임워크 비교의 표준 출처.
웹 프레임워크 / 런타임-agnostic
- Hono — https://hono.dev/ — Bun·Deno·Workers·Node 모두 지원.
- itty-router, h3 — 같은 카테고리의 다른 옵션.
SQLite 관련
bun:sqlite문서 — Bun 내장 SQLite의 API.- better-sqlite3 — Node 쪽의 사실상 표준 비교 대상.
Bun shell, zx
- Bun shell 문서 —
$API의 자세한 사용법. - Google zx — https://github.com/google/zx — Bun shell의 영감이 된 도구.
운영 채택 사례 (공개된 글 기준)
- Vercel 엔지니어링 블로그의 Bun 도입 글.
- 다수의 startup 회고록 — "왜 Bun을 (안) 골랐는가" 류의 글.
비판적 시각
- Bun의 early-days production 이슈 회고.
- APM auto-instrumentation의 한계에 대한 운영팀의 글.
- Node가 따라잡으면서 차이가 좁아진 영역에 대한 분석.