[cookbook] node exception error handling (Node.JS가 죽어? 당연히 죽지 않게 해야죠.)

소개

입문자의 눈높이에 맞게 Node.JS 기본 제작구성에 필요한 것을 재구성해 봅니다.

웹서버 사용시 프로세스, 쓰레드가 죽더라도 항상 안심을 했습니다. 왜냐하면, 웹서버가 또다른 프로세스나 쓰레드를 다시 구현해주기 때문입니다. 개발자는 웹서버를 띄우고 제작된 프로세스가 죽을 염려 할 필요가 없습니다. 그러나 Node.js으로 제작한 어플리케이션은 다릅니다. 왜냐하면 node에서 에러코드를 만나게 되면 프로세스는 바로 에러를 보여주며 죽어버리기 때문입니다. 아마도 입문자들이 테스트 과정에서 느껴보셨을 황당함은 에러를 발생시킨 자바스크립트 코드 한줄이면 Node.JS 프로세스가 죽는 현상일 것입니다. 이때 가장 필요한 부분은 Exception 처리입니다. 절대적으로 필요하며 필히 개발방법을 아셔야 합니다.

개요

Node.js 문서를 보시면 아래 구절을 확인할 수 있습니다.

Event: 'uncaughtException'
http://nodejs.org/docs/v0.6.7/api/all.html#event_uncaughtException_
Especially for server programs that are designed to stay running forever, uncaughtException can be a useful safety mechanism.

영원히 실행될 수 있도록 디자인된 서버프로그램, 안전한 메카니즘을 갖추기 위해서는 uncaughtException Handler의 작성은 필수적이라는 것입니다.

그럼 아래 내용에 대해서 알아보겠습니다.

  1. uncaughtException 사용시 node 에 미치는 영향
  2. try ~ catch 사용시 node에 미치는 영향

Code

uncaughtException

아래코드에 대한 설명

process.on('uncaughtException', function (err) {
 console.log('Caught exception: ' + err);
});
 
setTimeout(function () {
 console.log('자.. 프로세스는 죽지 않았습니다.');
 
 setTimeout(function() {
   console.log('난 아직도 죽지 않았습니다.');
 }, 5000); // 5초 뒤에 또 실행
}, 5000); // 5초뒤에 실행
 
// 강제적으로 프로세스 에러 발생시킴
// 존재하지 않는 함수 실행
nonExistentFunc(); // or tow new Error('나 에러!!');
 
// 에러지점 이하의 코드는 실행되지 않습니다.
console.log('이 부분은 console에 보여지지 않습니다.');

실행결과

# node test4.js 
Caught exception: ReferenceError: nonExistentFunc is not defined
자.. 프로세스는 죽지 않았습니다.
난 아직도 죽지 않았습니다.

위 코드에서 Exception Handler를 등록했기 때문에, nonexistentFunc() 에러코드를 만나더라도 프로세스는 바로 죽지 않습니다. 결국 이 프로세는 setTimeout으로 event loop에 등록한 callback이 모두 실행되고 나면 프로세스는 죽게 됩니다.

try ~ catch

uncaughtException Handler등록을 하지 않아도 event loop에 등록되어 있는 모든 event가 실행될때까지 프로세스를 죽이지 않을 수 있습니다.

setTimeout(function () {
 console.log('This will still run.');
 
 setTimeout(function() {
   console.log('This will still run~~');
 }, 3000);
}, 3000);
 
// 강제에러 -> try 로 해소함.
try {
 nonExistentFunc();
} catch (e) {
 // tow 할경우에는 uncaugntException을 설정해야만
 // 등록된 callback이 모두 실행될때까지 프로세스가 죽지 않습니다.
 // 즉, try ~ catch 문은 uncaughtException과 짝을 이루어 같이 사용하셔야 합니다.
 // tow new Error(e);    
}
 
setTimeout(function() {
 console.log('2 second');
}, 2000);

실행결과

# node test3.js 
2 second
This will still run.
This will still run~~

실습

자 그럼 실제 nodejs.org 메인화면에 소개된 웹서버띄우는 코드를 안정적이게 변형해 보겠습니다.

기존코드

아래 코드는 자바스크립트 1줄이라도 에러를 발생하면 Node 어플리케이션은 죽게 됩니다.

var http = require('http');
http.createServer(function (req, res) {
 res.writeHead(200, {'Content-Type': 'text/plain'});
 
 // 만약 여기서 자바스크립트 코드가 에러발생되었다고 가정시
 nonExistFunctionCall();
 
 res.end('Hello World\\n');
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

exception 적용한 안정한 코드

아래 코드는 자바스크립트 1줄의 에러를 만나도 Node 어플리케이션은 죽지 않게 됩니다.

// Exception Handler 등록
process.on('uncaughtException', function (err) {
 console.log('Caught exception: ' + err);
 
 // 추후 trace를 하게 위해서 err.stack 을 사용하여 logging하시기 바랍니다.
 // Published story에서 beautifule logging winston 참조
 
});
 
var http = require('http');
http.createServer(function (req, res) {
 res.writeHead(200, {'Content-Type': 'text/plain'});
 
 // 만약 여기서 자바스크립트 코드가 에러발생되었다고 가정시
 nonExistFunctionCall();
 
 res.end('Hello World\\n');
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

결론

Node.js의 수많은 third party module을 배워서 프로그래밍 하는것도 중요하지만, 기본을 익히는것이 가장 중요하다고 생각합니다.

KIN 플~

추천 관련글