일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 가상화
- Friendship
- 구글 앱 엔진
- 증강현실
- 파이썬
- 동아리
- 패턴 인식
- Bidirectional Associative Memory
- 나르왈프레오
- BAM
- Neural Network
- Python
- 인공지능
- 멤버십
- 패턴인식
- 갤럭시탭S8울트라
- 물걸레자동세척로봇청소기
- hopfield network
- SSM
- 삼성
- 삼성소프트웨어멤버십
- 신경회로망
- 하이퍼바이저
- 물걸레로봇청소기추천
- 고려대학교
- 삼성전자 소프트웨어멤버십 SSM
- 신경망
- 빅데이터
- NarwalFreo
- Google App Engine
- Today
- Total
정보공간_1
[6기 수원 김병연] Node.js 디버깅 및 실제 함수의 동작 이해 본문
개발 향상성을 위한 디버깅
예전에 저는 프로젝트의 서버를 Node.js로 빠르게 개발해야 하는 급박한 상황에 쳐해졌습니다.
따라서 구글링을 통해 마구잡이로 Node.js를 배우게 되었고
console.log를 통해 값을 출력하면서 디버깅을 했었던 기억이 있습니다.
이 글을 보시는 분들은 대부분 C 언어로 개발을 해본 경험이 있으실텐데
디버깅을 제대로 하면 얼마나 생산성이 향상되는지는 잘 아실겁니다.
특히 알고리즘 문제 풀 때 그것은 축복이죠.
Node.js 의 디버깅
보통 서버사이드 스크립트의 디버깅은 사실 접하기가 쉽지 않은데요.
Node.js 의 디버깅은 어떻게 해야 하는걸까요?
3년전에 나왔고 지금도 계속 활발히 업데이트 되고있는 node-inspector 라는 툴도 유명합니다만
이번화에서는 널리 쓰이고 있는 Eclipse를 통해 디버깅을 해보겠습니다.
NTS(Node Tool Suite)를 설치하시거나, Eclipse가 이미 있으신 분은 Help-Install New Software 메뉴에서 Nodeclipse를 설치하시면 됩니다.
NTS 다운로드 : http://sourceforge.net/projects/nodeclipse/
(Windows를 지원하며 MAC도 지원한다고 하네요.)
이제 간단히 테스트 해볼 자바스크립트 파일을 만들어 봅시다.
testFile.js
//1만을 더해주는 함수 function numberPlus(number){ //1만번을 돌면서 number를 증가시킵니다. for(var i=0; i<10000; i++){ number++; } //number +10000 이 출력되어야 합니다. console.log("testFile : number +10000 : ",number); return number; } numberPlus();
숫자를 1만 증가시켜주는 함수를 만들고 실행해보았습니다.
testFile : number +10000 : NaN
그런데 뭔가 이상하군요. 출력값이 NaN이에요.
연산과정에서 뭔가 잘못된 입력을 받았군요.
For문 안쪽 number가 증가하는 부분 왼쪽을 더블클릭해서 파란색 점을 만들고
F11을 눌러서 디버깅을 시작해 봅시다.
F8을 누르면 계속 진행을 해서 포인트에 멈추게 되는데요.
Varuables에서 변수를 볼 수도 있지만 Expressions에서 원하는 변수를 직접 입력해 볼 수도 있습니다.
number에 대한 값이 Undefined 네요.
아, 그러고 보니 number를 매개변수로 넘겨주지 않았습니다.
이제 F8을 눌러서 다른 브레이크 포인트를 찾거나
F7을 눌러서 이 함수 밖으로 나갈 수도 있습니다.
이제 numberPlus에 숫자를 넣어주면 됩니다.
그리고 이제 Node.js의 큰 특징인 Non-Blocking 에 대해 구체적으로 알아보기 위해서
이 함수에 약간의 딜레이를 줘 봅시다.
testFile.js
//1만을 더해주는 함수 function numberPlus(number){ //이번엔 10ms의 딜레이를 줘 봅시다. setTimeout(function(){ for(var i=0; i<10000; i++){ number++; } console.log(“testFile : number +10000 : “,number); return number; },10); } var numberTest=10; numberTest=numberPlus(numberTest); console.log(numberTest);
Node.js 동작의 특성
방금 위 소스에서는 어떤 값이 출력될까요?
testFile : number +10000 : 10010
10010
이렇게 출력되어야 할 것 같은데요.
이것이 바로 Node.js를 처음 접하시는 분들이 가장 많이 하는 실수 중 하나입니다.
왜냐하면 예상을 깨고 undefined가 먼저 출력되기 때문이죠.
이전 포스팅이 기억나시나요?
Node.js는 Non-Blocking / Event-Driven 라고 했었습니다.
Node.js 는 클라이언트가 기다리지 않도록 하기 위해 이벤트 핸들러가 일이 끝나면 알려준다고 했었는데요.
즉 이번에는 numberPlus() 함수가 실행되던 도중
console.log(numberTest);
가 먼저 출력되어 버렸기 때문입니다.
이쯤 되면
아, 저 함수에서 시간이 오래 걸렸기 때문에 즉
“numberTest값이 제대로 들어오기 전에 console.log(numberTest)가 실행되서 undefined가 떳구나.”
같은 생각이 들기 마련입니다.
저 또한 오랜 시간 이렇게 생각했었습니다.
“Node.js 의 모든 함수는 비동기구나…”
그런데 과연 이게 딜레이 때문일까요?
그러니까, numberPlus() 함수를 더 오랜시간동안 기다리면 numberTest에 undefined가 아닌 10010이 들어가게 될까요?
그렇지 않습니다. numberPlus() 함수는 비동기 함수인 setTimeout 때문에 비동기로 실행 된 것입니다.
이는 시간을 10이 아닌 0으로 주고 해도 같은 결과가 나오므로 확인 해 볼 수 있습니다.
그럼 바꿔 생각해서 setTimeout 함수가 없을 때 시간이 많이 걸리는 함수에 대해서
동기적으로 실행되는지를 확인해 봅시다.
testFile.js
//1만을 더해주는 함수 function numberPlus(number){ // setTimeout(function(){ for(var i=0; i<10000; i++){ //시간을 많이 걸리게 해봅니다. console.log(); number++; } console.log("testFile : number +10000 : ",number); return number; // },10); } var numberTest=10; numberTest=numberPlus(numberTest); console.log(numberTest);
실제로 위처럼 setTimeout을 제거하고 for문에 console.log() 를 넣어서 시간을 많이 걸리게 해보면
console.log(numberTest);
가 먼저 출력되는 것이 아니라
numberPlus() 함수 에서 Blocking이 되어
testFile : number +10000 : 10010
가 먼저 출력 되는 것을 확인할 수 있습니다.
그럼 setTimeout를 포함한 numberPlus() 함수가 처리 된 다음
1만이 더해진 변수를 출력하고 싶으면 어떻게 해야할까요?
Callback을 이용하면 됩니다.
Callback 함수를 작성하는 방법은 다음과 같습니다.
1.함수를 만들때 매개변수로 callback을 넣는다.
2.return 대신 callback(); 함수를 사용해서 결과값을 전달한다.
3.함수를 사용하면서 매개변수로 callback을 받아 처리한다.
백문이 불여일견이죠. 방금 전 그 함수를 Callback을 이용해 다시 만들어 보겠습니다.
testFile.js
//1만을 더해주는 함수 function numberPlus(number,callback){ //약간의 딜레이를 줘 봅시다. setTimeout(function(){ for(var i=0; i<10000; i++){ number++; } console.log("testFile : number +10000 : ",number); //return number; 대신 콜백함수를 통해 전달합니다. callback(number); },10); } var numberTest=10; numberPlus(numberTest,function(number){ //callback을 통해 받은 number를 출력합니다. console.log(number); });
testFile : number +10000 : 10010
10010
이런식으로 Node.js 대부분의 함수는 비동기로 처리되므로
동기적인 처리를 위해서는 Callback을 사용해야 합니다.
이런 경우는 어떨까요?
1.A파일을 가져오고
2.그 파일의 내용을 읽은 다음
3.해당 내용을 다른 파일 B에 쓴다.
를 생각해 봅시다.
2번 처리는 1번의 결과를 바탕으로 하며
3번 처리는 2번의 결과를 바탕으로 합니다.
그런데 Callback의 시점은 순차적이지 않습니다.
그렇기 때문에 겹쳐서 사용해야 하는데요.
위 경우는 다행히 두번 정도 중첩된 Callback을 사용하면 되겠습니다만,
더 복잡한 경우에는 어떻게 될까요?
위 그림과 같이 매우 깊은 형태의 코드를 볼수 있게 되며
또 이런식으로 코딩 하게 되면 유지보수와 디버깅이 힘들게 됩니다.
하지만 Async나 Step 같은 모듈을 사용하면 이 문제를 해결 할 수 있습니다.
Callback이 중첩된 형태
var fs = require('fs'); var path = './async.txt'; fs.stat(path, function(err, stats) { if (stats == undefined) { fs.readFile(__filename, function(err, content) { var code = content.toString(); fs.writeFile(path, code, function(err) { if (err) throw err; console.log('async.txt created!'); }); }); } });
Async 모듈을 통해 동기적으로 처리하도록 한 형태
var fs = require('fs'); var async = require('async'); var path = './async.txt'; async.waterfall([ function(cb) { fs.stat(path, function(err, stats) { if (stats == undefined) cb(null); else console.log('async.txt exists'); }); }, function(cb) { fs.readFile(__filename, function(err, content) { var code = content.toString(); cb(null, code); }); }, function(code, cb) { fs.writeFile(path, code, function(err) { if (err) throw err; console.log('async.txt created!'); }); } ]);
비록 코드는 길어졌지만 알아보기가 쉬워졌습니다.
중첩이 많을수록 훨씬 가독성이 높아지는 것을 확인 할 수 있습니다.
정리를 해보면
Node.js는 많은 경우 비동기로 처리되며 위 처럼 Callback 처리를 해 주어야 합니다.
그런데 Node.js의 대부분의 기능이 비동기로 처리 된다고 해서
모든 함수가 비동기인 것은 아닙니다.
이것을 이해하는 것은 중요합니다.
즉 모든 함수가 비동기라고 생각하고 코딩 하면 안됩니다.
기본적으로 Node.js는 Single Thread 이므로 한 함수가 오랜 시간 Blocking 되어버리면
굉장한 성능 저하를 가져 올 수 있기 때문입니다.
또한 반대로, 전통적인 동기식 코딩스타일을 잊고
비동기식 사고방식을 가져야 한다는 것을
이해하고 시작하면 나중에 고생하는 일이 없게 됩니다.
'IT 놀이터' 카테고리의 다른 글
[6기 수원 김병연] Node.js Server Testing (0) | 2014.12.13 |
---|---|
[6기 부산 박천경] mixare(증강현실) opensource 분석 #1 (0) | 2014.10.26 |
[6기 부산 박천경]SDL (Simple DirectMedia layer) #3 (0) | 2014.10.09 |
[UX research] 사용자 리서치를 간략하게 설명해봅시다. (0) | 2011.07.02 |