Bun 은 WebKit Inspector Protocol 을 사용하므로 인터랙티브 디버거로 코드를 디버깅할 수 있습니다. 데모를 위해 다음 간단한 웹 서버를 고려해보세요.
JavaScript 및 TypeScript 디버깅
Bun.serve({
fetch(req) {
console.log(req.url);
return new Response("Hello, world!");
},
});--inspect
Bun 으로 코드를 실행할 때 디버깅을 활성화하려면 --inspect 플래그를 사용합니다. 이는 사용 가능한 포트에서 WebSocket 서버를 자동으로 시작하여 실행 중인 Bun 프로세스를 검사할 수 있습니다.
bun --inspect server.ts------------------ Bun Inspector ------------------
리스닝 중:
ws://localhost:6499/0tqxs9exrgrm
브라우저에서 검사:
https://debug.bun.sh/#localhost:6499/0tqxs9exrgrm
------------------ Bun Inspector --------------------inspect-brk
--inspect-brk 플래그는 --inspect 와 동일하게 동작하지만 실행된 스크립트의 첫 번째 줄에 자동으로 중단점을 삽입합니다. 이는 빠르게 실행되고 즉시 종료되는 스크립트를 디버깅할 때 유용합니다.
--inspect-wait
--inspect-wait 플래그는 --inspect 와 동일하게 동작하지만 디버거가 실행 중인 프로세스에 연결할 때까지 코드가 실행되지 않습니다.
디버거의 포트 또는 URL 설정
어떤 플래그를 사용하든 선택적으로 포트 번호, URL 접두사 또는 둘 다를 지정할 수 있습니다.
bun --inspect=4000 server.ts
bun --inspect=localhost:4000 server.ts
bun --inspect=localhost:4000/prefix server.ts디버거
다양한 디버깅 도구가 이 서버에 연결하여 인터랙티브 디버깅 환경을 제공할 수 있습니다.
debug.bun.sh
Bun 은 debug.bun.sh 에서 웹 기반 디버거를 호스팅합니다. 이는 Safari 사용자에게 익숙할 WebKit 의 Web Inspector Interface 의 수정된 버전입니다.
제공된 debug.bun.sh URL 을 브라우저에서 열어 디버깅 세션을 시작합니다. 이 인터페이스에서 실행 중인 파일의 소스 코드를 보고 중단점을 설정하고 내장 콘솔을 사용하여 코드를 실행할 수 있습니다.
중단점을 설정해보겠습니다. Sources 탭으로 이동하면 이전의 코드가 보일 것입니다. console.log(req.url) 문에 있는 줄 번호 3 을 클릭하여 중단점을 설정합니다.
그런 다음 웹 브라우저에서 http://localhost:3000 을 방문합니다. 이는 localhost 웹 서버에 HTTP 요청을 보냅니다. 페이지가 로드되지 않는 것처럼 보일 것입니다. 왜일까요? 프로그램이 이전에 설정한 중단점에서 실행이 일시정지되었기 때문입니다.
UI 가 어떻게 변했는지 주목하세요.
이 시점에서 현재 실행 환경을 검사하기 위해 많은 작업을 수행할 수 있습니다. 하단의 콘솔을 사용하여 중단점에서 범위에 있는 변수에 완전히 접근할 수 있는 프로그램의 컨텍스트에서 임의의 코드를 실행할 수 있습니다.
Sources 창의 오른쪽에서 현재 범위에 있는 모든 로컬 변수를 보고 속성과 메서드를 자세히 살펴볼 수 있습니다. 여기서는 req 변수를 검사하고 있습니다.
Sources 창의 왼쪽 상단에서 프로그램 실행을 제어할 수 있습니다.
여기에는 제어 흐름 버튼의 기능을 설명하는 치트시트가 있습니다.
- 스크립트 실행 계속 — 다음 중단점이나 예외가 발생할 때까지 프로그램을 계속 실행합니다.
- 스텝 오버 — 프로그램이 다음 줄로 계속 실행됩니다.
- 스텝 인 — 현재 문에 함수 호출이 있으면 디버거가 호출된 함수로 "스텝 인"합니다.
- 스텝 아웃 — 현재 문이 함수 호출이면 디버거는 호출 실행을 완료한 후 호출된 위치로 함수에서 "스텝 아웃"합니다.
Visual Studio Code 디버거
Bun 스크립트 디버깅에 대한 실험적 지원은 Visual Studio Code 에서 사용할 수 있습니다. 사용하려면 Bun VSCode 확장 을 설치해야 합니다.
네트워크 요청 디버깅
BUN_CONFIG_VERBOSE_FETCH 환경 변수를 사용하면 fetch() 또는 node:http 로 만든 네트워크 요청을 자동으로 로깅할 수 있습니다.
| 값 | 설명 |
|---|---|
curl | 요청을 curl 명령어로 출력합니다. |
true | 요청 및 응답 정보를 출력합니다. |
false | 아무것도 출력하지 않습니다. 기본값 |
fetch 및 node:http 요청을 curl 명령어로 출력
Bun 은 환경 변수 BUN_CONFIG_VERBOSE_FETCH 를 curl 로 설정하여 fetch() 및 node:http 네트워크 요청을 curl 명령어로 출력하는 것을 지원합니다. 이는 fetch 요청을 한 줄 curl 명령어로 출력하여 터미널에 복사하여 붙여넣고 요청을 복제할 수 있게 합니다.
process.env.BUN_CONFIG_VERBOSE_FETCH = "curl";
await fetch("https://example.com", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ foo: "bar" }),
});[fetch] $ curl --http1.1 "https://example.com/" -X POST -H "content-type: application/json" -H "Connection: keep-alive" -H "User-Agent: Bun/1.3.3" -H "Accept: */*" -H "Host: example.com" -H "Accept-Encoding: gzip, deflate, br" --compressed -H "Content-Length: 13" --data-raw "{\"foo\":\"bar\"}"
[fetch] > HTTP/1.1 POST https://example.com/
[fetch] > content-type: application/json
[fetch] > Connection: keep-alive
[fetch] > User-Agent: Bun/1.3.3
[fetch] > Accept: */*
[fetch] > Host: example.com
[fetch] > Accept-Encoding: gzip, deflate, br
[fetch] > Content-Length: 13
[fetch] < 200 OK
[fetch] < Accept-Ranges: bytes
[fetch] < Cache-Control: max-age=604800
[fetch] < Content-Type: text/html; charset=UTF-8
[fetch] < Date: Tue, 18 Jun 2024 05:12:07 GMT
[fetch] < Etag: "3147526947"
[fetch] < Expires: Tue, 25 Jun 2024 05:12:07 GMT
[fetch] < Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
[fetch] < Server: EOS (vny/044F)
[fetch] < Content-Length: 1256[fetch] > 가 있는 줄은 로컬 코드에서의 요청이며, [fetch] < 가 있는 줄은 원격 서버에서의 응답입니다.
BUN_CONFIG_VERBOSE_FETCH 환경 변수는 fetch() 와 node:http 요청 모두에서 지원되므로 바로 작동합니다.
curl 명령어 없이 출력하려면 BUN_CONFIG_VERBOSE_FETCH 를 true 로 설정합니다.
process.env.BUN_CONFIG_VERBOSE_FETCH = "true";
await fetch("https://example.com", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ foo: "bar" }),
});[fetch] > HTTP/1.1 POST https://example.com/
[fetch] > content-type: application/json
[fetch] > Connection: keep-alive
[fetch] > User-Agent: Bun/1.3.3
[fetch] > Accept: */*
[fetch] > Host: example.com
[fetch] > Accept-Encoding: gzip, deflate, br
[fetch] > Content-Length: 13
[fetch] < 200 OK
[fetch] < Accept-Ranges: bytes
[fetch] < Cache-Control: max-age=604800
[fetch] < Content-Type: text/html; charset=UTF-8
[fetch] < Date: Tue, 18 Jun 2024 05:12:07 GMT
[fetch] < Etag: "3147526947"
[fetch] < Expires: Tue, 25 Jun 2024 05:12:07 GMT
[fetch] < Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
[fetch] < Server: EOS (vny/044F)
[fetch] < Content-Length: 1256스택 트레이스 및 소스맵
Bun 은 모든 파일을 트랜스파일하므로 콘솔에서 보는 스택 트레이스가 트랜스파일된 출력을 가리키며 도움이 되지 않을 것처럼 들릴 수 있습니다. 이를 해결하기 위해 Bun 은 트랜스파일하는 모든 파일에 대해 소스맵을 자동으로 생성하고 제공합니다. 콘솔에서 스택 트레이스를 볼 때 파일 경로를 클릭하면 TypeScript 나 JSX 로 작성되었거나 다른 변환이 적용되었더라도 원래 소스 코드로 이동할 수 있습니다.
Bun 은 온디맨드로 파일을 트랜스파일할 때 런타임에서와 bun build 를 사용하여 미리 파일을 컴파일할 때 모두 소스맵을 자동으로 로드합니다.
구문 강조된 소스 코드 미리보기
디버깅을 돕기 위해 Bun 은 처리되지 않은 예외나 거부가 발생할 때 자동으로 작은 소스 코드 미리보기를 출력합니다. Bun.inspect(error) 를 호출하여 이 동작을 시뮬레이션할 수 있습니다.
// 에러 생성
const err = new Error("Something went wrong");
console.log(Bun.inspect(err, { colors: true }));이것은 에러가 발생한 소스 코드의 구문 강조된 미리보기와 에러 메시지 및 스택 트레이스를 출력합니다.
1 | // 에러 생성
2 | const err = new Error("Something went wrong");
^
error: Something went wrong
at file.js:2:13V8 스택 트레이스
Bun 은 엔진으로 JavaScriptCore 를 사용하지만 Node.js 생태계와 npm 의 대부분은 V8 을 기대합니다. JavaScript 엔진은 error.stack 포맷팅이 다릅니다. Bun 은 Node.js 의 대체품이 되는 것을 목표로 하므로 엔진이 다르더라도 스택 트레이스는 가능한 한 유사하게 만드는 것이 우리의 일입니다.
그래서 Bun 에서 error.stack 를 로깅하면 error.stack 의 포맷팅이 Node.js 의 V8 엔진과 동일합니다. 이는 특히 V8 스택 트레이스를 기대하는 라이브러리를 사용할 때 유용합니다.
V8 스택 트레이스 API
Bun 은 스택 트레이스를 조작할 수 있는 함수 세트인 V8 스택 트레이스 API 를 구현합니다.
Error.prepareStackTrace
Error.prepareStackTrace 함수는 스택 트레이스 출력을 사용자 정의할 수 있는 전역 함수입니다. 이 함수는 에러 객체와 CallSite 객체 배열과 함께 호출되며 사용자 정의 스택 트레이스를 반환할 수 있습니다.
Error.prepareStackTrace = (err, stack) => {
return stack.map(callSite => {
return callSite.getFileName();
});
};
const err = new Error("Something went wrong");
console.log(err.stack);
// [ "error.js" ]CallSite 객체에는 다음 메서드가 있습니다.
| 메서드 | 반환값 |
|---|---|
getThis | 함수 호출의 this 값 |
getTypeName | typeof this |
getFunction | 함수 객체 |
getFunctionName | 문자열로서의 함수 이름 |
getMethodName | 문자열로서의 메서드 이름 |
getFileName | 파일 이름 또는 URL |
getLineNumber | 줄 번호 |
getColumnNumber | 열 번호 |
getEvalOrigin | undefined |
getScriptNameOrSourceURL | 소스 URL |
isToplevel | 함수가 전역 범위에 있으면 true 반환 |
isEval | 함수가 eval 호출이면 true 반환 |
isNative | 함수가 네이티브이면 true 반환 |
isConstructor | 함수가 생성자이면 true 반환 |
isAsync | 함수가 async 이면 true 반환 |
isPromiseAll | 아직 구현되지 않았습니다. |
getPromiseIndex | 아직 구현되지 않았습니다. |
toString | 호출 사이트의 문자열 표현 반환 |
경우에 따라 Function 객체가 이미 가비지 컬렉션되었을 수 있으므로 이 메서드 중 일부는 undefined 를 반환할 수 있습니다.
Error.captureStackTrace(error, startFn)
Error.captureStackTrace 함수를 사용하면 에러가 발생한 시점이 아닌 코드의 특정 지점에서 스택 트레이스를 캡처할 수 있습니다.
이는 콜백이나 비동기 코드로 인해 에러가 어디서 발생했는지 확인하기 어려울 때 유용합니다. Error.captureStackTrace 의 두 번째 인수는 스택 트레이스를 시작하려는 함수입니다.
예를 들어, 아래 코드는 에러가 myInner 에서 발생했더라도 err.stack 이 fn() 을 호출하는 코드를 가리키게 합니다.
const fn = () => {
function myInner() {
throw err;
}
try {
myInner();
} catch (err) {
console.log(err.stack);
console.log("");
console.log("-- captureStackTrace --");
console.log("");
Error.captureStackTrace(err, fn);
console.log(err.stack);
}
};
fn();Error: here!
at myInner (file.js:4:15)
at fn (file.js:8:5)
at module code (file.js:17:1)
at moduleEvaluation (native)
at moduleEvaluation (native)
at <anonymous> (native)
-- captureStackTrace --
Error: here!
at module code (file.js:17:1)
at moduleEvaluation (native)
at moduleEvaluation (native)
at <anonymous> (native)