Node.js 프로젝트 개요 1

본 문서는 그동안의 Node.js 기여 경험을 바탕으로 Node.js 프로젝트를 처음 시작하는 사람들을 위해 간략한 개요를 전달하고자 한다. 물론 프로젝트 내용은 지속적으로 변경되고 있으며 현 시점에서 유효한 내용이다. 그러나 어느 정도 견고하게 확정되어 오랫동안 통용되고 있는 내용에 대해 작성하고자 한다.

Node.js Core의 용어

Node.js 에서의 각 요소를 가르키는 용어는 여러가지로 통용이 되어왔으나 아래와 같이 공식적으로 정리되었다.

  • Built-in(s): Node.js 는 JavaScript 부분과 C++ 부분으로 이루어져 있다. Node core를 이루는 기본적으로 JavaScript 코드를 Builtins 혹은 Builtin module 이라고 부른다.
  • Bindings: Builtins 에서 사용하는 API 로서 Native 쪽에서 실행되는 부분을 뜻한다. Native 코드는 C++로 이루어져 있다. C++ 코드가 직접적으로 사용자 영역으로 노출되는 경우는 없으며 JavaScript 부분에서 사용자 인터페이스를 거쳐서 사용된다.

일반적으로 JavaScript 부분은 사용자 인터페이스를 노출하고 Bindings를 부르기 전에 입력된 Arguments에 대한 Validation을 처리한다. C++ 코드내에서는 별도의 Validation은 수행하지 않고 정해진 Arguments가 들어왔는지에 대해서 Assertion을 수행한다.

  • addons: Node.js 에 동적으로 링크되는 Shared library로 Node-API, NAN 를 통해 구성되고 API를 제공한다.

프로젝트 소스 구성

lib

  • lib - JavaScript builtins 에 해당하는 코드가 포함된다. lib/**/*.js 하위의 코드이다. 모든 모듈은 외부 인터페이스 영역과 internals 영역으로 나뉜다. 이러한 구분을 통하여 internal 영역의 코드가 사용자에게 노출되어 변조되는 것을 방지한다. internal/bootstrap과 internal/main 은 Node.js 의 Builtins를 Bootstrap하는 코드와 옵션별 Entry 코드를 포함하고 있다.

src

  • src - C++ 영역에서 구현된 src/node_*.cc 의 이름으로 된 bindings 코드와 node_api.h 파일에 정의된 addons (Node-API)지원 인터페이스 코드를 제공한다. node_main.cc는 Node.js 의 프로그램 Entry 이며, 각 JavaScript Context 별로 생성된 환경정보는 env.cc 의 코드에서 정의된 Environment 클래스에 의해 다룬다.

deps

  • deps - Node.js 가 사용하고 있는 외부 Dependency들을 다룬다. v8, libuv, http_parser, zlib, openssl 등이 있다. git submodule이나 subtree로 다루지 않고 직접 코드를 copy하여 사용한다. 빌드를 위해 각 프로젝트의 build config를 직접 부르지 않고 gyp로 구성한 build config 를 각각에 추가해 프로젝트 root의 node.gyp로 부터 읽는다. dependency가 업데이트 할때 버전 정보를 별도의 header로 관리하도록 되어있다. (src/*_version.h 파일) 이를 통해 Node.js 에서 각 dependency의 정보를 확인할 수 있게 한다. 업데이트 스크립트는 tools/dep_updaters/update-*.sh 에서 확인할 수 있다.

test

  • test - Node Core에 대한 Test를 다룬다. test/parallel 내 테스트 코드가 주로 사용되는데, 병렬로 실행되어도 서로 영향을 미치지 않은 코드를 담고 있다. 이에비해 test/sequential은 순차적으로 실행되어야하는 테스트를 다룬다. test/cctest는 gtest로 구성하여 Node.js embedder를 위한 테스트 코드, test/addons 은 Node-API에 대한 테스트를 포함한다. test/wpt는 Node.js의 Web 호환성 테스트를 위해 구성되어있는데, Web Platform Test의 특정 버전을 가져와 사용한다. wpt 버전을 업데이트하기 위한 tool과 Node.js에서 WPT test harness가 동작하기 위한 환경 설정을 한다.
    • test/common: 해당 폴더는 Node.js test 구성을 위한 툴을 다루고 있다. 해당 툴의 사용은 선택적인것이 아니고 반드시 모든 테스트가 test/common/index.js를 호출해줘야한다. 각 테스트를 Node.js 런타임으로 직접 실행할 수도 있지만 기본적으로 Worker Thread에서 동작하도록 되어있다. 런타임 실행시 특별한 CLI option이 전달되야할 때는 Flags 커멘트 라인을 테스트 코드 첫줄에 작성하여 전달할 수 있도록 한다.
1
// Flags: --no-warnings --expose-gc --expose-internals

benchmark

  • benchmark - 연산성능을 측정하기 위한 코드를 다루고 있다. compare.js 는 비교하고자 하는 두개의 executable을 파라미터로 받으며, local build 버전과 global에 설치된 특정 Node.js 버전을 전달함으로서 하나의 코드상에서 어떤 성능 변화가 있는지 확인 가능하다.

벤치마크 수행결과 읽는 방법

벤치마크에서의 성능차이는 실제 변경 사항 자체보다 각 환경에 따라 발생하는 임의의 변수들로 인해 달라질 수 있다. 그렇기 때문에 수행결과의 신뢰성 나타내는 지표를 확인할 필요가 있다.

1
2
3
4
5
6
7
8
9
10
11
                                confidence improvement accuracy (*)   (**)  (***)
util/priority-queue.js n=100000 -2.50 % ±4.41% ±5.87% ±7.64%
fs/bench-writeSync.js n=100000 *** 116.41 % ±9.35% ±12.49% ±16.36%
fs/bench-readSync.js n=100000 type=1 0.46 % ±6.13% ±8.16% ±10.62%

Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case, there are 1 comparisons, you can thus
expect the following amount of false-positive results:
0.05 false positives, when considering a 5% risk acceptance (*, **, ***),
0.01 false positives, when considering a 1% risk acceptance (**, ***),
0.00 false positives, when considering a 0.1% risk acceptance (***)

벤치마크를 수행하면 위와 같은 결과를 확인 할 수 있다. 이때 먼저 확인해야 할 것은 confidence다. confidence에 별표 (*, **, ***) 가 없는 모든 줄은 무시한다.

util/priority-queue.js 케이스를 해석하면 -2.50%-4.41%와 -2.50%+4.41% 사이라고 가정할 수 있으며, 해당 내용은 5%의 확률로 틀린 결과 (False Positives) 일 수 있다는 뜻이다. Node.js 에서는 일반적으로 별표가 2개 혹은 3개 정도의 risk 허용범위에 있을때 개선, 퇴보 여부를 신뢰할 수 있는 데이터라고 생각하고 있다.

typings

  • typings - Node.js 코드 작성시 Type을 확인할 수 있게 하는 용도로 작성된 *.d.ts 파일을 포함한다. JavaScript 자체는 타입정보를 제공하지 않지만 이곳의 파일들이 lib 폴더내 모듈의 외부 인터페이스 파일들과 매칭된다. vscode 와 같은 툴에서 개발시 타입을 확인 할 수 있고 code complition과 같은 기능을 제공할 수 있다.

doc

  • doc - API 도큐먼트를 빌드하기 위한 원본 md파일과 Node.js에 기여를 할 때 알아야 할 여러 정보를 확인 할 수 있다. API 도큐먼트 빌드를 목적으로 하기 때문에 따라야할 convention이 존재하며 수정 후 $ make format-md 혹은 $ tools/lint-md/lint-md.mjs 이용해 lint 가능하다. API 도큐먼트의 API는 알파벳 순으로 작성되야하며 내부/외부 링크는 md에 직접 작성하지 않고 문서의 최하단에 주석으로 작성되야한다. Node.js의 CLI Option이 수정되면 doc/node.1 의 파일을 업데이트 한다. 그렇게 함으로서 Unix 계열의 운영체제에서 man 유틸을 통해 명령어 문서에 접근할 수 있도록 한다.
Share