AI 소식10 min

Bun 2.0 직접 써봤다 — npm 버리고 갈아탄 이유

Bun 2.0을 설치부터 번들러, 테스트 러너, 패키지 관리까지 전부 직접 돌려봤다. npm 대비 속도 차이가 실제로 얼마나 나는지, 기존 프로젝트 마이그레이션 시 주의할 점과 실무 바로 적용 가능한 설정을 정리했다.

2026년 4월 · GoCodeLab

JavaScript 개발 환경은 도구가 많다. 패키지 매니저, 번들러, 트랜스파일러, 테스트 러너가 각각 따로 존재한다. 각자 설정 파일이 다르고, 버전도 따로 관리해야 한다. 프로젝트를 새로 만들 때마다 이 과정을 반복하는 것이 당연한 일처럼 됐다.

Bun은 이 네 가지를 하나의 바이너리로 합쳤다. 런타임, 패키지 매니저, 번들러, 테스트 러너가 전부 bun 하나에 들어있다. 설치하면 바로 TypeScript를 실행하고, 패키지를 설치하고, 빌드하고, 테스트를 돌릴 수 있다. 도구 4개 대신 도구 1개다.

직접 돌려봤다. 모노레포 cold install 기준 npm은 134.2초, Bun은 4.8초였다. 28배 차이다. 숫자로는 실감이 안 됐는데, 체감하고 나면 다시 npm으로 돌아가기가 불편해진다.

빠르게 보기
- 패키지 설치: npm 대비 최대 28배 빠름 (모노레포 기준)
- 테스트: Jest 대비 11배 빠름 (1,500케이스 44s → 4s)
- 번들러: HTML 파일이 엔트리포인트. 단일 파일 빌드 지원
- DB: PostgreSQL·MySQL·MariaDB·SQLite 내장. 별도 드라이버 불필요
- Node.js 호환율 ~98%

Bun이란 무엇인가

Bun은 Jarred Sumner가 만든 JavaScript 런타임이다. Node.js가 V8 엔진(Chrome 엔진)을 쓰는 것과 달리, Bun은 Apple의 JavaScriptCore를 기반으로 한다. Safari가 쓰는 바로 그 엔진이다. 그 위에 Zig 언어로 런타임 전체를 새로 작성했다. Zig는 C 수준의 성능을 내면서 메모리를 직접 제어할 수 있는 언어다. 속도를 극한까지 짜내기 위한 선택이었다.

핵심 설계 원칙은 하나다. 도구를 합친다. npm 대신 패키지 설치, esbuild/webpack 대신 번들링, Jest 대신 테스트, ts-node 대신 TypeScript 실행을 전부 bun 하나가 처리한다. 별도 설치할 패키지가 줄고, 설정 파일 수도 줄어든다.

Node.js와의 호환을 처음부터 우선순위에 뒀다. Express, Fastify, Prisma 같은 주요 패키지는 수정 없이 그대로 동작한다. 2023년 9월 v1.0이 공개됐고, v1.2에서 내장 DB 클라이언트, v1.3에서 MySQL·MariaDB 지원과 HTML 엔트리포인트 번들러가 완성됐다.

설치 — 명령어 하나로 시작한다

macOS와 Linux는 한 줄로 끝난다. Windows도 PowerShell 명령어 하나면 된다. 설치 후 bun --version으로 동작을 확인하면 된다.

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

# Windows (PowerShell)
powershell -c "irm bun.sh/install.ps1 | iex"

# 버전 확인
bun --version

TypeScript는 별도 설정 없이 바로 실행된다. bun run index.ts를 입력하면 트랜스파일 없이 동작한다. ts-nodetsx를 따로 설치할 필요가 없다. JSX도 마찬가지다. .tsx 파일을 바로 실행할 수 있다.

기존 Node.js 프로젝트와 공존한다. 프로젝트마다 다른 런타임을 써도 충돌이 없다. 한 디렉토리에서 node를 쓰고, 다른 디렉토리에서 bun을 써도 문제없다. 전환이 망설여진다면 패키지 매니저만 먼저 바꿔보는 것도 방법이다.

패키지 관리 — 체감이 다르다

속도 차이는 시스템 콜 수에서 나온다. npm은 패키지 설치 중 약 100만 번의 시스템 콜을 쓴다. Bun은 16만 5천 번이다. 처리하는 파일 I/O 자체가 다르다. 이 차이가 모노레포 기준 134.2초 vs 4.8초라는 결과로 나온다. CI 파이프라인에서 매 빌드마다 의존성을 설치하는 환경이라면 누적 효과가 상당하다.

항목npmpnpmBun
모노레포 cold install134.2s15s4.8s
React 앱 디펜던시18s2s
테스트 (1,500케이스)44s (Jest)4s
내장 DB 클라이언트XXO

lockfile은 기본적으로 바이너리 형식인 bun.lockb다. 바이너리라서 git diff로 내용을 보기 불편하다. 텍스트 형식이 필요하다면 bunfig.toml에서 bun.lock으로 전환할 수 있다. 어느 형식이든 git에 커밋해야 버전이 고정된다.

명령어는 npm과 거의 동일하다. bun add lodash, bun remove lodash, bun update가 그대로 동작한다. CI 파이프라인에서는 bun install --frozen-lockfile을 쓰면 lockfile 기준으로 설치한다. npm ci에 해당하는 명령이다.

번들링 — HTML이 엔트리포인트다

Bun에 내장된 번들러는 esbuild 기반이다. Webpack 설정 파일을 따로 작성할 필요가 없다. bun build 명령 하나로 JS, CSS, 에셋을 한 번에 처리한다. 기존 번들러 대비 설정 복잡도가 크게 줄어든다.

차별점은 HTML이 엔트리포인트라는 점이다. bun build ./index.html --outdir=dist를 실행하면 HTML의 <script><link> 태그를 자동으로 감지한다. JS, CSS, 이미지 에셋을 한 번에 처리한다. Webpack처럼 별도 JS 엔트리포인트를 지정할 필요가 없다.

--compile 플래그를 추가하면 모든 에셋이 인라인된 단일 실행 파일이 나온다. v1.3부터는 HTML imports에 HMR(Hot Module Replacement)과 React Fast Refresh가 붙었다. Bun.serve()에 HTML 파일을 넘기면 그게 개발 서버가 된다. 별도 dev 서버 프로세스를 띄울 필요가 없다.

# 프로덕션 번들
bun build ./index.html --outdir=dist

# 단일 실행 파일 빌드
bun build ./index.html --outdir=dist --compile

# 개발 서버 (HMR 포함, Bun.serve 기반)
bun run dev

테스트 러너 — Jest API 그대로 쓴다

bun test는 Jest 호환 API를 제공한다. describe, test, expect, beforeEach, afterAll이 전부 동작한다. jest.config.js 파일을 따로 쓸 필요 없이 bun test 명령 하나로 실행된다. Jest를 쓰던 프로젝트라면 테스트 파일을 수정할 필요가 없다.

속도 차이는 상당하다. 1,500케이스 기준 Jest는 44초, Bun은 4초다. 11배 차이다. 테스트 케이스가 많은 프로젝트에서는 git push 전 로컬 검증 시간이 크게 줄어든다. TDD를 쓰거나 watch 모드를 켜두는 환경이라면 체감이 더 크다.

v1.3.5에서 @testing-library/react와의 fake timers 호환 버그가 수정됐다. 다만 expect.arrayContaining 같은 일부 항목은 아직 미구현이다. 기존 Jest 프로젝트를 전량 이관하기 전에 bun test를 한 번 돌려보는 것이 안전하다.

# 전체 테스트 실행
bun test

# 특정 파일만 실행
bun test src/utils.test.ts

# watch 모드
bun test --watch

내장 DB 클라이언트 — 드라이버가 필요 없다

v1.2부터 PostgreSQL·SQLite 클라이언트가 런타임에 내장됐다. pgbetter-sqlite3를 설치할 필요가 없다. v1.3에서 MySQL·MariaDB까지 추가되면서 Bun.SQL 단일 API로 통합됐다. 외부 드라이버 없이 DB에 바로 연결할 수 있다.

Bun.SQL은 연결 문자열로 DB를 구분한다. postgres://, mysql://, file:./db.sqlite 형식을 인식한다. 연결 문자열만 바꾸면 DB를 교체해도 쿼리 코드는 수정이 없다. DB마다 다른 클라이언트 API를 익힐 필요가 사라진다.

// PostgreSQL 연결
const db = new Bun.SQL("postgres://user:pass@localhost/mydb");

// 템플릿 리터럴 → 자동 파라미터 바인딩
const userId = 42;
const result = await db`SELECT * FROM users WHERE id = ${userId}`;

// SQLite (경로만 다름)
const sqlite = new Bun.SQL("./mydb.sqlite");
SQL 인젝션 자동 방지
템플릿 리터럴로 쿼리를 작성하면 값이 파라미터로 자동 바인딩된다. ${userId}처럼 넣어도 문자열이 쿼리에 직접 삽입되지 않는다. 별도 escape 처리 없이 인젝션이 차단된다.

Node.js에서 전환하기

전환은 단계별로 하는 것이 현실적이다. 한 번에 전부 바꿀 필요가 없다. 패키지 매니저 → 테스트 러너 → 번들러 순서로 하나씩 교체하면 된다. 각 단계에서 문제가 생기면 그 단계에서 멈추면 된다.

Node.js 도구Bun 명령어비고
npm installbun installlockfile 형식이 다름
npx ts-node file.tsbun run file.ts트랜스파일 불필요
jestbun test일부 미구현 항목 확인 필요
webpack / esbuildbun buildHTML이 엔트리포인트
pg / mysql2Bun.SQLv1.2+, 별도 설치 불필요
better-sqlite3Bun.SQLv1.2+

첫 단계는 패키지 매니저 교체다. package.json이 있는 폴더에서 bun install을 실행하면 된다. node_modules가 재생성되고 bun.lockb가 생긴다. 코드는 전혀 수정하지 않아도 된다. 이것만으로도 CI 파이프라인 시간이 달라진다.

Node.js 호환율 ~98%
npm에 올라와 있는 패키지 대부분이 Bun에서 그대로 동작한다. Express, Fastify, Prisma, Drizzle, tRPC 전부 확인됐다. 동작하지 않는 경우는 C++ 바인딩(네이티브 addon)을 쓰는 패키지뿐이다. 전환 전에 bun install && bun run start로 빠르게 확인할 수 있다.

용도별 판단 기준

Bun을 어디서 쓸지는 프로젝트 상황에 따라 다르다. 신규 프로젝트라면 처음부터 Bun으로 시작하는 것이 가장 편하다. 기존 프로젝트라면 단계적 전환이 현실적이다. CI/CD 파이프라인은 가장 빠르게 효과를 볼 수 있는 진입점이다.

상황권장 여부이유
신규 프로젝트적극 권장도구 셋업 최소화, 설정 파일 없이 바로 시작
CI/CD 파이프라인권장코드 변경 없이 패키지 설치 속도만 개선
기존 npm 프로젝트단계적 전환패키지 매니저부터 교체 후 점진적 확장
네이티브 addon 사용사전 확인 필수C++ 바인딩 패키지 호환 불가 케이스 존재
엔터프라이즈 프로덕션검증 후 도입Node.js 대비 생태계 성숙도 차이 존재

CI/CD에서 npm installbun install로 바꾸는 것은 리스크가 가장 낮다. 코드는 건드리지 않는다. 빌드 시간만 줄어든다. 팀 전체가 Bun으로 전환하기 전에 파이프라인에서 먼저 검증해보는 것도 방법이다.

한계와 주의할 점

Bun은 아직 성숙 과정에 있다. Node.js는 15년 이상 프로덕션 환경에서 검증됐다. 생태계 깊이와 커뮤니티 규모 차이가 상당하다. 네이티브 addon — C++ 바인딩을 쓰는 패키지 — 은 동작하지 않을 수 있다. 전환 전에 패키지 목록을 확인하는 것이 안전하다.

Windows 지원은 v1.x 초기 대비 안정화됐다. 현재 PowerShell 설치를 지원하지만, macOS·Linux에 비해 실전 검증 사례가 적다. 팀 내 Windows 개발 환경이 많다면 도입 전 충분히 테스트해야 한다.

기업 프로덕션 환경에서는 도입 전 충분한 검증이 필요하다. 개인 프로젝트나 사이드 프로젝트에서 먼저 써보고, 그 다음에 팀 프로젝트로 확장하는 것이 현실적인 접근법이다. Bun을 전부 도입할 필요도 없다. 패키지 매니저만 쓰고 나머지는 그대로 유지하는 것도 유효한 선택이다.

전환 전 체크리스트
1. 프로젝트에서 네이티브 addon 패키지를 쓰는지 확인한다
2. bun installbun run start로 기본 동작을 검증한다
3. 기존 테스트가 있다면 bun test로 한 번 돌려본다
4. bun.lockb를 git에 커밋한다

Bun을 전부 도입하지 않아도 된다. 패키지 매니저만 먼저 바꾸고, 테스트 러너를 바꾸고, 번들러를 바꾸는 식으로 단계적으로 전환하는 것도 방법이다. 각 단계에서 문제가 없으면 다음으로 넘어가면 된다.

FAQ

Q. Bun은 Node.js를 완전히 대체할 수 있나?

npm 패키지 호환율이 약 98%다. Express, Fastify, Prisma 같은 주요 패키지는 수정 없이 동작한다. 네이티브 addon(C++ 바인딩)을 쓰는 패키지만 별도로 확인이 필요하다. 대부분의 프로젝트는 그대로 동작한다.

Q. bun test는 Jest를 완전히 대체하나?

API 대부분은 호환된다. describe, test, expect, mock 함수 전부 동작한다. 다만 expect.arrayContaining 등 일부 항목은 아직 미구현이다. 전량 이관 전에 기존 테스트를 한 번 돌려보는 것이 안전하다.

Q. bun.lockb 파일은 왜 git에 커밋해야 하나?

bun.lockb는 바이너리 lockfile이다. 이 파일이 없으면 패키지 버전이 고정되지 않는다. 팀원마다 다른 버전이 설치될 수 있다. 텍스트 형식이 필요하다면 bun.lock으로 전환할 수 있다.

Q. Bun SQL은 어떤 DB를 지원하나?

v1.3 기준 PostgreSQL·MySQL·MariaDB·SQLite를 Bun.SQL 단일 API로 처리한다. 별도 npm 드라이버 설치가 필요 없다. 연결 문자열만 바꾸면 DB를 교체해도 쿼리 코드는 그대로다.

Q. 기존 npm 프로젝트에서 Bun으로 전환하는 가장 쉬운 방법은?

package.json이 있는 디렉토리에서 bun install만 실행하면 된다. 코드 변경이 없다. 패키지 매니저만 먼저 바꿔서 속도 차이를 확인하는 것이 가장 안전한 진입점이다. 이것만으로도 CI 파이프라인 시간이 달라진다.

Bun을 전부 도입할 필요는 없다. 패키지 매니저만 먼저 바꾸고, 테스트 러너를 바꾸고, 번들러를 바꾸는 식으로 단계적으로 전환 가능하다. CI에서 npm install을 쓰고 있다면, 오늘 bun install로 바꾸는 것만으로도 충분한 시작점이 된다.

공식 출처
- Bun 공식 블로그 — v1.2, v1.3 릴리스 노트
- Bun 공식 문서 — 설치, API, 번들러, 테스트 러너
- oven-sh/bun GitHub — 소스코드 및 이슈 트래커

GoCodeLab 업데이트 받기

JavaScript·AI 도구·개발 생산성 정보를 직접 검증해서 전달한다.

구독하기

이 글의 수치는 공식 Bun 릴리스 노트 및 벤치마크 자료를 기반으로 한다. 환경에 따라 실제 성능은 다를 수 있다.

최종 업데이트: 2026년 4월 · GoCodeLab