Bun 완전 가이드 | Node.js를 뛰어넘는 초고속 JavaScript 런타임
이 글의 핵심
Node.js를 뛰어넘는 초고속 JavaScript 런타임 Bun. 번들러·테스트·패키지 매니저까지 올인원으로 제공하며, 3배 빠른 성능과 네이티브 TypeScript 지원으로 차세대 표준을 제시합니다.
Bun이란 걸 처음 보고 “또 런타임?” 했다가, bun install 한 번 돌려본 다음부터 입장이 좀 흔들린다. 솔직히 말하면 아직 전 회사의 코어 백엔드 전부를 Bun으로 갈아타라고는 못 하겠다. 생태계·엣지 케이스·온콜 대응까지 다 치면 Node가 아직 익숙하니까. 그런데 사이드 프로젝트, 내부 툴, CI에서 패키지 깔 때 기다리는 시간 줄이는 용도로는 꽤 매력 있어. 그냥 “빠르다”로 끝낼 문제가 아니라, 도구를 하나로 줄이는 느낌이 강하다. 번들·테스트·런·패키지가 한 bin 안에 있으니, 레포마다 Jest/ Vitest/ Webpack 뭐 쓰는지 머리 쓰는 횟수가 확 줄어.
Bun으로 마이그레이션하면서 겪은 건, 빠른 것도 빠른 건데 가장 큰 이득이 CI 시간이었다. 예전엔 npm install이 몇 분씩 먹을 때가 있었는데, Bun으로 바꾸고 나서 락을 bun.lockb 쪽에 맞춰 두니 로컬이랑 파이프라인 둘 다 “아, 끝났네?” 느낌이 먼저 온다. 대신 package-lock.json 갖고 있던 팀이면, 누가 실수로 npm이랑 섞으면 꼬이니까 한 번 팀 룰로 정해두는 게 낫다. 난 그 과정에서 가끔 네이티브 애드온 쪽에서만 삑사리 나는 케이스 봤고, 그때는 그냥 그 패키지 경로는 Node로 돌리거나 이미지를 나누는 식으로 피했다. “완벽 호환”을 맹신하다가 밤새는 건 별로다.
엔진 이야기만 짧게 짚자면 Bun은 JavaScriptCore(사파리 계열)를 쓰고, Node는 V8이다. 누가 절대적으로 이긴다는 표는 안 깔겠다—숫자는 환경에 따라 흔들리니까. 다만 체감으로는 같은 머신에서 bun run이 덜 꿈틀거리는 경우가 잦다. HTTP 마이크로벤치 돌리면 RPS가 꽤 차이나는 씬이 있고, “우리 API가 진짜 그만큼 병목이냐?” 싶을 정도는 아닐 때가 많다. 그래서 프레임에 숫자 박는 것보다, 의심가는 엔드포인트 하나 잡고 wrk 같은 걸로 전후를 찍는 쪽이 난 더 설득력 있다고 본다.
설치는 OS마다 정해진 스크립트 쓰면 되고, Docker는 oven/bun 이미지가 깔끔하다. 로컬은 보통 아래 둘 중 하나.
curl -fsSL https://bun.sh/install | bash
bun --version
powershell -c "irm bun.sh/install.ps1 | iex"
프로젝트 띄울 땐 bun init 하고 bun add로 의존성 박으면 끝에 가깝다. bun run index.ts 하면 TS를 그냥 굴린다—이게 꽤 큰다. 팀에 “tsc + node 두 번 치는” 루틴 익숙한 사람이면 처음엔 오히려 불안한데, 익으면 package.json 스크립트가 짧아지는 만족이 있다.
서버는 Bun.serve로 바로 쓰는 경우가 많다. Express 끼워 쓰는 것도 여전히 되고, 기존 코드 덜 고치고 싶으면 그 쪽이 현실적이다.
const server = Bun.serve({
port: 3000,
fetch(req) {
return new Response("Hello from Bun");
},
});
console.log(`http://localhost:${server.port}`);
파일·SQLite는 Bun.file, bun:sqlite 쪽 API가 꽤 직선적이다. “왜 이게 이렇게 짧지?” 싶을 때가 있는데, 그만큼 추상화가 얇다는 뜻이기도 하니, I/O 꼭지 하나가 중요한 서비스면 스트림·에러·백프레셔는 별도로 설계해라.
import { Database } from "bun:sqlite";
const db = new Database("app.db");
db.run("CREATE TABLE IF NOT EXISTS t (id INTEGER PRIMARY KEY, v TEXT)");
테스트는 bun:test가 Jest랑 결이 비슷해서 옮기기 괜찮다. “엄청 빨라요”는 마케팅 문장으로 듣지 말고, 실제로 스위트가 커질수록 빛을 본다. 작은 프로젝트에선 별차이도 없을 수 있음.
번들은 Bun.build로 때우면 되는데, Webpack·esbuild 쓰던 레포는 설정 습관이 남아 있을 거다. “한 방에 갈아엎는다”기보다 새 마이크로서비스 하나만 Bun 빌드로 시험해보는 쪽이 덜 위험하다. 거기서 괜찮으면 점진적으로.
솔까 프로덕션 얘기하자. 공식 1.0 이후 “써도 된다”는 스탠스가 있고, 사례도 는다. 그래도 결제·인증·감사 로그 같은 라인에선 아직 “Node로 가자, Bun은 팀이 익숙해지면” 쪽이 나한텐 낫다. 이유는 단순하다. 온콜 때 스택트레이스 읽는 속도, 레퍼런스 검색, 레거시 애드온 지원, 그리고 채용까지 포석체로 보면 Node가 압승이니까. 반대로 Edge 근처 실험, 내부 대시보드, 봇, CLI, 프리뷰 환경은 Bun 써볼 만하다. 리스크를 줄이는 방법은, 런타임만 갈아끼우지 말고 로컬·스테이징에서 한두 주 더 흔들어보고, 락 파일과 설치 엔트리하인트를 한 팀 룰로 고정하는 것.
끝으로, Bun이 해결해주는 건 “자바스크립트가 느려서”만이 아니다. 도구의 개수를 줄여주는 쪽이 더 크게 다가온다. curl … | bash로 설치해보고, bun init → bun add → bun test 흐름만 한번 밟아봐. 맞는 팀이면 돌아가기 힘들고, 아니면 Node로 쉽게 돌아가면 그만이다.