Skip to content

Bun 은 WebKit Inspector Protocol 을 사용하므로 인터랙티브 디버거로 코드를 디버깅할 수 있습니다. 데모를 위해 다음 간단한 웹 서버를 고려해보세요.

JavaScript 및 TypeScript 디버깅

typescript
Bun.serve({
  fetch(req) {
    console.log(req.url);
    return new Response("Hello, world!");
  },
});

--inspect

Bun 으로 코드를 실행할 때 디버깅을 활성화하려면 --inspect 플래그를 사용합니다. 이는 사용 가능한 포트에서 WebSocket 서버를 자동으로 시작하여 실행 중인 Bun 프로세스를 검사할 수 있습니다.

sh
bun --inspect server.ts
txt
------------------ 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 접두사 또는 둘 다를 지정할 수 있습니다.

sh
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_FETCHcurl 로 설정하여 fetch()node:http 네트워크 요청을 curl 명령어로 출력하는 것을 지원합니다. 이는 fetch 요청을 한 줄 curl 명령어로 출력하여 터미널에 복사하여 붙여넣고 요청을 복제할 수 있게 합니다.

ts
process.env.BUN_CONFIG_VERBOSE_FETCH = "curl";

await fetch("https://example.com", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ foo: "bar" }),
});
txt
[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_FETCHtrue 로 설정합니다.

ts
process.env.BUN_CONFIG_VERBOSE_FETCH = "true";

await fetch("https://example.com", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ foo: "bar" }),
});
txt
[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) 를 호출하여 이 동작을 시뮬레이션할 수 있습니다.

ts
// 에러 생성
const err = new Error("Something went wrong");
console.log(Bun.inspect(err, { colors: true }));

이것은 에러가 발생한 소스 코드의 구문 강조된 미리보기와 에러 메시지 및 스택 트레이스를 출력합니다.

ts
1 | // 에러 생성
2 | const err = new Error("Something went wrong");
                ^
error: Something went wrong
      at file.js:2:13

V8 스택 트레이스

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 객체 배열과 함께 호출되며 사용자 정의 스택 트레이스를 반환할 수 있습니다.

ts
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
getTypeNametypeof this
getFunction함수 객체
getFunctionName문자열로서의 함수 이름
getMethodName문자열로서의 메서드 이름
getFileName파일 이름 또는 URL
getLineNumber줄 번호
getColumnNumber열 번호
getEvalOriginundefined
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.stackfn() 을 호출하는 코드를 가리키게 합니다.

ts
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();
txt
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)

Bun by www.bunjs.com.cn 편집