서문에
Q:Node 는 어떻게 디버깅합니까?
A:디버깅이란 무엇입니까?
일반적으로 말하는 "디버깅"은 스텝 오버, 스텝 인, 스텝 아웃으로, 소스 코드를 한 줄씩 실행하는 것을 말할 것입니다. 이 경우, 서버 사이드 프로그램의 디버깅과 일반적인 클라이언트 프로그램没什么区别로, 모두 실행 흐름, 콜 스택, 변수의 현재 값 등을 엿보고 싶은 것입니다. 즉, Node 서비스 디버깅과 페이지 중 JS 스크립트 디버깅 방식은 동일합니다
물론, 서버 사이드에는 서버 사이드의 특수성이 있으며, 많은 코드는 클라이언트 환경과 밀접하게 관련되어 있습니다. 예를 들어 Cookie, Request Header, localStorage ��입니다. 한 줄씩 디버깅하는 것은 현실적이지 않은 것 같습니다. 먼저, 서비스의 입력 (클라이언트 요청) 은 어디에서 오는가? 요청을 시뮬레이션하거나, 직접 데이터를 시뮬레이션할 수도 있습니다...これ以上話すと実はテストの内容で, "디버깅"이 아닙니다
一.Debugger
Node 에는 브레이크포인트 디버깅, 즉 debugger 문이 내장되어 있습니다. 다음과 같습니다:
// console.js
debugger;
var value = 1;
var fn1 = function() {
debugger;
value = '2';
console.log('fn1');
};
var fn2 = function() {
debugger;
value = 3;
fn1();
console.log('fn2');
};
console.log(1);
process.nextTick(function () {
debugger;
value = 4;
fn2();
console.log(2);
});
console.log(3);
여기서 debugger; 는 브레이크포인트를 설정하는 것을 나타내며, 비동기 실행 흐름도 브레이크포인트에서 중단됩니다. 물론, debugger 는 디버깅 환경에서만 유효하며, 명령줄에서 debug 모드로 진입합니다:
node debug ./console.js
// 이미 실행 중인 서비스에 대해, 해당 프로세스에 SIGUSR1 신호를 전송하여 디버깅 모드로 진입할 수 있습니다
// kill -s USR1 [pid]
그 후, 프롬프트 정보와 debug 대화 프롬프트가 표시됩니다:
< Debugger listening on port 5858
debug> . ok
break in E:\node\learn\debug\console.js:1
> 1 debugger;
2
3 var value = 1;
debug>
실행 흐름이 1 행目の debugger; 에서 정지하고, 커서가 깜빡이며 입력을 기다립니다. Node 는 V8 디버그 명령의 완전한 지원을 제공하지 않으며, 사용 가능한 명령은 다음과 같습니다:
###1.실행 흐름 제어
-
c/cont
다음 브레이크포인트까지 계속 실행
-
n/next
다음 문까지 실행
-
s/step
함수 내부로 스텝 인
-
o/out
함수 내부에서 스텝 아웃
-
pause
실행 일시 정지
예를 들어 c 를 입력하면 1 과 3 이 출력되고, 그 후 value = 4; 의 위一行에서 정지합니다. 다음으로 n 을 입력하면 value = 4; 에서 정지하고, 그 후 n 을 입력한 다음 s 를 입력하면 fn2 의 함수 본문으로 들어가 함수 본문의 1 행째에서 정지합니다...
주의:디버그 명령은 그다지 친절하지 않습니다. 프로그램이 모두 실행完毕后,さらに c 를 입력하면, 프로세스를 kill 하여 디버깅을 종료해야 합니다
###2.브레이크포인트 설정/클리어
-
sb()/setBreakpoint()
현재 행에 브레이크포인트 설정
-
sb(line)/...
line 행째에 브레이크포인트 설정
-
sb('fn()')/...
함수 본문의 시작에 브레이크포인트 설정
-
sb('script.js', 1)/...
script.js 파일의 1 행째에 브레이크포인트 설정
-
cb()/clearBeakpoint()
브레이크포인트 클리어
주의:이러한 명령은매우 사용하기 어렵습니다. 소스 코드 내에서 debugger; 문을 사용하여 브레이크포인트를 설정하는 것을 권장합니다
###3.상태 정보 확인
-
bt/backtrace
현재 스택 정보 출력
-
list(3)
현재 행의 전후 각 3 행의 소스 코드를 리스트
-
watch('expr')
expr 을 관찰 리스트에 추가
-
unwatch('expr')
관찰 리스트에서 expr 을 삭제
-
watchers
관찰 리스트 내의 모든 식과 값을 리스트
-
repl
디버그의 컨텍스트를 열고, 직접 디버그 코드를 입력
이러한 명령은 매우 유용합니다. watch 로 빈번하게 변화하는 변수/식을 감시하거나, 또는 repl 로 디버그 환경 중의 디버그 환경에 들어가, 무엇을 출력할 수도 있습니다
二.디버그 도구
수동으로 명령을 입력하는 것은 번거로우므로, 디버그 도구가 있습니다:node-inspector. npm 으로 글로벌 설치한 후, 직접 실행:
E:\node\learn\debug>node-inspector
Node Inspector v0.12.7
Visit http://127.0.0.1:8080/?port=5858 to start debugging.
Cannot send response - there is no front-end connection.
브라우저 (브라우저에는Blink 개발자 도구가 필요합니다. 예를 들어 Chrome 과 Opera. FF45 는 불가) 에서 http://127.0.0.1:8080/?port=5858 에 액세스하지만, 아무것도 표시되지 않습니다. 기다려요, 마지막 행에 디버그 대상을 찾을 수 없다고 쓰여 있습니다. 그렇다면, 프로그램을 실행하고 debug 모드로 진입합니다:
node debug ./console.js
// 물론, 프로세스에 SIGUSR1 신호를 전송할 수도 있습니다
// kill -s USR1 [pid]
그 후 브라우저를 리프레시하면, 페이지에 소스 코드가 표시되고, 익숙한 Dev Tools 가 표시됩니다:
(function (exports, require, module, __filename, __dirname) { debugger;
var value = 1;
var fn1 = function() {
debugger;
value = '2';
console.log('fn1');
};
var fn2 = function() {
debugger;
value = 3;
fn1();
console.log('fn2');
};
console.log(1);
process.nextTick(function () {
debugger;
value = 4;
fn2();
console.log(2);
});
console.log(3);
});
코드가 모듈로 래핑되어 있다는 것을 알 수 있습니다. 따라서 디버깅의장점은 node 소스 코드를 엿볼 수 있다는 것으로, 근원을 추구하고 싶다면, 무한히 스텝 인하면 실행 흐름 전체를 끌어낼 수 있습니다. 마찬가지로, 서드파티 모듈 내부의 구체적인 실행 흐름도 쉽게 확인할 수 있어, 소스 코드 분석 시 유용합니다
P.S.여기서 먼저 node-inspector 를 실행한 것은, 순서는 문제없음을 설명하기 위한 것으로, 매번 엄격하게 디버그 대상 프로그램을 먼저 debug 실행할 필요는 없습니다. 원리는 node 가 TCP 디버그 프로토콜을 제공하며, 프로토콜을 통해 프로세스 외부에서 디버깅할 수 있고, node-inspector 는 해당 프로토콜을 통해 디버그 대상 프로세스와 통신하여, debugger 명령을 실행하고, Blink 개발자 도구 인터페이스를 통해 표시합니다
三.정리
실제, 명령을 사용해도 도구를 사용해도, 모두 비교적 번거롭다고 느낍니다. 그리고, 왜 디버깅이 필요한 것일까요?
이유로는, 필자는 2 가지 상황しか 생각나지 않습니다:
- 코드가 엉망 (이상한 오류가 발생하여, 단순한 정적 분석으로는 오류 원인을 찾을 수 없음)
실행 흐름을 알 수 없게 되어, 정리할 필요가 있음
- 소스 코드를 분석하고 싶음
약타입의 js 는 정의에 점프할 수 없으므로, 디버깅을 통해 소스 코드를 분석하는 것은 좋은 선택입니다
디버깅은 실행 중단을 일으키며, 오프라인에서 실행해야 합니다. 개발 중에서 한 줄씩盯着걷는 상황은 극히 드물며, 유닛 테스트를 통해 코드의 견고성을 보장해야 하며, 문제가 발생할 때마다 디버깅해서는 안 됩니다
서버 사이드 프로그램에 대해, 유닛 테스트 (mocha, should, muk, rewire. 내용은 비교적 많고, 나중에 다시 이야기합니다) 외에도, 로그(pm2 는 간단한 오류 로그를自带) 도 매우 필요합니다. 로그를 분석하여 오류 원인을 특정하고, 그에 대응하는 유닛 테스트 케이스를 찾아, 수정합니다
참고 자료
- 『深入浅出 NodeJS』
아직 댓글이 없습니다