Bunjs v.1.1 출시
Bunjs가 v1.1을 출시 했습니다.
🟦Bun 이란?
bun는 node, deno 같은 javascript 런타임 및 패키지 관리자 입니다. node, deno와 달리 bun은 빠릅니다. v8엔진을 사용하는 node, deno와 달리 Zig로 작성되고 JavaScriptCore로 구동되어 속도가 굉장히 빠릅니다.
🟦 Bun의 특징
node가 있는데 bun을 쓸 이유가 있을까요? 좀더 빠른 것을 원하면 bun을 선택하는 것이 좋습니다. 걱정되는 것은 node에서 사용되었던 것들이 호환이 안될 수 있다는 것 입니다. 걱정 안하셔도 됩니다. bun 개발자들이 가장 중요하게 생각하는 것이 node와 호환성입니다.
Bun을 썼을 때 더 편리한 방법중 몇가지 알려드리겠습니다.
npx
— 5배 더 빠름bunx
dotenv
, — Bun은 기본적으로 파일을 읽습니다.cross-env
.env
nodemon
, — 내장 시계 모드pm2
ws
— 내장 WebSocket 서버node-fetch
, — 내장isomorphic-fetch
fetch
이렇게 내장되어 있는 기능이 많습니다.jest
호환 테스트 라이브러리를 내장하고 있습니다. 자세한 내용은 Bun v1.0 출시 블로그에 나와있습니다.
bun v1.1이 출시되면서 엄청난 업데이트를 하였습니다. 그 내용 중에 중요하다고 생각되는 것을 살펴보겠습니다.
🟩 window 지원
이제 Windows 10 이상에서 Bun을 실행할 수 있습니다. 예전 버전에서는 window 환경에서 실행 할 수 없었습니다. macOs/Linux 환경에서만 실행이 가능했었습니다. window로 개발하는 사람들은 wsl을 설치하고 bun을 설치해서 사용했었어야 했습니다.
이제 v1.1 버전이 나오면서 window 지원이 가능해졌습니다! 이제 window 환경에서 bun을 마음것 사용할 수 있습니다.
🟩 Windows에서 `bun 설치
> powershell -c "irm bun.sh/install.ps1 | iex"
Bun에는 패키지를 설치하는 npm 호환 패키지 관리자가 내장되어 있습니다. bun install
은 yarn
npm
을 사용해서 Vite React 앱을 설치할 때 Windows보다 18배, 30배 빠르게 실행됩니다.
Windows에서 '--ignore-scripts'를 사용하여 vite react 앱에 종속성을 설치하는 데 소요된 시간입니다.
🟩 bun --watch
(Windows)
Bun에는 watch
모드가 내장되어 있습니다. 이렇게 하면 변경 내용이 코드에 영향을 주는 것을 파악하는 시간이 빨라집니다.
왼쪽은 테스트 파일을 변경하는 모습입니다. 오른쪽은 Windows의 'bun test --watch'입니다.
🟩 Node.js 호환성
bun은 nodejs쓰는 기본적인 api를 많이 지원해주고 있습니다.
Node.js와 호환되는 Date.parse()
Bun은 V8을 사용하는 Node.js와 달리 JavaScriptCore를 JavaScript 엔진으로 사용합니다. 날짜
구문 분석은 복잡하며 그 동작은 엔진마다 크게 다릅니다.
예를 들어, Bun 1.0에서는 다음이 Node.js에서는 작동하지만 Bun에서는 작동하지 않습니다.
const date = "2020-09-21 15:19:06 +00:00";
Date.parse(date); // Bun: Invalid Date
Date.parse(date); // Node.js: 1600701546000
Bun 1.0에서는 에러가 났지만 Bun 1.1에서는 node.js와 동일한 값을 출력합니다.
fs.readdir()
Bun 1.0에서는 fs.readdir()
의 옵션을 지원하지 않았습니다. 옵션에 대한 지원을 추가했을 뿐만 아니라 Node.js보다 22배 더 빨라졌다고 합니다.
🟩 웹 API
Bun은 fetch()
및 Response
를 포함한 웹 표준 API도 지원합니다. 이렇게 하면 브라우저와 Bun 모두에서 작동하는 코드를 더 쉽게 작성할 수 있습니다.
🟩 WebSocket
이 안정적이게 되었습니다.
이전에는 WebSocket
이 초기 연결 끊김 및 조각화 문제와 같은 프로토콜 버그로 인해 실험적으로 표시되었습니다.
Bun 1.1에서는 이제 안정적으로 바꿨다고 합니다
const ws = new WebSocket("wss://echo.websocket.org/");
ws.addEventListener("message", ({ data }) => {
console.log("Received:", data);
});
ws.addEventListener("open", () => {
ws.send("Hello!");
});
🟩 시간측정 performance.mark()
Bun은 이제 및 와 같은 API를 포함하는 user-timings API를 지원합니다. 이는 응용 프로그램의 성능을 측정하는 데 유용합니다.performance.mark()
performance.measure()
performance.mark("start");
while (true) {
// ...
}
performance.mark("end");
performance.measure("task", "start", "end");
🟩 Brotli 압축을 사용하는 fetch()
이제 fetch()
를 사용하여 인코딩으로 요청할 수 있습니다. 이는 Brotli 압축을 지원하는 서버에 요청할 때 유용합니다.
const response = await fetch("https://example.com/", {
headers: {
"Accept-Encoding": "br",
},
});
🟩 url 검증기 URL.canParse()
Bun은 이제 최근에 추가된 URL.canParse()
API를 지원합니다. 이렇게 하면 문자열이 오류를 발생시키지 않고 유효한 URL인지 확인할 수 있습니다.
URL.canParse("https://example.com:8080/"); // true
URL.canParse("apoksd!"); // false
🟩 console.table
, console.time
js에서 구조화된 객체를 쉽게 보기 위한 console.table()
이 구현되었다고 합니다. 시간을 측정할 수 있는 console.timeLog()
이 구현되었다고 합니다.
🟩 Bun.write()는
상위 디렉터리를 만듭니다.
이전에는 부모 디렉터리가 없는 경우 오류가 발생했습니다.Bun.write()
import { write } from "bun";
await write("does/not/exist/hello.txt", "Hello!");
// ENOENT: No such file or directory
Bun 1.0.16 부터 Bun은 부모 디렉터리가 존재하지 않는 경우 부모 디렉터리를 만듭니다.
bun 1.0.16 미만 버전을 사용하는 개발자는 다음과 같은 boilterplate 코드를 작성해야 합니다.
import { write } from "bun";
import { mkdir } from "node:fs/promises";
try {
await write("does/not/exist/hello.txt", "Hello!");
} catch (error) {
if (error.code === "ENOENT") {
await mkdir("does/not/exist", { recursive: true });
await write("does/not/exist/hello.txt", "Hello!");
} else {
throw error;
}
}
createPath
속성을 지정해서 파일을 만들지 못하게 할 수 있습니다.
import { write } from "bun";
await write("does/not/exist/hello.txt", "Hello, world!", { createPath: false });
// ENOENT: No such file or directory
🟩 Bun은 테스트 러너입니다.
Bun에는 JavaScript, TypeScript 및 JSX로 테스트를 쉽게 작성하고 실행할 수 있는 테스트 모듈이 내장되어 있습니다. expect()
스타일 API를 포함하는 Jest와 동일한 API를 지원합니다.
matcher
매처는 코드를 테스트하는 데 사용할 수 있는 어설션입니다. Bun 1.0 이후, 다음과 같은 수십 개의 새로운 매처가 추가되었습니다.expect()
import { expect } from "bun:test";
expect.hasAssertions();
expect.assertions(9);
expect({}).toBeObject();
expect([{ foo: "bar" }]).toContainEqual({ foo: "bar" });
expect(" foo ").toEqualIgnoringWhitespace("foo");
expect("foo").toBeOneOf(["foo", "bar"]);
expect({ foo: Math.PI }).toEqual({ foo: expect.closeTo(3.14) });
expect({ a: { b: 1 } }).toEqual({ a: expect.objectContaining({ b: 1 }) });
expect({ a: Promise.resolve("bar") }).toEqual({ a: expect.resolvesTo("bar") });
expect({ b: Promise.reject("bar") }).toEqual({ b: expect.rejectsTo("bar") });
expect.unreachable();
expect.extend()
를 사용한 사용자 정의 매처
Bun이 지원하지 않는 매처가 있는 경우 expect.extend()
를 사용하여 직접 만들 수 있습니다. 이는 여러 테스트에서 재사용할 수 있는 사용자 지정 매처를 정의하려는 경우에 유용합니다.
import { test, expect } from "bun:test";
expect.extend({
toBeWithinRange(received, floor, ceiling) {
const pass = received >= floor && received <= ceiling;
if (pass) {
return {
message: () =>
`Expected ${received} not to be within range ${floor} - ${ceiling}`,
pass: true,
};
} else {
return {
message: () =>
`Expected ${received} to be within range ${floor} - ${ceiling}`,
pass: false,
};
}
},
});
test("toBeWithinRange()", () => {
expect(1).toBeWithinRange(1, 99); // ✅
expect(100).toBeWithinRange(1, 99); // ❌ Expected 100 to be within range 1 - 99
});
🟩 Bun은 SQLite를 기본적으로 지원합니다.
better-sqlite3
1.0부터 Bun은 SQLite를 기본적으로 지원했습니다.
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
const query = db.query("select 'Bun' as runtime;");
query.get(); // { runtime: "Bun" }
그 이후로 에 대한 많은 새로운 기능과 개선 사항이 있었습니다.bun:sqlite
다중 문 쿼리
다중 문 쿼리에 대한 지원을 추가하여 run()
exec()
명령어를 사용해서 여러 SQL 문을 단일 호출로 실행할 수 있습니다.
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
db.run(`
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT
);
INSERT INTO users (name) VALUES ("Alice");
INSERT INTO users (name) VALUES ("Bob");
`);