1. 개요
디버거의 동작과 개발환경과의 상호작용을 표준화하기 위한 프로토콜 및 표준.2. 구조
DAP는 protocol이기 때문에 각 실제 디버거들에 붙어 DAP compat 인터페이스를 깔아 주는 컴포넌트가 필요한데, 이를 adapter라고 한다. LSP에서의 server에 대응한다고 보면 된다. 반대로 IDE 레이어는 클라이언트/호스트라고 하며, DAP compat한 unified UI만 제공하면 더 이상의 구현이 필요 없다. 스펙에서는 주로 클라이언트라고 불린다.
이 아키텍처로 remote debugging이 가능하냐 하면 실제로 가능하다. 다만 좀 글러먹은(...) 구현체의 경우 path mapping 등 단계에서 이슈가 있을 순 있다. 당연히
RunInTerminal 등은 쓰기 어렵다.2.1. 세션 초기화와 디버거 부착 방식
LSP와 비슷하게 adapter를 initialize하면서 응답으로 지원되는 capabilities 맵을 받는다. 클라이언트 쪽에선 adapter의 capabilities를 전달받은 그 즉시 후술할 실행 요청을 보낼 수 있는데, 이는 많은 디버거 구현체(LLDB, vsdbg 등)가 context를 초기화하기 전에는 중단점 binding이 불가능하기 때문이다. initialize 스텝 이후 adapter는 내부적으로 자신이 관리할 디버거를 실행시키는 등의 준비를 하고, 완료되면
Initialized 이벤트를 발생시킨다.이후로는 LSP와 조금 다르게 debug configuration 시퀀스가 진행되는데, 디버깅인 만큼 보통 중단점(breakpoint), 예외 중단점 등의 중단점 설정이 들어간다. 설정이 완료되면
ConfigurationDone으로 이를 알린다.debugee 실행 방식의 경우 크게 다음 두 가지로 나뉜다.
Launch: adapter 단에서 debugee를 스스로 실행하고, 디버거 부착까지 수행하는 방식.Attach: 이미 실행되고 있는 debugee에 디버거를 부착하여 실행하는 방식. 디버거마다 방식이 차이나기 때문에 스펙에서는 큰 정의가 없다.
3. 프로토콜
specificationwire format은 놀랍게도(?) JSON-RPC가 아닌데, 이는 초창기 DAP가 V8의 V8 Debugger Protocol에 기초해 만들어졌고 정작 LSP는 DAP에서 파생되었지만 JSON-RPC를 채택했기 때문이다.#58 참고로 V8 Debugger Protocol은 알려져 있다시피 현재 CDP로 인해 deprecated되었다.
크게 HTTP와 닮은 헤더 영역과 content 영역으로 나누어지나, 현재 지원되는 헤더는
Content-Length 하나뿐이다. 용도 또한 HTTP의 Content-Length와 유사하다. 이후 content 영역은 JSON 데이터이며, LSP와 거의 유사한 구조로 구성되어 있다.4. 주요 구현체
4.1. 어댑터 구현체
디버거가 내장 지원하는 경우는 * 표시.- gdb* - 2023년 12월 14.1버전 이후부터 내장 지원된다.#@
- vscode-js-debug - 이름대로 Visual Studio Code에서 쓰이는 JavaScript/TypeScript 공식 DAP 구현체이다. 현재 CDP, Node.js 등 주요 JS 디버거 및 프로토콜을 대부분 지원하며 과거 쓰이던 vscode-chrome-debug 어댑터까지 대체한다.
- LLDB
lldb-dap- LLVM 공식 프로젝트이다.- codelldb - 이름에 code가 들어가 있지만, 근본적으로 DAP 구현체이기 때문에 Visual Studio Code 말고 다른 환경에서도 쓸 수 있다. LLDB 레이어 위에 Rust 디버깅용으로 마개조를 해놓았기 때문에 Rust 개발시엔 lldb-dap보다도 자주 쓰이는 편.
- delve* - 내장 지원#