이런 것도 필요하신가요? Node.js v0.10.36 API Doc WinHelp

Node.js 가 최근에 v0.12.0으로 업데이트 되었습니다.
그런데 이전에 사용하던 몇가지 모듈과 호환이 되지 않아 사용할 수 없는 상황이네요.

매번 웹에서 API를 확인했는데 이제 웹 문서가 업데이트 버전에 맞춰져, 온라인으로 문서 보는 건 포기
이전 버전의 markdown 문서를 받아 doxygen으로 만들었습니다.

Windows 사용하시는 분께는 편리한…
하지만 Linux 사용하시는 분들께는 미안한…
CHM 포맷으로 만들었습니다.

cfile23.uf.267467385501C6EC0185C9.7z

뭔가 문제가 있나봐요… 그리고… 마크다운을 그냥 doxygen으로 바꿨더니 불편하네요.

html 파일 버전도 추가합니다.

cfile23.uf.267DCF505508622A019879.zip

Node.js에서 cluster 사용시 디버깅

v0.10.36 이 버전에서 cluster 모듈을 사용한 어플리케이션을 –debug 옵션으로 실행하면 fork() 된 worker 들도 같은 debug port를 사용해서 오류가 발생합니다. 그래서 디버깅을 위해 몇가지 작업을 했었는데…


cluster.setupMaster()를 통해 fork 될 worker에게 전달하는 execArgv 값을 master의 process.execArgv 에다가
–debug-port=XXXX 이런 식으로 바꾸어서 실행 되도록 하는 등… 번거로운 작업을 했습니다.


BS의 경우에는 아예 모듈하나 만들어서 debug 모드에서는 cluster를 사용하지 않고 단일 프로세스로, debug 모드가 아닐 경우에는 cluster를 사용하는 멀티 프로세스로 동작하도록 했습니다.


그런데 v0.12.0 에서 이 부분이 변경이 되어 발표되었습니다.


[GitHub의 Node.js cluster.js 소스]를 보면


var workerEnv = util._extend({}, process.env);
var execArgv = cluster.settings.execArgv.slice();
var debugPort = process.debugPort + id;
var hasDebugArg = false;

workerEnv = util._extend(workerEnv, env);
workerEnv.NODE_UNIQUE_ID = ” + id;

for (var i = 0; i < execArgv.length; i++) {
  var match = execArgv[i].match(/^(–debug|–debug-brk)(=\d+)?$/);

  if (match) {
 execArgv[i] = match[1] + ‘=’ + debugPort;
 hasDebugArg = true;
  }
}

if (!hasDebugArg)
  execArgv = [‘–debug-port=’ + debugPort].concat(execArgv);


위와 같은 코드를 볼 수 있습니다.
worker 프로세스를 생성하는 함수 createWorkerProcess() 안에 있는데
내용은


master의 debug port + worker의 id 한 값을 debug port로 무조건 사용한다

입니다. 심지어는 debug 모드가 아닌 경우에도 –debug-port 옵션을 설정합니다!


이것 때문에 debug 모드를 검사하던 방법을 바꿔야 했습니다.


var isDebuggingMode = process[“execArgv”].some((argv) => {
  return /^(–debug|–debug-brk)(=\d+)?$/.test(argv);
});

그런데 여기서 드는 의문점…


TCP/IP 의 port 라는 것은 0 ~ 65535 일 수 밖에 없는데 (2바이트의 정수)…
cluster.fork()로 생성되는 worker의 id 는 무조건 증가만 되게 되어 있어서


cluster.fork = function(env) {
  cluster.setupMaster();
  var id = ++ids;
  var workerProcess = createWorkerProcess(id, env);
  var worker = new Worker({
    id: id,
    process: workerProcess
  });
  …

[Node.js cluster 문서의 cluster event “exit” 설명]에 나오는 아래 예제처럼 작성할 경우


cluster.on(‘exit’, function(worker, code, signal) {
  console.log(‘worker %d died (%s). restarting…’,
    worker.process.pid, signal || code);
  cluster.fork();
});

결국은 debug port가 65535가 넘어가는 사건이 발생하게 됩니다.


결론




  1. Node.js의 cluster 모듈 사용할 때에는 worker를 동적으로 계속 생성하지 않도록 한다.

  2. 동적으로 fork()할 일이 있는 어플리케이션은 cluster 모듈을 사용하지 말고 child_process 모듈을 사용한다.

  3. port 공유가 필요하고 동적으로 fork()를 해야 하는 어플리케이션은 C++로 직접 구현해서 붙인다
    (또는 잘 찾으면 이런 걸 한방에 해결하는 module이 있을지도)

 

Typescript 컴파일 오류, TS2082, TS2087, tsc.exe exited with code 1

컴파일하면 오류나고 다시 빌드하면 빌드할게 없다고 하고…

뭔가 찝찝해서 옵션에서 빌드 정보를 최대한 자세하게 출력하도록 설정한 뒤 다시 빌드를 했습니다.

역시 컴파일 오류가 하나 섞여 있었네요.

문제의 오류는 …

Visual Studio 2013의 기본 Typescript 라이브러리인 lib.d.ts와 node.d.ts가 충돌나서
clearTimeout() 함수가 파라미터 number인 것과 NodeTimer인 것이 생겨버려
컴파일러가 뭐가 뭔지 모르겠다는 것이었습니다.

실행 환경이 웹브라우저가 아니라 Node.js이므로 lib.d.ts의 것이 필요 없기 때문에 빼 버리고 싶었는데…
tsc.exe 명령 도움말에서 힌트를 찾을 수가 없었네요.

숨겨진 옵션으로 –nolib가 있다는 것을 알게 되었습니다.
njsproj 파일에 <TypeScriptIncludeDefaultLib>false</TypeScriptIncludeDefaultLib> 을 넣어도 됩니다.

간단한 테스트 후에 해결했습니다.

  1. .njsproj 파일에 <TypeScriptIncludeDefaultLib>false</TypeScriptIncludeDefaultLib> 추가
  2. Visual Studio 설치 경로/Common7/IDE/CommonExtensions/Microsoft/TypeScript 하위의 lib.d.ts를
    프로젝트 경로/Scripts/typings/node 안으로 복사
  3. 프로젝트에 복사한 lib.d.ts를 포함
  4. 프로젝트에 포함시킨 lib.d.ts에서 문제의 함수 선언 삭제
    clearTimeout, setTimeout
  5. 다시 빌드
  6. 에러 없음 확인
정말 core 한 부분만 사용하시고 싶으시면 [GitHub TypeScript 소스]에서 lib.core.d.ts 만 받으셔서 사용하시면 됩니다.

jQuery 를 사용해서 form 데이터를 자바스크립트 오브젝트로 만드는 예제

jQuery에 있는 serializeArray 를 사용해서 아래와 같은 코드를 추가합니다.

$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || ”);
} else {
o[this.name] = this.value || ”;
}
});
return o;
};

그리고 호출할 때에는

var someObject = $(“#someForm”).serializeObject();
와 같이 사용합니다.

Node.js에서 console 출력이 표시되기 전에 프로그램이 종료됩니다.

아래와 같은 코드를 실행해 보았습니다.
실행 환경은 Windows 에서 Nodeclipse 플러그인 설치한 Eclipse입니다.

(function() {
    var i;
    for (i = 0; i < 100; ++i) {
        console.log(i);
    }
    process.exit(0);
}());

당연히 마지막에 99가 찍히리라… 생각되겠지만
콘솔에는 0 하나 달랑 출력되고 프로그램은 종료되었습니다.
현상의 원인은 console 출력이 완료되기 전에 process.ext()에 의해서 프로그램이 종료되었기 때문이죠.
이걸 출력하기 위해 setTimeout()을 사용하는 건 좀 이상하고…
그래서 아래와 같은 방법으로 시도를 했습니다.

(function() {
    var i;
    for (i = 0; i < 100; ++i) {
        console.log(i);
    }
    process.stdout.write("", function() {
        process.exit(0);
    });
}());

원하는대로 출력되었습니다.
그런데 이런 증상은 Windows에서만 발생합니다.
첫번째 소스로도 Linux 에서는 원하는 동작을 합니다.
두번째 소스도 마찬가지 입니다.
그 이유를 [Node.js 공식페이지]에서는 아래와 같이 설명합니다.


process.stderr과 process.stdout은 다른 스트림과 달리 보통 blocking으로 동작합니다.

  • 보통의 파일 또는 TTY에 출력할 경우 blocking

  • pipe로 사용할 경우에는

    • Linux/Unix에서는 blocking

    • Windows에서는 non-blocking

그렇군요… 그래서 console의 결과를 pipe를 통해 IDE로 가져오게 되면 Windows에서 non-blocking으로 동작하는 것입니다.