{ "source": "doc-ko/api/all.markdown", "miscs": [ { "textRaw": "About this Documentation", "name": "About this Documentation", "type": "misc", "desc": "
이 문서의 목적은 Node.js API를 레퍼런스부터 개념적인 부분까지 광범위하게 설명하는\n데 있다. 각 섹션은 내장(built-in) 모듈이나 고수준의 개념을 설명한다.\n\n
\n프로퍼티 타입, 메서드 아규먼트, 이벤트 핸들러의 아규먼트은 제목 밑에 리스트로 상세하게\n적혀있다.\n\n
\n각 .html
문서는 구조화되어 같은 정보를 담고 있는 .json
과 대응된다. 이 기능은\n실험적이고 문서를 프로그래밍 적인 것으로 다루는 IDE나 다른 유틸리티의 이점을 위해서\n추가되었다.\n\n
각 .html
과 .json
파일은 node의 소스트리에서 doc/api/
폴더 안에\n대응되는 .markdown
파일로 생성된다. 이 문서는 tools/doc/generate.js
\n프로그램을 사용해서 생성한다. HTML 템플릿은 doc/template.html
에 있다.\n\n
문서 전체에서 섹션의 안정성 지표를 볼 것이다. Node.js API는 아직도 조금씩 바뀌고\n있고 성숙도에 따라 어떤 부분은 다른 부분보다 더 신뢰할 수 있다. 어떤 것들은 그렇게\n증명되었고 전혀 변경될 가능성이 없어 보이는 것에 의존하고 있다. 다른 것들은 새롭고\n실험적이거나 위험하다고 알려져 있거나 새로 디자인하고 있다.\n\n
\n안정성 지표는 다음과 같이 표시한다.\n\n
\nStability: 0 - Deprecated\n이 기능은 문제의 소지가 있는 것으로 알려졌고 변경될 예정이다.\n여기에 의존하지 말아라. 이 기능을 사용하면 경고나 나올 것이다.\n하위호환성을 기대하지 말아야 한다.
\nStability: 1 - Experimental\n이 기능은 최근에 도입되었고 차기 버전에서 변경되거나 제거될 것이다.\n이 기능을 시험해보고 피드백을 주기 바란다. 이 기능이 당신에게 중요한 유즈케이스를 제공한다면\n노드 코어팀에게 말해줘라.
\nStability: 2 - Unstable\nAPI가 안정화되는 과정에 있지만 아직 안정적이라고 고려될 만큼 충분한\n실세계의 테스트를 거치지 않았다. 합당하다면 하위호환성은 유지될 것이다.
\nStability: 3 - Stable\nAPI가 충분히 검증되었지만 기반이 되는 코드의 정리때문에 마이너한 변경이\n있을 수 있다. 하위호완성이 보장된다.
\n+Stability: 4 - API Frozen\n이 API는 프로덕션레벨에서 광범위하게 테스트되었고\n변경될 여지가 거의 없다.
\n+Stability: 5 - Locked\n심각한 버그가 발견되지 않는한 이 코드는 절대 변경되지 않을 것이다.\n이 영역에서 변경사항을 제안하지 말아라. 아마도 거절될 것이다.
\n"
},
{
"textRaw": "JSON Output",
"name": "json_output",
"stability": 1,
"stabilityText": "Experimental",
"desc": "마크다운의 모든 HTML파일은 같은 데이터를 가진 대응되는 JSON 파일이 있다.\n\n
\n이 기능은 node v0.6.12에서 추가되었고 실험적인 것이다.\n\n
\n", "type": "misc", "displayName": "JSON Output" } ] }, { "textRaw": "Synopsis", "name": "Synopsis", "type": "misc", "desc": "Node로 작성한 'Hello World'를 응답하는 web server 예제:\n\n
\nvar http = require('http');\n\nhttp.createServer(function (request, response) {\n response.writeHead(200, {'Content-Type': 'text/plain'});\n response.end('Hello World\\n');\n}).listen(8124);\n\nconsole.log('Server running at http://127.0.0.1:8124/');
\n서버를 실행하려면 example.js
파일에 코드를 입력하고 node 프로그램으로 실행해라.\n\n
> node example.js\nServer running at http://127.0.0.1:8124/
\n문서의 모든 예제는 비슷하게 실행할 수 있다.\n\n
\n" }, { "textRaw": "Global Objects", "name": "Global Objects", "type": "misc", "desc": "이 객체들은 모든 모듈에서 이용할 수 있다. 이 객체들 중 일부는 실제로 전역 범위를 가지지\n않고 모듈 범위를 가진다. - 이는 따로 표시할 것이다.\n\n
\n", "globals": [ { "textRaw": "global", "name": "global", "type": "global", "desc": "브라우저에서 최상위 범위는 전역 범위이다. 이는 브라우저의 전역 범위에서 var something
가\n전역 변수를 정의한다는 것을 의미한다. Node에서는 다르다. 최상위 범위는 전역 범위가 아니다.\nNode 모듈에서 var something
는 해당 모듈의 지역 범위가 된다.\n\n
process 객체. [process object][]부분을 봐라.\n\n
\n" }, { "textRaw": "console", "name": "console", "type": "global", "desc": "stdout와 stderr에 출력하는 데 사용한다. [console][]부분을 봐라.\n\n
\n" }, { "textRaw": "Class: Buffer", "type": "global", "name": "Buffer", "desc": "바이너리 데이터를 다루는데 사용한다. [buffer section][]을 봐라.\n\n
\n" }, { "textRaw": "clearInterval(t)", "type": "global", "name": "clearInterval", "desc": "이전에 setInterval()
로 생성된 타이머를 멈춘다. 콜백은 실행하지 않을 것이다.\n\n
timer 함수는 전역 변수이다. [timers][]부분을 봐라.\n\n
\n" }, { "textRaw": "console", "name": "console", "stability": 4, "stabilityText": "API Frozen", "type": "global", "desc": "stdout와 stderr에 출력하기 위해 사용한다. 대부분의 웹 브라우저가 제공하는 console\n객체의 기능과 유사하게 stdout이나 stderr로 출력한다.\n\n
\n목적지가 터미널이거나 피일일 때는(빠르게 종료되는 경우 메시지를 잃어버리지 않기 위해서)\nconsole 기능은 동기적이고 파이프인 경우(장시간 블락킹하는 것을 피하기 위해)에는 비동기이다.\n\n
\n즉, 다음 예제에서 stdout은 넌블락킹이고 stderr은 블락킹이다.\n\n
\n$ node script.js 2> error.log | tee info.log
\n일반적인 사용해서 엄청난 양의 데이터를 로깅하지 않는한 블락킹과 넌블락킹을 걱정할 필요는 없다.\n\n\n
\n", "methods": [ { "textRaw": "console.log([data], [...])", "type": "method", "name": "log", "desc": "새로운 라인으로 stdout에 출력한다. 이 함수는 printf()
와 같은 방식으로 여러 아규먼트를\n받는다. 예제:\n\n
console.log('count: %d', count);
\n첫 문자열에 포매팅 객체가 없으면 각 아규먼트에 util.inspect
를 사용한다.\n더 자세한 내용은 [util.format()][]를 봐라.\n\n
console.log
와 동일하다.\n\n
console.log
와 같지만 stderr에 출력한다.\n\n
console.error
와 같다.\n\n
obj
에 util.inspect
를 사용하고 결과 문자열을 stdout에 출력한다.\n\n
시간을 마킹한다.\n\n
\n", "signatures": [ { "params": [ { "name": "label" } ] } ] }, { "textRaw": "console.timeEnd(label)", "type": "method", "name": "timeEnd", "desc": "타이머를 종료하고 결과를 기록한다. 예제:\n\n
\nconsole.time('100-elements');\nfor (var i = 0; i < 100; i++) {\n ;\n}\nconsole.timeEnd('100-elements');
\n",
"signatures": [
{
"params": [
{
"name": "label"
}
]
}
]
},
{
"textRaw": "console.trace(label)",
"type": "method",
"name": "trace",
"desc": "현지 위치의 stderr에 스택트레이스를 출력한다.\n\n
\n", "signatures": [ { "params": [ { "name": "label" } ] } ] }, { "textRaw": "console.assert(expression, [message])", "type": "method", "name": "assert", "desc": "expression
가 false
이면 message
로 AssertionError를 던지는 [assert.ok()][]와\n같다.\n\n
process
객체는 전역객체이고 어디서나 접근할 수 있다.\n이 객체는 [EventEmitter][] 인스턴스이다.\n\n\n
프로세스가 종료될 때 발생한다. 이 이벤트는 모듈의 상태를 상수시간으로 확인하는데 좋은\n훅(hook)이다.(유닛테스트에서처럼) 메인 이벤트루프는 'exit' 콜백이 종료된 후에는 더이상\n실행되지 않으므로 타이머도 스케쥴링되지 않을 것이다.\n\n
\nexit
이벤트 예제:\n\n
process.on('exit', function() {\n setTimeout(function() {\n console.log('This will not run');\n }, 0);\n console.log('About to exit.');\n});
\n",
"params": []
},
{
"textRaw": "Event: 'uncaughtException'",
"type": "event",
"name": "uncaughtException",
"desc": "예외가 이벤트루프까지 버블링되었을 때 발생한다. 이 예외에 대한 리스너를 추가하면\n기본 동작(스택트레이스를 출력하고 종료한다)은 수행되지 않을 것이다.\n\n
\nuncaughtException
이벤트 예제:\n\n
process.on('uncaughtException', function(err) {\n console.log('Caught exception: ' + err);\n});\n\nsetTimeout(function() {\n console.log('This will still run.');\n}, 500);\n\n// 의도적인 예외로 예외를 처리하지 않는다.\nnonexistentFunc();\nconsole.log('This will not run.');
\nuncaughtException
는 세련되지 않은 예외처리 방법이이고 차후에는 제거될 것이다.\n\n
uncaughtException
를 사용하지 말고 대신 domains를 사용해라.\nuncaughtException
를 사용한다면 처리하지 않은 예외마다 어플리케이션을 리스타트해라!\n\n
uncaughtException
를 node.js의 On Error Resume Next
로 사용하지 마라.\n처리하지 않은 예외는 어플리케이션(그리고 node.js 확장)이 정의되지 않은 상태에 있음을 의미한다.\n맹목적으로 복구하면 무슨 일이든 발생할 수 있다.\n\n
시스템을 업그레이드 하는 중에 파워코드가 빠졌을 때의 복구를 생각해보자.\n열의 아홉은 아무일도 발생하지 않을 것이다. 하지만 10번째는 시스템이 깨진다.\n\n
\n주의해라.\n\n
\n", "params": [] }, { "textRaw": "Signal Events", "name": "SIGINT, SIGUSR1, etc.", "type": "event", "desc": "프로세스가 Signal을 받았을 때 발상한다. SIGINT, SIGUSR1와 같은 표준 POSIX 신호이름의\n목록은 sigaction(2)를 봐라.\n\n
\nSIGINT
예제:\n\n
// stdin를 읽기 시작하므로 종료되지 않는다.\nprocess.stdin.resume();\n\nprocess.on('SIGINT', function() {\n console.log('Got SIGINT. Press Control-D to exit.');\n});
\nSIGINT
신호를 보내는 쉬운 방법은 대부분의 터미털 프로그램에서 Control-C
를 입력하는\n것이다.\n\n\n
stdout
에 대한 Writable Stream
이다.\n\n
예제: console.log
의 정의\n\n
console.log = function(d) {\n process.stdout.write(d + '\\n');\n};
\nprocess.stderr
와 process.stdout
을 쓰기를 할 때 보통 블락킹된다는 점에서 Node의\n다른 스크림과는 다르다. 이 둘은 보통의 파일이나 TTY 파일 디스크립터를 참조할 때\n블락킹된다. 파이프를 참조하는 경우에는 다른 스크림처럼 넌블락킹이다.\n\n
Node가 TTY 컨텐스트로 실행되는지 확인하려면 process.stderr
, process.stdout
,\nprocess.stdin
의 isTTY
프로퍼티를 읽어라.\n\n
$ node -p "Boolean(process.stdin.isTTY)"\ntrue\n$ echo "foo" | node -p "Boolean(process.stdin.isTTY)"\nfalse\n\n$ node -p "Boolean(process.stdout.isTTY)"\ntrue\n$ node -p "Boolean(process.stdout.isTTY)" | cat\nfalse
\n자세한 내용은 the tty docs를 참고해라.\n\n
\n" }, { "textRaw": "process.stderr", "name": "stderr", "desc": "stderr에 대한 writable stream이다.\n\n
\nprocess.stderr
와 process.stdout
는 쓰기를 할 때 보통 블락킹된다는 점에서 Node의\n다른 스크림과는 다르다. 이 둘은 보통의 파일이나 TTY 파일 디스크립터를 참조할 때\n블락킹된다. 파이프를 참조하는 경우에는 다른 스크림처럼 넌블락킹이다.\n\n\n
stdin에 대한 Readable Stream
이다. stdin 스트림은 기본적으로 멈추기 때문에 stdin에서\n읽으려면 process.stdin.resume()
를 호출해야 한다.\n\n
표준 입력을 열고 두 이벤트를 리스닝하는 예제:\n\n
\nprocess.stdin.resume();\nprocess.stdin.setEncoding('utf8');\n\nprocess.stdin.on('data', function(chunk) {\n process.stdout.write('data: ' + chunk);\n});\n\nprocess.stdin.on('end', function() {\n process.stdout.write('end');\n});
\n"
},
{
"textRaw": "process.argv",
"name": "argv",
"desc": "커맨드라인 아규먼트를 담고 있는 배열이다. 첫 엘리먼트는 'node'일 것이고 두 번째\n엘리먼트는 자바스트립트 파일명이 될 것이다. 다음 엘리먼트들은 추가적인 커맨드라인\n아규먼트일 것이다.\n\n
\n// process.argv 출력\nprocess.argv.forEach(function(val, index, array) {\n console.log(index + ': ' + val);\n});
\n다음과 같이 출력된다:\n\n
\n$ node process-2.js one two=three four\n0: node\n1: /Users/mjr/work/node/process-2.js\n2: one\n3: two=three\n4: four
\n"
},
{
"textRaw": "process.execPath",
"name": "execPath",
"desc": "프로세스가 시작되는 실행가능한 절대경로명이다.\n\n
\n예제:\n\n
\n/usr/local/bin/node
\n"
},
{
"textRaw": "process.execArgv",
"name": "execArgv",
"desc": "이 값은 프로세스를 실행할 때 사용한 노드의 커맨드라인 옵션의 세트다. 이 옵션은\nprocess.argv
에서는 보이지 않고 node 실행명령어, 스크립트 명, 스크립트 명 뒤에\n오는 옵션들은 포함하지 않는다. 이 옵션은 부모와 같은 실행환경으로 자식 프로세스를\n생성할때 유용하다.\n\n
예제:\n\n
\n$ node --harmony script.js --version
\nprocess.execArgv는 다음 값이 된다.\n\n
\n['--harmony']
\nprocess.argv는 다음과 같다.\n\n
\n['/usr/local/bin/node', 'script.js', '--version']
\n"
},
{
"textRaw": "process.env",
"name": "env",
"desc": "사용자의 환경변수를 담고 있는 객체다. environ(7)를 봐라.\n\n\n
\n" }, { "textRaw": "process.version", "name": "version", "desc": "NODE_VERSION
으로 노출된 컴파일된 프로퍼티이다.\n\n
console.log('Version: ' + process.version);
\n"
},
{
"textRaw": "process.versions",
"name": "versions",
"desc": "node와 의존성에 대한 버전 문자열을 노출하는 프로퍼티이다.\n\n
\nconsole.log(process.versions);
\n다음과 같이 출력될 것이다:\n\n
\n{ http_parser: '1.0',\n node: '0.10.4',\n v8: '3.14.5.8',\n ares: '1.9.0-DEV',\n uv: '0.10.3',\n zlib: '1.2.3',\n modules: '11',\n openssl: '1.0.1e' }
\n"
},
{
"textRaw": "process.config",
"name": "config",
"desc": "현재 실행되는 노드를 컴파일하는데 사용한 설정 옵션의 자바스크립트 표현을 담고 있는 객체다.\n이는 ./configure
스크립트를 실행했을 때 생성되는 "config.gypi" 파일과 같다.\n\n
출력은 다음 예제와 같다.\n\n
\n{ target_defaults:\n { cflags: [],\n default_configuration: 'Release',\n defines: [],\n include_dirs: [],\n libraries: [] },\n variables:\n { host_arch: 'x64',\n node_install_npm: 'true',\n node_prefix: '',\n node_shared_cares: 'false',\n node_shared_http_parser: 'false',\n node_shared_libuv: 'false',\n node_shared_v8: 'false',\n node_shared_zlib: 'false',\n node_use_dtrace: 'false',\n node_use_openssl: 'true',\n node_shared_openssl: 'false',\n strict_aliasing: 'true',\n target_arch: 'x64',\n v8_use_snapshot: 'true' } }
\n"
},
{
"textRaw": "process.pid",
"name": "pid",
"desc": "프로세스의 PID.\n\n
\nconsole.log('This process is pid ' + process.pid);
\n"
},
{
"textRaw": "process.title",
"name": "title",
"desc": "'ps'에서 표시될 어떻게 표시되는 지에 대한 Getter와 Setter\n\n
\nsetter로 사용하는 경우 최대 길이는 플랫폼에 의존적이고 아마도 길지 않을 것이다.\n\n
\n리눅스나 OS X에서는 argv 메모리를 덮어쓰기 때문에 바이너리 명의 크기에 명령행 인자의 길이를\n더한 크기로 제한될 것이다.\n\n
\nv0.8은 environ 메모리를 덮어써서 프로세스 타이틀 문자열을 더 길게 처리할 수 있지만\n몇몇 (명확하지 않은)경우에는 잠재적으로 보안에 취약하거나 혼란스러울 수 있다.\n\n\n
\n" }, { "textRaw": "process.arch", "name": "arch", "desc": "어떤 프로세스 아키텍쳐에서 실행되고 있는지 보여준다.: 'arm'
, 'ia32'
, 'x64'
.\n\n
console.log('This processor architecture is ' + process.arch);
\n"
},
{
"textRaw": "process.platform",
"name": "platform",
"desc": "어떤 플랫폼에서 실행되고 있는지 보여준다.\n'darwin'
, 'freebsd'
, 'linux'
, 'sunos'
, 'win32'
\n\n
console.log('This platform is ' + process.platform);
\n"
},
{
"textRaw": "`maxTickDepth` {Number} Default = 1000 ",
"name": "maxTickDepth",
"desc": "process.nextTick
에 전달되는 콜백은 보통 현재 실행 흐름의 끝에 호출될 것이므로\n대략 함수를 동기적으로 호출한 것만큼 빠르게 호출된다. 확인하지 않은채로 놔두면 이는\n어떤 I/O의 발생도 발생하지 못하게 막으면서 이벤트 루프가 굶주리게(starve)할 것이다.\n\n
다음 코드를 보자.\n\n
\nprocess.nextTick(function foo() {\n process.nextTick(foo);\n});
\nnextTick의 재귀 호출로 인한 무한루프가 Node를 블락하는 상황을 피하려면 매번\n일부 I/O가 수행되도록 지연시켜야 한다.\n\n
\nprocess.maxTickDepth
값은 다른 I/O가 일어나도록 하기전에 계산할\nnextTick이 호출하는 nextTick 콜백의 최대 깊이이다.\n\n
이는 node가 abort를 발생시키게 한다. 즉 node가 종료되고 코어파일을 생성한다.\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "process.chdir(directory)", "type": "method", "name": "chdir", "desc": "프로세스의 현재 워킹디렉토리를 바꾸거나 바꾸는데 실패할 경우 예외를 던진다.\n\n
\nconsole.log('Starting directory: ' + process.cwd());\ntry {\n process.chdir('/tmp');\n console.log('New directory: ' + process.cwd());\n}\ncatch (err) {\n console.log('chdir: ' + err);\n}
\n",
"signatures": [
{
"params": [
{
"name": "directory"
}
]
}
]
},
{
"textRaw": "process.cwd()",
"type": "method",
"name": "cwd",
"desc": "프로세스의 현재 워킹디렉토리를 리턴한다.\n\n
\nconsole.log('Current directory: ' + process.cwd());
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "process.exit([code])",
"type": "method",
"name": "exit",
"desc": "지정한 code
로 프로세스를 종료한다. code
를 생략하면 'success' 코드 0
을\n사용해서 종료한다.\n\n
'failure' 코드로 종료하려면:\n\n
\nprocess.exit(1);
\nnode를 실행한 쉘은 1을 종료코드로 간주할 것이다.\n\n\n
\n", "signatures": [ { "params": [ { "name": "code", "optional": true } ] } ] }, { "textRaw": "process.getgid()", "type": "method", "name": "getgid", "desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(예를 들어 Windows에서는 안된다.)\n\n
\n프로세스의 그룹식별자를 얻는다.(getgid(2)를 봐라.)\n이는 그룹 이름이 아니라 숫자로 된 그룹 id 이다.\n\n
\nif (process.getgid) {\n console.log('Current gid: ' + process.getgid());\n}
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "process.setgid(id)",
"type": "method",
"name": "setgid",
"desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(예를 들어 Windows에서는 안된다.)\n\n
\n프로세스의 그룹 식별자를 설정한다.(setgid(2)를 봐라.) 이 함수는 숫자로 된 ID나 문자열로 된\n그룹명을 모두 받아들인다. 그룹명을 지정하면 이 메서드가 그룹명을 숫자로된 ID로 처리할 때까지\n블락킹한다.\n\n
\nif (process.getgid && process.setgid) {\n console.log('Current gid: ' + process.getgid());\n try {\n process.setgid(501);\n console.log('New gid: ' + process.getgid());\n }\n catch (err) {\n console.log('Failed to set gid: ' + err);\n }\n}
\n",
"signatures": [
{
"params": [
{
"name": "id"
}
]
}
]
},
{
"textRaw": "process.getuid()",
"type": "method",
"name": "getuid",
"desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(예를 들어 Windows에서는 안된다.)\n\n
\n프로세스의 사용자 식별자를 얻는다.(getuid(2)를 봐라.)\n이는 사용자명이 아니라 숫자로된 userid이다.\n\n
\nif (process.getuid) {\n console.log('Current uid: ' + process.getuid());\n}
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "process.setuid(id)",
"type": "method",
"name": "setuid",
"desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(예를 들어 Windows에서는 안된다.)\n\n
\n프로세스의 사용자 식별자를 설정한다. (setuid(2)를 봐라.) 이는 숫자로된 ID와 문자열로 된\n사용자명을 모두 받아들인다. 사용자명을 지정하면 이 메서드가 사용자명을 숫자로 된 ID로\n처리할 때까지 블락킹한다.\n\n
\nif (process.getuid && process.setuid) {\n console.log('Current uid: ' + process.getuid());\n try {\n process.setuid(501);\n console.log('New uid: ' + process.getuid());\n }\n catch (err) {\n console.log('Failed to set uid: ' + err);\n }\n}
\n",
"signatures": [
{
"params": [
{
"name": "id"
}
]
}
]
},
{
"textRaw": "process.getgroups()",
"type": "method",
"name": "getgroups",
"desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(윈도우즈에선 사용할 수 없다.)\n\n
\n추가적인 그룹 ID를 가진 배열을 반환한다. POSIX는 유효한 그룹 ID를 포함하고 있는지\n지정하지 않지만 node.js를 이를 항상 보장한다.\n\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "process.setgroups(groups)", "type": "method", "name": "setgroups", "desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(윈도우즈에선 사용할 수 없다.)\n\n
\n추가적인 그룹 ID를 설정한다. 이는 권한힌 필요한 작업이다. 즉, root이거나 CAP_SETGID 권한을\n가져야 한다.\n\n
\n목록은 그룹 ID, 그룹명 또는 둘 다를 포함할 수 있다.\n\n\n
\n", "signatures": [ { "params": [ { "name": "groups" } ] } ] }, { "textRaw": "process.initgroups(user, extra_group)", "type": "method", "name": "initgroups", "desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(윈도우즈에선 사용할 수 없다.)\n\n
\n/etc/group를 읽고 사용자가 멤버로 있는 모든 그룹을 사용해서 그룹 접근 목록을 초기화한다.\n이는 권한이 필요한 작업이므로 root이거나 CAP_SETGID 권한을 가져야 한다.\n\n
\nuser
는 사용자명이거나 사용자 ID이다. extra_group
는 그룹명이나 그룹ID이다.\n\n
권한을 버릴때는 조심할 필요가 있다.\n예제:\n\n
\nconsole.log(process.getgroups()); // [ 0 ]\nprocess.initgroups('bnoordhuis', 1000); // switch user\nconsole.log(process.getgroups()); // [ 27, 30, 46, 1000, 0 ]\nprocess.setgid(1000); // drop root gid\nconsole.log(process.getgroups()); // [ 27, 30, 46, 1000 ]
\n",
"signatures": [
{
"params": [
{
"name": "user"
},
{
"name": "extra_group"
}
]
}
]
},
{
"textRaw": "process.kill(pid, [signal])",
"type": "method",
"name": "kill",
"desc": "프로세스에 신호를 보낸다. pid
는 프로세스 id이고 signal
은 보내려는 신호를\n설명하는 문자열이다. 신호이름은 'SIGINT'나 'SIGUSR1'같은 문자열이다. signal
을\n생략하면 'SIGTERM'가 될 것이다. 더 자세한 내용은 kill(2)를 봐라.\n\n
이 함수의 이름이 process.kill
이므로 실제로 kill
시스템 호출처럼 단순히 신호\n전송자이다. 보낸 신호는 타겟 신호를 죽이는 일이외에 다른 일을 할 것이다.\n\n
자신에게 신호를 보내는 예제:\n\n
\nprocess.on('SIGHUP', function() {\n console.log('Got SIGHUP signal.');\n});\n\nsetTimeout(function() {\n console.log('Exiting.');\n process.exit(0);\n}, 100);\n\nprocess.kill(process.pid, 'SIGHUP');
\n",
"signatures": [
{
"params": [
{
"name": "pid"
},
{
"name": "signal",
"optional": true
}
]
}
]
},
{
"textRaw": "process.memoryUsage()",
"type": "method",
"name": "memoryUsage",
"desc": "Node 프로세스의 메모리 사용량을 바이트로 나타내서 보여주는 객체를 리턴한다.\n\n
\nvar util = require('util');\n\nconsole.log(util.inspect(process.memoryUsage()));
\n다음과 같이 출력될 것이다:\n\n
\n{ rss: 4935680,\n heapTotal: 1826816,\n heapUsed: 650472 }
\nheapTotal
와 heapUsed
는 V8의 메모리 사용량을 참조한다.\n\n\n
이벤트 루프의 다음 번 루프에서 이 callback을 호출한다.\n이는 단순히 setTimeout(fn, 0)
에 대한 별칭이 아니라 훨씬 더 효율적이다.\n이는 보통 어떤 I/O 이벤트도 발생하기 전에 실행되지만 몇가지 예외가 존재한다.\n아래의 process.maxTickDepth
를 참고해라.\n\n
process.nextTick(function() {\n console.log('nextTick callback');\n});
\n이는 객체가 만들어 진 후이지만 어떤 I/O도 발생하기 전에 사용자가 이벤트 핸들러를 할당할 기회를\n주고자 하는 API를 개발할 때 중요하다.\n\n
\nfunction MyThing(options) {\n this.setupOptions(options);\n\n process.nextTick(function() {\n this.startDoingStuff();\n }.bind(this));\n}\n\nvar thing = new MyThing();\nthing.getReadyForStuff();\n\n// thing.startDoingStuff()는 이제 호출된다.(그 이전이 아니라)
\n이는 100% 동기이거나 100% 비동기여야 하는 API에 아주 중요한다.\n다음 예제를 봐라.\n\n
\n// WARNING! DO NOT USE! BAD UNSAFE HAZARD!\nfunction maybeSync(arg, cb) {\n if (arg) {\n cb();\n return;\n }\n\n fs.stat('file', cb);\n}
\n이 API는 위험하다. 다음과 같이 사용한다면\n\n
\nmaybeSync(true, function() {\n foo();\n});\nbar();
\nfoo()
와 bar()
중 어느 쪽이 먼저 호출될 것인지 명확하지 않다.\n\n
다음 접근방법이 훨씬 좋다.\n\n
\nfunction definitelyAsync(arg, cb) {\n if (arg) {\n process.nextTick(cb);\n return;\n }\n\n fs.stat('file', cb);\n}
\n",
"signatures": [
{
"params": [
{
"name": "callback"
}
]
}
]
},
{
"textRaw": "process.umask([mask])",
"type": "method",
"name": "umask",
"desc": "프로세스의 파일 모드 생성 마스크를 설정하거나 읽는다. 자식 프로세스는 부모 프로세스에서\n이 마스크를 상속받는다. mask
아규먼트를 전달하면 이전의 마스크를 리턴하고 mask
아규먼트를\n전달하지 않으면 현재 마스크를 리턴한다.\n\n
var oldmask, newmask = 0644;\n\noldmask = process.umask(newmask);\nconsole.log('Changed umask from: ' + oldmask.toString(8) +\n ' to ' + newmask.toString(8));
\n",
"signatures": [
{
"params": [
{
"name": "mask",
"optional": true
}
]
}
]
},
{
"textRaw": "process.uptime()",
"type": "method",
"name": "uptime",
"desc": "Node가 실행되고 있는 시간을 초단위로 나타낸다.\n\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "process.hrtime()", "type": "method", "name": "hrtime", "desc": "[seconds, nanoseconds]
튜플 배열 형식으로 현재의 고해상도(high-resolution)\n실제 시간을 반환한다. 이는 과거 임의의 시간과 관계가 있고 시각과는 관련이 없으므로\n클럭 드리프트(clock drift)를 따르지 않는다. 어떤 구간사이의 성능을 측정하는 것이\n주요 사용처이다.\n\n
어떤 구간을 벤치마킹을 위해 시간 간격을 얻기 위해 process.hrtime()
에 이전 호출의 결과를\n전달한다.\n\n
var time = process.hrtime();\n// [ 1800216, 25 ]\n\nsetTimeout(function() {\n var diff = process.hrtime(time);\n // [ 1, 552 ]\n\n console.log('benchmark took %d nanoseconds', diff[0] * 1e9 + diff[1]);\n // benchmark took 1000000527 nanoseconds\n}, 1000);
\n",
"signatures": [
{
"params": []
}
]
}
]
}
],
"vars": [
{
"textRaw": "require()",
"type": "var",
"name": "require",
"desc": "모듈을 require한다. [Modules][]부분을 봐라.\nrequire
는 실제로 전역이 아니라 각 모듈의 지역범위다.\n\n
모듈의 위치를 검색하는데 내부 require()
장치(machinery)를 사용한다. 모듈을 로딩하는\n것이 아니라 처리된 파일명을 리턴할 뿐이다.\n\n
모듈을 require했을 때 모듈은 이 객체에 캐시된다. 이 객체에서 키 값을 삭제하면 다음 번\nrequire
에서 해당 모듈을 다시 로드할 것이다.\n\n
특정 파일 확장자를 어떻게 다룰지를 require
에 지시한다.\n\n
.sjs
확장자의 파일을 .js
처럼 처리한다.\n\n
require.extensions['.sjs'] = require.extensions['.js'];
\nDeprecated 과거에 이 항목은 요청에 따라 컴파일해서 Node에 자바스크립트가 아닌 모듈을\n로드하는데 사용했다. 하지만 실제로 다른 몇몇 Node 프로그램을 통해서 모듈을 로딩하거나\nahead of time으로 자바스크립트로 컴파일하는 등의 이를 위한 훨씬 더 좋은 방법이 존재한다.\n\n
\nModule 시스템이 locked 상태이므로 이 기능은 없어지지 않을 것이다. 하지만 미묘한 버그나\n건드릴 수 없는 복잡성을 가질 수 있다.\n\n
\n" } ] }, { "textRaw": "__filename", "name": "__filename", "type": "var", "desc": "실행되는 코드의 파일명이다. 이 코드 파일을 처리한 절대경로이다. 메인 프로그램에서 이는\n커맨드라인에서 사용한 것과 반드시 같은 파일명은 아니다. 모듈내부에서 이 값은 해당 모듈 파일에\n대한 경로이다.\n\n
\n예제: /Users/mjr
에서 node example.js
를 실행한다.\n\n
console.log(__filename);\n// /Users/mjr/example.js
\n__filename
은 실제로 전역이 아니라 각 모듈의 지역범위이다.\n\n
현재 실행되는 스크립트가 존재하는 디렉토리 이름이다.\n\n
\n예제: /Users/mjr
에서 node example.js
를 실행한다.\n\n
console.log(__dirname);\n// /Users/mjr
\n__dirname
는 실제로 전역이 아니라 각 모듈의 지역범위이다.\n\n\n
현재 모듈에 대한 참조이다. 특히 module.exports
는 exports
객체와 같다.\nmodule
는 실제로 전역이 아니라 각 모듈의 지역범위이다.\n\n
더 자세한 내용은 [module system documentation][]를 봐라.\n\n
\n" }, { "textRaw": "exports", "name": "exports", "type": "var", "desc": "현재 모듈과 require()
로 접근가능하게 된 모듈의 모든 인스턴스 사이에서 공유되는\nmodule.exports
객체에 대한 참조. 언제 exports
를 사용하고 언제 module.exports
를\n사용하는 지에 대한 자세한 내용은 [module system documentation][]를 참고해라.\nexports
는 실제로 전역이 아니라 각 모듈의 지역범위이다.\n\n
더 자세한 내용은 [module system documentation][]를 봐라.\n\n
\n더 자세한 내용은 [module section][]를 봐라.\n\n
\n" } ], "methods": [ { "textRaw": "setTimeout(cb, ms)", "type": "method", "name": "setTimeout", "desc": "최소 ms
밀리초 후에 콜백 cb
를 실행한다. 실제 지연시간은 OS 타이머의 크기와 시스템\n부하같은 외부 요소에 달려있다.\n\n
타임아웃은 1-2,147,483,647의 범위여야 한다. 값이 이 범위 밖이면 타임아웃은 1 밀리초로\n바뀐다. 대략적으로 말해서 타이머는 24.8일이상이 될 수 없다.\n\n
\n타이머를 나타내는 불투명한 값을 반환한다.\n\n
\n", "signatures": [ { "params": [ { "name": "cb" }, { "name": "ms" } ] } ] }, { "textRaw": "clearTimeout(t)", "type": "method", "name": "clearTimeout", "desc": "이전에 setTimeout()
로 생성된 타이머를 멈춘다. 콜백은 실행하지 않을 것이다.\n\n
ms
밀리초마다 반복적으로 콜백 cb
를 실행한다. 실제 간격은 OS 타이머의 크기나 시스템\n부하같은 외부 요소에 따라 다양하다. 시간간격은 ms
보다 작을 수 없다.\n\n
간격은 1-2,147,483,647의 범위여야 한다. 값이 이 범위 밖이면 1밀리초로 바뀐다. 대력적으로\n말해서 타이머는 24.8일 이상이 될 수 없다.\n\n
\n타이머를 나타내는 불투명한 값을 반환한다.\n\n
\n", "signatures": [ { "params": [ { "name": "cb" }, { "name": "ms" } ] } ] } ] }, { "textRaw": "Debugger", "name": "Debugger", "stability": 3, "stabilityText": "Stable", "type": "misc", "desc": "V8에는 확장 가능한 디버거가 들어 있다. 이 디버거는 간단한 TCP 프로토콜을 통해서 프로세스 외부에서 접근할 수 있다. 그리고 Node에는 이 디버거를 사용하는 빌트인 디버거 클라이언트가 들어 있다. Node를 실행할 때 debug
인자를 주면 디버거를 사용할 수 있다:\n\n
% node debug myscript.js\n< debugger listening on port 5858\nconnecting... ok\nbreak in /home/indutny/Code/git/indutny/myscript.js:1\n 1 x = 5;\n 2 setTimeout(function () {\n 3 debugger;\ndebug>
\n이 빌트인 클라이언트는 명령어를 다 지원하지 않지만 step과 inspection을 간단히 해볼 수 있다. 소스코드에 debugger;
를 집어 넣으면 그 부분이 breakpoint가 된다.\n\n
예를 들어, 다음과 같은 myscript.js
를 보자:\n\n
// myscript.js\nx = 5;\nsetTimeout(function () {\n debugger;\n console.log("world");\n}, 1000);\nconsole.log("hello");
\n그리고 나서 디버거를 실행하면 4번째 줄에서 멈춘다.\n\n
\n% node debug myscript.js\n< debugger listening on port 5858\nconnecting... ok\nbreak in /home/indutny/Code/git/indutny/myscript.js:1\n 1 x = 5;\n 2 setTimeout(function () {\n 3 debugger;\ndebug> cont\n< hello\nbreak in /home/indutny/Code/git/indutny/myscript.js:3\n 1 x = 5;\n 2 setTimeout(function () {\n 3 debugger;\n 4 console.log("world");\n 5 }, 1000);\ndebug> next\nbreak in /home/indutny/Code/git/indutny/myscript.js:4\n 2 setTimeout(function () {\n 3 debugger;\n 4 console.log("world");\n 5 }, 1000);\n 6 console.log("hello");\ndebug> repl\nPress Ctrl + C to leave debug repl\n> x\n5\n> 2+2\n4\ndebug> next\n< world\nbreak in /home/indutny/Code/git/indutny/myscript.js:5\n 3 debugger;\n 4 console.log("world");\n 5 }, 1000);\n 6 console.log("hello");\n 7\ndebug> quit\n%
\nrepl
명령어는 원격에서 코드를 실행해볼 수 있도록 해준다. next
명령어를 실행하면 다음 줄로 넘어간다(step over). 그외에도 사용할 수 있는 명령어가 꽤 있다. help
를 입력하면 뭐가 있는지 보여준다.\n\n
디버깅하는 동안 표현식(expression)과 변수의 값을 watch할 수 있다. breakpoint마다 watcher에 등록된 표현을 현 컨텍스트에서 실행해서 보여준다. 그 다음에 breakpoint가 있는 소스코드가 출력된다.\n\n
\nwatch("my_expression")
으로 watcher를 등록하고 watchers
명령으로 등록된 watcher들을 확인할 수 있다. 그리고 unwatch("my_expression")
으로 등록된 watcher를 제거할 수 있다.\n\n
아직 로딩되지 않은 파일(모듈)에 breakpoint를 설정할 수도 있다.\n\n
\n% ./node debug test/fixtures/break-in-module/main.js\n< debugger listening on port 5858\nconnecting to port 5858... ok\nbreak in test/fixtures/break-in-module/main.js:1\n 1 var mod = require('./mod.js');\n 2 mod.hello();\n 3 mod.hello();\ndebug> setBreakpoint('mod.js', 23)\nWarning: script 'mod.js' was not loaded yet.\n 1 var mod = require('./mod.js');\n 2 mod.hello();\n 3 mod.hello();\ndebug> c\nbreak in test/fixtures/break-in-module/mod.js:23\n 21\n 22 exports.hello = function() {\n 23 return 'hello from module';\n 24 };\n 25\ndebug>
\n",
"type": "module",
"displayName": "Breakpoints"
},
{
"textRaw": "Breakpoints",
"name": "breakpoints",
"desc": "아직 로딩되지 않은 파일(모듈)에 breakpoint를 설정할 수도 있다.\n\n
\n% ./node debug test/fixtures/break-in-module/main.js\n< debugger listening on port 5858\nconnecting to port 5858... ok\nbreak in test/fixtures/break-in-module/main.js:1\n 1 var mod = require('./mod.js');\n 2 mod.hello();\n 3 mod.hello();\ndebug> setBreakpoint('mod.js', 23)\nWarning: script 'mod.js' was not loaded yet.\n 1 var mod = require('./mod.js');\n 2 mod.hello();\n 3 mod.hello();\ndebug> c\nbreak in test/fixtures/break-in-module/mod.js:23\n 21\n 22 exports.hello = function() {\n 23 return 'hello from module';\n 24 };\n 25\ndebug>
\n",
"type": "module",
"displayName": "Breakpoints"
},
{
"textRaw": "Execution control",
"name": "Execution control",
"type": "module",
"displayName": "Various"
},
{
"textRaw": "Various",
"name": "various",
"type": "module",
"displayName": "Various"
}
],
"type": "misc",
"displayName": "Commands reference"
},
{
"textRaw": "Advanced Usage",
"name": "advanced_usage",
"desc": "커맨드 라인에서 --debug
플래그 주고 Node를 실행하면 V8 디버거가 켜진다. 또 이미 실행중인 Node 프로세스에 SIGUSR1
시그널을 보내면 V8 디버거가 켜지고 접근해서 사용할 수 있다.\n\n
프로세스가 디버그 모드로 설정되면 노드 디버거로 접속할 수 있다. 디버거에 pid
나 URI로 접속할 수 있다.\n문법은 다음과 같다.\n\n
node debug -p <pid>
- pid
로 프로세스에 연결한다브라우저에서 최상위 범위는 전역 범위이다. 이는 브라우저의 전역 범위에서 var something
가\n전역 변수를 정의한다는 것을 의미한다. Node에서는 다르다. 최상위 범위는 전역 범위가 아니다.\nNode 모듈에서 var something
는 해당 모듈의 지역 범위가 된다.\n\n
process 객체. [process object][]부분을 봐라.\n\n
\n" }, { "textRaw": "console", "name": "console", "type": "global", "desc": "stdout와 stderr에 출력하는 데 사용한다. [console][]부분을 봐라.\n\n
\n" }, { "textRaw": "Class: Buffer", "type": "global", "name": "Buffer", "desc": "바이너리 데이터를 다루는데 사용한다. [buffer section][]을 봐라.\n\n
\n" }, { "textRaw": "clearInterval(t)", "type": "global", "name": "clearInterval", "desc": "이전에 setInterval()
로 생성된 타이머를 멈춘다. 콜백은 실행하지 않을 것이다.\n\n
timer 함수는 전역 변수이다. [timers][]부분을 봐라.\n\n
\n" }, { "textRaw": "console", "name": "console", "stability": 4, "stabilityText": "API Frozen", "type": "global", "desc": "stdout와 stderr에 출력하기 위해 사용한다. 대부분의 웹 브라우저가 제공하는 console\n객체의 기능과 유사하게 stdout이나 stderr로 출력한다.\n\n
\n목적지가 터미널이거나 피일일 때는(빠르게 종료되는 경우 메시지를 잃어버리지 않기 위해서)\nconsole 기능은 동기적이고 파이프인 경우(장시간 블락킹하는 것을 피하기 위해)에는 비동기이다.\n\n
\n즉, 다음 예제에서 stdout은 넌블락킹이고 stderr은 블락킹이다.\n\n
\n$ node script.js 2> error.log | tee info.log
\n일반적인 사용해서 엄청난 양의 데이터를 로깅하지 않는한 블락킹과 넌블락킹을 걱정할 필요는 없다.\n\n\n
\n", "methods": [ { "textRaw": "console.log([data], [...])", "type": "method", "name": "log", "desc": "새로운 라인으로 stdout에 출력한다. 이 함수는 printf()
와 같은 방식으로 여러 아규먼트를\n받는다. 예제:\n\n
console.log('count: %d', count);
\n첫 문자열에 포매팅 객체가 없으면 각 아규먼트에 util.inspect
를 사용한다.\n더 자세한 내용은 [util.format()][]를 봐라.\n\n
console.log
와 동일하다.\n\n
console.log
와 같지만 stderr에 출력한다.\n\n
console.error
와 같다.\n\n
obj
에 util.inspect
를 사용하고 결과 문자열을 stdout에 출력한다.\n\n
시간을 마킹한다.\n\n
\n", "signatures": [ { "params": [ { "name": "label" } ] } ] }, { "textRaw": "console.timeEnd(label)", "type": "method", "name": "timeEnd", "desc": "타이머를 종료하고 결과를 기록한다. 예제:\n\n
\nconsole.time('100-elements');\nfor (var i = 0; i < 100; i++) {\n ;\n}\nconsole.timeEnd('100-elements');
\n",
"signatures": [
{
"params": [
{
"name": "label"
}
]
}
]
},
{
"textRaw": "console.trace(label)",
"type": "method",
"name": "trace",
"desc": "현지 위치의 stderr에 스택트레이스를 출력한다.\n\n
\n", "signatures": [ { "params": [ { "name": "label" } ] } ] }, { "textRaw": "console.assert(expression, [message])", "type": "method", "name": "assert", "desc": "expression
가 false
이면 message
로 AssertionError를 던지는 [assert.ok()][]와\n같다.\n\n
process
객체는 전역객체이고 어디서나 접근할 수 있다.\n이 객체는 [EventEmitter][] 인스턴스이다.\n\n\n
프로세스가 종료될 때 발생한다. 이 이벤트는 모듈의 상태를 상수시간으로 확인하는데 좋은\n훅(hook)이다.(유닛테스트에서처럼) 메인 이벤트루프는 'exit' 콜백이 종료된 후에는 더이상\n실행되지 않으므로 타이머도 스케쥴링되지 않을 것이다.\n\n
\nexit
이벤트 예제:\n\n
process.on('exit', function() {\n setTimeout(function() {\n console.log('This will not run');\n }, 0);\n console.log('About to exit.');\n});
\n",
"params": []
},
{
"textRaw": "Event: 'uncaughtException'",
"type": "event",
"name": "uncaughtException",
"desc": "예외가 이벤트루프까지 버블링되었을 때 발생한다. 이 예외에 대한 리스너를 추가하면\n기본 동작(스택트레이스를 출력하고 종료한다)은 수행되지 않을 것이다.\n\n
\nuncaughtException
이벤트 예제:\n\n
process.on('uncaughtException', function(err) {\n console.log('Caught exception: ' + err);\n});\n\nsetTimeout(function() {\n console.log('This will still run.');\n}, 500);\n\n// 의도적인 예외로 예외를 처리하지 않는다.\nnonexistentFunc();\nconsole.log('This will not run.');
\nuncaughtException
는 세련되지 않은 예외처리 방법이이고 차후에는 제거될 것이다.\n\n
uncaughtException
를 사용하지 말고 대신 domains를 사용해라.\nuncaughtException
를 사용한다면 처리하지 않은 예외마다 어플리케이션을 리스타트해라!\n\n
uncaughtException
를 node.js의 On Error Resume Next
로 사용하지 마라.\n처리하지 않은 예외는 어플리케이션(그리고 node.js 확장)이 정의되지 않은 상태에 있음을 의미한다.\n맹목적으로 복구하면 무슨 일이든 발생할 수 있다.\n\n
시스템을 업그레이드 하는 중에 파워코드가 빠졌을 때의 복구를 생각해보자.\n열의 아홉은 아무일도 발생하지 않을 것이다. 하지만 10번째는 시스템이 깨진다.\n\n
\n주의해라.\n\n
\n", "params": [] }, { "textRaw": "Signal Events", "name": "SIGINT, SIGUSR1, etc.", "type": "event", "desc": "프로세스가 Signal을 받았을 때 발상한다. SIGINT, SIGUSR1와 같은 표준 POSIX 신호이름의\n목록은 sigaction(2)를 봐라.\n\n
\nSIGINT
예제:\n\n
// stdin를 읽기 시작하므로 종료되지 않는다.\nprocess.stdin.resume();\n\nprocess.on('SIGINT', function() {\n console.log('Got SIGINT. Press Control-D to exit.');\n});
\nSIGINT
신호를 보내는 쉬운 방법은 대부분의 터미털 프로그램에서 Control-C
를 입력하는\n것이다.\n\n\n
stdout
에 대한 Writable Stream
이다.\n\n
예제: console.log
의 정의\n\n
console.log = function(d) {\n process.stdout.write(d + '\\n');\n};
\nprocess.stderr
와 process.stdout
을 쓰기를 할 때 보통 블락킹된다는 점에서 Node의\n다른 스크림과는 다르다. 이 둘은 보통의 파일이나 TTY 파일 디스크립터를 참조할 때\n블락킹된다. 파이프를 참조하는 경우에는 다른 스크림처럼 넌블락킹이다.\n\n
Node가 TTY 컨텐스트로 실행되는지 확인하려면 process.stderr
, process.stdout
,\nprocess.stdin
의 isTTY
프로퍼티를 읽어라.\n\n
$ node -p "Boolean(process.stdin.isTTY)"\ntrue\n$ echo "foo" | node -p "Boolean(process.stdin.isTTY)"\nfalse\n\n$ node -p "Boolean(process.stdout.isTTY)"\ntrue\n$ node -p "Boolean(process.stdout.isTTY)" | cat\nfalse
\n자세한 내용은 the tty docs를 참고해라.\n\n
\n" }, { "textRaw": "process.stderr", "name": "stderr", "desc": "stderr에 대한 writable stream이다.\n\n
\nprocess.stderr
와 process.stdout
는 쓰기를 할 때 보통 블락킹된다는 점에서 Node의\n다른 스크림과는 다르다. 이 둘은 보통의 파일이나 TTY 파일 디스크립터를 참조할 때\n블락킹된다. 파이프를 참조하는 경우에는 다른 스크림처럼 넌블락킹이다.\n\n\n
stdin에 대한 Readable Stream
이다. stdin 스트림은 기본적으로 멈추기 때문에 stdin에서\n읽으려면 process.stdin.resume()
를 호출해야 한다.\n\n
표준 입력을 열고 두 이벤트를 리스닝하는 예제:\n\n
\nprocess.stdin.resume();\nprocess.stdin.setEncoding('utf8');\n\nprocess.stdin.on('data', function(chunk) {\n process.stdout.write('data: ' + chunk);\n});\n\nprocess.stdin.on('end', function() {\n process.stdout.write('end');\n});
\n"
},
{
"textRaw": "process.argv",
"name": "argv",
"desc": "커맨드라인 아규먼트를 담고 있는 배열이다. 첫 엘리먼트는 'node'일 것이고 두 번째\n엘리먼트는 자바스트립트 파일명이 될 것이다. 다음 엘리먼트들은 추가적인 커맨드라인\n아규먼트일 것이다.\n\n
\n// process.argv 출력\nprocess.argv.forEach(function(val, index, array) {\n console.log(index + ': ' + val);\n});
\n다음과 같이 출력된다:\n\n
\n$ node process-2.js one two=three four\n0: node\n1: /Users/mjr/work/node/process-2.js\n2: one\n3: two=three\n4: four
\n"
},
{
"textRaw": "process.execPath",
"name": "execPath",
"desc": "프로세스가 시작되는 실행가능한 절대경로명이다.\n\n
\n예제:\n\n
\n/usr/local/bin/node
\n"
},
{
"textRaw": "process.execArgv",
"name": "execArgv",
"desc": "이 값은 프로세스를 실행할 때 사용한 노드의 커맨드라인 옵션의 세트다. 이 옵션은\nprocess.argv
에서는 보이지 않고 node 실행명령어, 스크립트 명, 스크립트 명 뒤에\n오는 옵션들은 포함하지 않는다. 이 옵션은 부모와 같은 실행환경으로 자식 프로세스를\n생성할때 유용하다.\n\n
예제:\n\n
\n$ node --harmony script.js --version
\nprocess.execArgv는 다음 값이 된다.\n\n
\n['--harmony']
\nprocess.argv는 다음과 같다.\n\n
\n['/usr/local/bin/node', 'script.js', '--version']
\n"
},
{
"textRaw": "process.env",
"name": "env",
"desc": "사용자의 환경변수를 담고 있는 객체다. environ(7)를 봐라.\n\n\n
\n" }, { "textRaw": "process.version", "name": "version", "desc": "NODE_VERSION
으로 노출된 컴파일된 프로퍼티이다.\n\n
console.log('Version: ' + process.version);
\n"
},
{
"textRaw": "process.versions",
"name": "versions",
"desc": "node와 의존성에 대한 버전 문자열을 노출하는 프로퍼티이다.\n\n
\nconsole.log(process.versions);
\n다음과 같이 출력될 것이다:\n\n
\n{ http_parser: '1.0',\n node: '0.10.4',\n v8: '3.14.5.8',\n ares: '1.9.0-DEV',\n uv: '0.10.3',\n zlib: '1.2.3',\n modules: '11',\n openssl: '1.0.1e' }
\n"
},
{
"textRaw": "process.config",
"name": "config",
"desc": "현재 실행되는 노드를 컴파일하는데 사용한 설정 옵션의 자바스크립트 표현을 담고 있는 객체다.\n이는 ./configure
스크립트를 실행했을 때 생성되는 "config.gypi" 파일과 같다.\n\n
출력은 다음 예제와 같다.\n\n
\n{ target_defaults:\n { cflags: [],\n default_configuration: 'Release',\n defines: [],\n include_dirs: [],\n libraries: [] },\n variables:\n { host_arch: 'x64',\n node_install_npm: 'true',\n node_prefix: '',\n node_shared_cares: 'false',\n node_shared_http_parser: 'false',\n node_shared_libuv: 'false',\n node_shared_v8: 'false',\n node_shared_zlib: 'false',\n node_use_dtrace: 'false',\n node_use_openssl: 'true',\n node_shared_openssl: 'false',\n strict_aliasing: 'true',\n target_arch: 'x64',\n v8_use_snapshot: 'true' } }
\n"
},
{
"textRaw": "process.pid",
"name": "pid",
"desc": "프로세스의 PID.\n\n
\nconsole.log('This process is pid ' + process.pid);
\n"
},
{
"textRaw": "process.title",
"name": "title",
"desc": "'ps'에서 표시될 어떻게 표시되는 지에 대한 Getter와 Setter\n\n
\nsetter로 사용하는 경우 최대 길이는 플랫폼에 의존적이고 아마도 길지 않을 것이다.\n\n
\n리눅스나 OS X에서는 argv 메모리를 덮어쓰기 때문에 바이너리 명의 크기에 명령행 인자의 길이를\n더한 크기로 제한될 것이다.\n\n
\nv0.8은 environ 메모리를 덮어써서 프로세스 타이틀 문자열을 더 길게 처리할 수 있지만\n몇몇 (명확하지 않은)경우에는 잠재적으로 보안에 취약하거나 혼란스러울 수 있다.\n\n\n
\n" }, { "textRaw": "process.arch", "name": "arch", "desc": "어떤 프로세스 아키텍쳐에서 실행되고 있는지 보여준다.: 'arm'
, 'ia32'
, 'x64'
.\n\n
console.log('This processor architecture is ' + process.arch);
\n"
},
{
"textRaw": "process.platform",
"name": "platform",
"desc": "어떤 플랫폼에서 실행되고 있는지 보여준다.\n'darwin'
, 'freebsd'
, 'linux'
, 'sunos'
, 'win32'
\n\n
console.log('This platform is ' + process.platform);
\n"
},
{
"textRaw": "`maxTickDepth` {Number} Default = 1000 ",
"name": "maxTickDepth",
"desc": "process.nextTick
에 전달되는 콜백은 보통 현재 실행 흐름의 끝에 호출될 것이므로\n대략 함수를 동기적으로 호출한 것만큼 빠르게 호출된다. 확인하지 않은채로 놔두면 이는\n어떤 I/O의 발생도 발생하지 못하게 막으면서 이벤트 루프가 굶주리게(starve)할 것이다.\n\n
다음 코드를 보자.\n\n
\nprocess.nextTick(function foo() {\n process.nextTick(foo);\n});
\nnextTick의 재귀 호출로 인한 무한루프가 Node를 블락하는 상황을 피하려면 매번\n일부 I/O가 수행되도록 지연시켜야 한다.\n\n
\nprocess.maxTickDepth
값은 다른 I/O가 일어나도록 하기전에 계산할\nnextTick이 호출하는 nextTick 콜백의 최대 깊이이다.\n\n
이는 node가 abort를 발생시키게 한다. 즉 node가 종료되고 코어파일을 생성한다.\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "process.chdir(directory)", "type": "method", "name": "chdir", "desc": "프로세스의 현재 워킹디렉토리를 바꾸거나 바꾸는데 실패할 경우 예외를 던진다.\n\n
\nconsole.log('Starting directory: ' + process.cwd());\ntry {\n process.chdir('/tmp');\n console.log('New directory: ' + process.cwd());\n}\ncatch (err) {\n console.log('chdir: ' + err);\n}
\n",
"signatures": [
{
"params": [
{
"name": "directory"
}
]
}
]
},
{
"textRaw": "process.cwd()",
"type": "method",
"name": "cwd",
"desc": "프로세스의 현재 워킹디렉토리를 리턴한다.\n\n
\nconsole.log('Current directory: ' + process.cwd());
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "process.exit([code])",
"type": "method",
"name": "exit",
"desc": "지정한 code
로 프로세스를 종료한다. code
를 생략하면 'success' 코드 0
을\n사용해서 종료한다.\n\n
'failure' 코드로 종료하려면:\n\n
\nprocess.exit(1);
\nnode를 실행한 쉘은 1을 종료코드로 간주할 것이다.\n\n\n
\n", "signatures": [ { "params": [ { "name": "code", "optional": true } ] } ] }, { "textRaw": "process.getgid()", "type": "method", "name": "getgid", "desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(예를 들어 Windows에서는 안된다.)\n\n
\n프로세스의 그룹식별자를 얻는다.(getgid(2)를 봐라.)\n이는 그룹 이름이 아니라 숫자로 된 그룹 id 이다.\n\n
\nif (process.getgid) {\n console.log('Current gid: ' + process.getgid());\n}
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "process.setgid(id)",
"type": "method",
"name": "setgid",
"desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(예를 들어 Windows에서는 안된다.)\n\n
\n프로세스의 그룹 식별자를 설정한다.(setgid(2)를 봐라.) 이 함수는 숫자로 된 ID나 문자열로 된\n그룹명을 모두 받아들인다. 그룹명을 지정하면 이 메서드가 그룹명을 숫자로된 ID로 처리할 때까지\n블락킹한다.\n\n
\nif (process.getgid && process.setgid) {\n console.log('Current gid: ' + process.getgid());\n try {\n process.setgid(501);\n console.log('New gid: ' + process.getgid());\n }\n catch (err) {\n console.log('Failed to set gid: ' + err);\n }\n}
\n",
"signatures": [
{
"params": [
{
"name": "id"
}
]
}
]
},
{
"textRaw": "process.getuid()",
"type": "method",
"name": "getuid",
"desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(예를 들어 Windows에서는 안된다.)\n\n
\n프로세스의 사용자 식별자를 얻는다.(getuid(2)를 봐라.)\n이는 사용자명이 아니라 숫자로된 userid이다.\n\n
\nif (process.getuid) {\n console.log('Current uid: ' + process.getuid());\n}
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "process.setuid(id)",
"type": "method",
"name": "setuid",
"desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(예를 들어 Windows에서는 안된다.)\n\n
\n프로세스의 사용자 식별자를 설정한다. (setuid(2)를 봐라.) 이는 숫자로된 ID와 문자열로 된\n사용자명을 모두 받아들인다. 사용자명을 지정하면 이 메서드가 사용자명을 숫자로 된 ID로\n처리할 때까지 블락킹한다.\n\n
\nif (process.getuid && process.setuid) {\n console.log('Current uid: ' + process.getuid());\n try {\n process.setuid(501);\n console.log('New uid: ' + process.getuid());\n }\n catch (err) {\n console.log('Failed to set uid: ' + err);\n }\n}
\n",
"signatures": [
{
"params": [
{
"name": "id"
}
]
}
]
},
{
"textRaw": "process.getgroups()",
"type": "method",
"name": "getgroups",
"desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(윈도우즈에선 사용할 수 없다.)\n\n
\n추가적인 그룹 ID를 가진 배열을 반환한다. POSIX는 유효한 그룹 ID를 포함하고 있는지\n지정하지 않지만 node.js를 이를 항상 보장한다.\n\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "process.setgroups(groups)", "type": "method", "name": "setgroups", "desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(윈도우즈에선 사용할 수 없다.)\n\n
\n추가적인 그룹 ID를 설정한다. 이는 권한힌 필요한 작업이다. 즉, root이거나 CAP_SETGID 권한을\n가져야 한다.\n\n
\n목록은 그룹 ID, 그룹명 또는 둘 다를 포함할 수 있다.\n\n\n
\n", "signatures": [ { "params": [ { "name": "groups" } ] } ] }, { "textRaw": "process.initgroups(user, extra_group)", "type": "method", "name": "initgroups", "desc": "Note: 이 함수는 POSIX 플랫폼에서만 사용할 수 있다.(윈도우즈에선 사용할 수 없다.)\n\n
\n/etc/group를 읽고 사용자가 멤버로 있는 모든 그룹을 사용해서 그룹 접근 목록을 초기화한다.\n이는 권한이 필요한 작업이므로 root이거나 CAP_SETGID 권한을 가져야 한다.\n\n
\nuser
는 사용자명이거나 사용자 ID이다. extra_group
는 그룹명이나 그룹ID이다.\n\n
권한을 버릴때는 조심할 필요가 있다.\n예제:\n\n
\nconsole.log(process.getgroups()); // [ 0 ]\nprocess.initgroups('bnoordhuis', 1000); // switch user\nconsole.log(process.getgroups()); // [ 27, 30, 46, 1000, 0 ]\nprocess.setgid(1000); // drop root gid\nconsole.log(process.getgroups()); // [ 27, 30, 46, 1000 ]
\n",
"signatures": [
{
"params": [
{
"name": "user"
},
{
"name": "extra_group"
}
]
}
]
},
{
"textRaw": "process.kill(pid, [signal])",
"type": "method",
"name": "kill",
"desc": "프로세스에 신호를 보낸다. pid
는 프로세스 id이고 signal
은 보내려는 신호를\n설명하는 문자열이다. 신호이름은 'SIGINT'나 'SIGUSR1'같은 문자열이다. signal
을\n생략하면 'SIGTERM'가 될 것이다. 더 자세한 내용은 kill(2)를 봐라.\n\n
이 함수의 이름이 process.kill
이므로 실제로 kill
시스템 호출처럼 단순히 신호\n전송자이다. 보낸 신호는 타겟 신호를 죽이는 일이외에 다른 일을 할 것이다.\n\n
자신에게 신호를 보내는 예제:\n\n
\nprocess.on('SIGHUP', function() {\n console.log('Got SIGHUP signal.');\n});\n\nsetTimeout(function() {\n console.log('Exiting.');\n process.exit(0);\n}, 100);\n\nprocess.kill(process.pid, 'SIGHUP');
\n",
"signatures": [
{
"params": [
{
"name": "pid"
},
{
"name": "signal",
"optional": true
}
]
}
]
},
{
"textRaw": "process.memoryUsage()",
"type": "method",
"name": "memoryUsage",
"desc": "Node 프로세스의 메모리 사용량을 바이트로 나타내서 보여주는 객체를 리턴한다.\n\n
\nvar util = require('util');\n\nconsole.log(util.inspect(process.memoryUsage()));
\n다음과 같이 출력될 것이다:\n\n
\n{ rss: 4935680,\n heapTotal: 1826816,\n heapUsed: 650472 }
\nheapTotal
와 heapUsed
는 V8의 메모리 사용량을 참조한다.\n\n\n
이벤트 루프의 다음 번 루프에서 이 callback을 호출한다.\n이는 단순히 setTimeout(fn, 0)
에 대한 별칭이 아니라 훨씬 더 효율적이다.\n이는 보통 어떤 I/O 이벤트도 발생하기 전에 실행되지만 몇가지 예외가 존재한다.\n아래의 process.maxTickDepth
를 참고해라.\n\n
process.nextTick(function() {\n console.log('nextTick callback');\n});
\n이는 객체가 만들어 진 후이지만 어떤 I/O도 발생하기 전에 사용자가 이벤트 핸들러를 할당할 기회를\n주고자 하는 API를 개발할 때 중요하다.\n\n
\nfunction MyThing(options) {\n this.setupOptions(options);\n\n process.nextTick(function() {\n this.startDoingStuff();\n }.bind(this));\n}\n\nvar thing = new MyThing();\nthing.getReadyForStuff();\n\n// thing.startDoingStuff()는 이제 호출된다.(그 이전이 아니라)
\n이는 100% 동기이거나 100% 비동기여야 하는 API에 아주 중요한다.\n다음 예제를 봐라.\n\n
\n// WARNING! DO NOT USE! BAD UNSAFE HAZARD!\nfunction maybeSync(arg, cb) {\n if (arg) {\n cb();\n return;\n }\n\n fs.stat('file', cb);\n}
\n이 API는 위험하다. 다음과 같이 사용한다면\n\n
\nmaybeSync(true, function() {\n foo();\n});\nbar();
\nfoo()
와 bar()
중 어느 쪽이 먼저 호출될 것인지 명확하지 않다.\n\n
다음 접근방법이 훨씬 좋다.\n\n
\nfunction definitelyAsync(arg, cb) {\n if (arg) {\n process.nextTick(cb);\n return;\n }\n\n fs.stat('file', cb);\n}
\n",
"signatures": [
{
"params": [
{
"name": "callback"
}
]
}
]
},
{
"textRaw": "process.umask([mask])",
"type": "method",
"name": "umask",
"desc": "프로세스의 파일 모드 생성 마스크를 설정하거나 읽는다. 자식 프로세스는 부모 프로세스에서\n이 마스크를 상속받는다. mask
아규먼트를 전달하면 이전의 마스크를 리턴하고 mask
아규먼트를\n전달하지 않으면 현재 마스크를 리턴한다.\n\n
var oldmask, newmask = 0644;\n\noldmask = process.umask(newmask);\nconsole.log('Changed umask from: ' + oldmask.toString(8) +\n ' to ' + newmask.toString(8));
\n",
"signatures": [
{
"params": [
{
"name": "mask",
"optional": true
}
]
}
]
},
{
"textRaw": "process.uptime()",
"type": "method",
"name": "uptime",
"desc": "Node가 실행되고 있는 시간을 초단위로 나타낸다.\n\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "process.hrtime()", "type": "method", "name": "hrtime", "desc": "[seconds, nanoseconds]
튜플 배열 형식으로 현재의 고해상도(high-resolution)\n실제 시간을 반환한다. 이는 과거 임의의 시간과 관계가 있고 시각과는 관련이 없으므로\n클럭 드리프트(clock drift)를 따르지 않는다. 어떤 구간사이의 성능을 측정하는 것이\n주요 사용처이다.\n\n
어떤 구간을 벤치마킹을 위해 시간 간격을 얻기 위해 process.hrtime()
에 이전 호출의 결과를\n전달한다.\n\n
var time = process.hrtime();\n// [ 1800216, 25 ]\n\nsetTimeout(function() {\n var diff = process.hrtime(time);\n // [ 1, 552 ]\n\n console.log('benchmark took %d nanoseconds', diff[0] * 1e9 + diff[1]);\n // benchmark took 1000000527 nanoseconds\n}, 1000);
\n",
"signatures": [
{
"params": []
}
]
}
]
}
],
"vars": [
{
"textRaw": "require()",
"type": "var",
"name": "require",
"desc": "모듈을 require한다. [Modules][]부분을 봐라.\nrequire
는 실제로 전역이 아니라 각 모듈의 지역범위다.\n\n
모듈의 위치를 검색하는데 내부 require()
장치(machinery)를 사용한다. 모듈을 로딩하는\n것이 아니라 처리된 파일명을 리턴할 뿐이다.\n\n
모듈을 require했을 때 모듈은 이 객체에 캐시된다. 이 객체에서 키 값을 삭제하면 다음 번\nrequire
에서 해당 모듈을 다시 로드할 것이다.\n\n
특정 파일 확장자를 어떻게 다룰지를 require
에 지시한다.\n\n
.sjs
확장자의 파일을 .js
처럼 처리한다.\n\n
require.extensions['.sjs'] = require.extensions['.js'];
\nDeprecated 과거에 이 항목은 요청에 따라 컴파일해서 Node에 자바스크립트가 아닌 모듈을\n로드하는데 사용했다. 하지만 실제로 다른 몇몇 Node 프로그램을 통해서 모듈을 로딩하거나\nahead of time으로 자바스크립트로 컴파일하는 등의 이를 위한 훨씬 더 좋은 방법이 존재한다.\n\n
\nModule 시스템이 locked 상태이므로 이 기능은 없어지지 않을 것이다. 하지만 미묘한 버그나\n건드릴 수 없는 복잡성을 가질 수 있다.\n\n
\n" } ] }, { "textRaw": "__filename", "name": "__filename", "type": "var", "desc": "실행되는 코드의 파일명이다. 이 코드 파일을 처리한 절대경로이다. 메인 프로그램에서 이는\n커맨드라인에서 사용한 것과 반드시 같은 파일명은 아니다. 모듈내부에서 이 값은 해당 모듈 파일에\n대한 경로이다.\n\n
\n예제: /Users/mjr
에서 node example.js
를 실행한다.\n\n
console.log(__filename);\n// /Users/mjr/example.js
\n__filename
은 실제로 전역이 아니라 각 모듈의 지역범위이다.\n\n
현재 실행되는 스크립트가 존재하는 디렉토리 이름이다.\n\n
\n예제: /Users/mjr
에서 node example.js
를 실행한다.\n\n
console.log(__dirname);\n// /Users/mjr
\n__dirname
는 실제로 전역이 아니라 각 모듈의 지역범위이다.\n\n\n
현재 모듈에 대한 참조이다. 특히 module.exports
는 exports
객체와 같다.\nmodule
는 실제로 전역이 아니라 각 모듈의 지역범위이다.\n\n
더 자세한 내용은 [module system documentation][]를 봐라.\n\n
\n" }, { "textRaw": "exports", "name": "exports", "type": "var", "desc": "현재 모듈과 require()
로 접근가능하게 된 모듈의 모든 인스턴스 사이에서 공유되는\nmodule.exports
객체에 대한 참조. 언제 exports
를 사용하고 언제 module.exports
를\n사용하는 지에 대한 자세한 내용은 [module system documentation][]를 참고해라.\nexports
는 실제로 전역이 아니라 각 모듈의 지역범위이다.\n\n
더 자세한 내용은 [module system documentation][]를 봐라.\n\n
\n더 자세한 내용은 [module section][]를 봐라.\n\n
\n" } ], "methods": [ { "textRaw": "setTimeout(cb, ms)", "type": "method", "name": "setTimeout", "desc": "최소 ms
밀리초 후에 콜백 cb
를 실행한다. 실제 지연시간은 OS 타이머의 크기와 시스템\n부하같은 외부 요소에 달려있다.\n\n
타임아웃은 1-2,147,483,647의 범위여야 한다. 값이 이 범위 밖이면 타임아웃은 1 밀리초로\n바뀐다. 대략적으로 말해서 타이머는 24.8일이상이 될 수 없다.\n\n
\n타이머를 나타내는 불투명한 값을 반환한다.\n\n
\n", "signatures": [ { "params": [ { "name": "cb" }, { "name": "ms" } ] } ] }, { "textRaw": "clearTimeout(t)", "type": "method", "name": "clearTimeout", "desc": "이전에 setTimeout()
로 생성된 타이머를 멈춘다. 콜백은 실행하지 않을 것이다.\n\n
ms
밀리초마다 반복적으로 콜백 cb
를 실행한다. 실제 간격은 OS 타이머의 크기나 시스템\n부하같은 외부 요소에 따라 다양하다. 시간간격은 ms
보다 작을 수 없다.\n\n
간격은 1-2,147,483,647의 범위여야 한다. 값이 이 범위 밖이면 1밀리초로 바뀐다. 대력적으로\n말해서 타이머는 24.8일 이상이 될 수 없다.\n\n
\n타이머를 나타내는 불투명한 값을 반환한다.\n\n
\n", "signatures": [ { "params": [ { "name": "cb" }, { "name": "ms" } ] } ] } ], "modules": [ { "textRaw": "Timers", "name": "timers", "stability": 5, "stabilityText": "Locked", "desc": "timer 함수는 모두 전역객체이다. timer를 사용하기 위해 이 모듈을 require()
할\n필요가 없다.\n\n
delay
밀리초 후에 callback
을 한번만 실행하도록 스케쥴링한다. clearTimeout()
과 사용할\n수 있도록 timeoutId
를 리턴한다. 선택적으로 콜백에 아규먼트를 전달할 수 있다.\n\n
콜백이 정확한 delay
밀리초에 실행되지 않을 수도 있다는 점은 중요하다. - Node.js는 콜백이\n정확한 타이밍에 실행된다는 것을 보장하지 않고 순차적으로 실행된다는 것도 보장하지 않는다. 콜백은\n지정한 시간과 가능한한 가깝게 호출할 것이다.\n\n
타임머가 트리거되는 것을 막는다.\n\n
\n", "signatures": [ { "params": [ { "name": "timeoutId" } ] } ] }, { "textRaw": "setInterval(callback, delay, [arg], [...])", "type": "method", "name": "setInterval", "desc": "delay
밀리초마다 callback
실행을 반복하도록 스케쥴링한다. clearInterval()
에서\n사용할 수 있도록 intervalId
를 리턴한다. 선택적으로 콜백에 아규먼트를 전달할 수도 있다.\n\n
인터벌의 실행을 멈춘다.\n\n
\n", "signatures": [ { "params": [ { "name": "intervalId" } ] } ] }, { "textRaw": "unref()", "type": "method", "name": "unref", "desc": "setTimeout
와 setInterval
이 반환한 불투명한(opaque) 값도 활성화된 타이머이기는 하지만\n이 타이머가 이벤트 루프에서 유일하게 남은 것일 경우에는 프로그램이 동작하도록 유지하지는 못하는 타이머를\n생성할 수 있도록 할 timer.unref()
메서드를 가진다. 타이머에 이미 unref
를 호출했다면\nunref
를 다시 호출해도 아무런 영향이 없을 것이다.\n\n
setTimeout
의 경우 unref
하면 이벤트 루프를 깨울 분리된 타이머를 생성한다. 이 타이머를\n너무 많이 생성하면 이벤트 루프 성능에 역효과를 줄 수 있다. -- 잘 사용해라.\n\n
이전에 unref()
된 타이머가 있다면 타이머가 가진 프로그램을 열도록 명시적으로 요청하는 ref()
를\n호출할 수 있다. 타이머에 이미 ref
를 호출했다면 ref
를 다시 호출해도 아무런 영향이 없을 것이다.\n\n
I/O 이벤트 콜백후와 setTimeout
와 setInterval
이전에 callback
을 "즉시" 실행하도록\n스케쥴링한다. clearImmediate()
와 사용할 수 있는 immediateId
를 반환한다. 선택적으로\n콜백에 인자를 전달할 수도 있다.\n\n
Immediate는 생성한 순서대로 큐에 들어가고 루프 이터레이션마나 하나씩 큐에서 빠진다. 이 부분이\n이터레이션마다 process.maxTickDepth
큐에 있는 콜백을 실행하는 process.nextTick
와\n다른 점이다. setImmediate
는 큐에 있는 콜백을 실행한 후에 I/O가 실행되도록 보장하기 위해 이벤트\n루프에 양보할 것이다. 실행하는 동안 순서가 유지되지만 다른 I/O 이벤트는 스케쥴된 두\nimmediate 콜백사이에서 실행될 것이다.\n\n
immediate의 실행을 멈춘다.\n\n
\n", "signatures": [ { "params": [ { "name": "immediateId" } ] } ] } ], "type": "module", "displayName": "Timers" }, { "textRaw": "Modules", "name": "module", "stability": 5, "stabilityText": "Locked", "desc": "매우 간단하게 모듈을 로딩할 수 있다. 노드에서는 파일 하나가 모듈 하나다. 예를 들어 foo.js
파일에서\n같은 디렉토리에 있는 circle.js
를 로드하는 것을 살펴보자.\n\n
foo.js
:\n\n
var circle = require('./circle.js');\nconsole.log( 'The area of a circle of radius 4 is '\n + circle.area(4));
\ncircle.js
:\n\n
var PI = Math.PI;\n\nexports.area = function (r) {\n return PI * r * r;\n};\n\nexports.circumference = function (r) {\n return 2 * PI * r;\n};
\ncircle.js
모듈은 area()
와 circumference()
를 Export했다.\n뭔가 Export하려면 해당 객체를 exports
객체에 할당한다. exports
는\nExport하기 위해 사용하는 객체다.\n\n
exports
는 추가할 때만 사용할 수 있는 module.exports
의 참조이다.\n생성자같은 단일 아이템을 익스포트한다면 module.exports
를 직접 사용해야 한다.\n\n
function MyConstructor (opts) {\n //...\n}\n\n// BROKEN: exports를 수정하지 않는다\nexports = MyConstructor;\n\n// 생성자를 제대로 익스포트한다\nmodule.exports = MyConstructor;
\n로컬 변수는 모듈 외부에 노출되지 않는다(private). 이 예제에서 PI
는 circle.js
에서만\n사용할 수 있는 private 변수다.\n\n
이 모듈 시스템은 module
이라는 모듈에 구현했다.\n\n
두 모듈이 require()
함수로 서로 참조할 때는 한쪽 모듈은 아직 완전히 로딩하지 못한 미완성\n모듈을 그냥 반환한다.\n\n
이게 무슨 소리냐 하면:\n\n
\na.js
:\n\n
console.log('a starting');\nexports.done = false;\nvar b = require('./b.js');\nconsole.log('in a, b.done = %j', b.done);\nexports.done = true;\nconsole.log('a done');
\nb.js
:\n\n
console.log('b starting');\nexports.done = false;\nvar a = require('./a.js');\nconsole.log('in b, a.done = %j', a.done);\nexports.done = true;\nconsole.log('b done');
\nmain.js
:\n\n
console.log('main starting');\nvar a = require('./a.js');\nvar b = require('./b.js');\nconsole.log('in main, a.done=%j, b.done=%j', a.done, b.done);
\nmain.js
는 a.js
를 로드하고, a.js
는 b.js
를 로드한다. 여기서 b.js
는 다시 a.js
를\n로드하려고 한다. 무한 루프가 생기지 않도록 아직 미완성인 a.js
의 exports
객체를 b.js
에\n반환해 버린다. 그리고 b.js
가 완성되면 a.js
에 반환된다.\n\n
main.js
이 두 모듈을 로드할 때는 이미 둘 다 완성됐다. 이 프로그램의 실행 결과는 다음과 같다:\n\n
$ node main.js\nmain starting\na starting\nb starting\nin b, a.done = false\nb done\nin a, b.done = true\na done\nin main, a.done=true, b.done=true
\n그러니까 꼭 모듈을 서로 참조하게 하여야 하면 계획을 잘 짜야 한다.\n\n
\n" }, { "textRaw": "Core Modules", "name": "Core Modules", "type": "misc", "desc": "Node 모듈 중에서는 바이너리로 컴파일해야 하는 모듈이 있다. 코어 모듈은 이 문서 곳곳에서 설명한다.\n\n
\n코어 모듈은 Node 소스코드의 lib/
폴더에 들어 있다.\n\n
모듈을 require하면 항상 코어 모듈이 먼저 로드된다. 예를 들어, require('http')
로 로드될 것\n같은 파일이 있어도 Node에 들어 있는 HTTP 모듈이 반환된다.\n\n
입력한 이름으로 파일을 못 찾으면 Node는 그 이름에 .js
, .json
, .node
를 붙이고\n해당 파일이 있는지 찾는다.\n\n
.js
파일은 JavaScript 텍스트 파일로 Interpret하고 .json
은 JSON 텍스트 파일로\nInterpret한다. 그리고 .node
파일은 컴파일한 addon 모듈이라서 dlopen
으로 로드한다.\n\n
모듈을 절대 경로로 찾을 때는 모듈 이름을 '/'
로 시작하면 된다. 예를 들어,\nrequire('home/marco/foo.js')
는 /home/marco/foo.js
파일을 로드한다.\n\n
모듈을 상대 경로로 찾으려면 모듈 이름이 './'
로 시작하면 된다. 즉, foo.js
라는 파일에서\nrequire('./circle')
라고 호출하면 같은 디렉토리에 있는 circle.js
를 로드한다.\n\n
'/'이나 './'로 시작하지 않으면 그냥 파일이 아니라 "코어 모듈"이나 node_modules
폴더에 있는\n모듈을 찾는다.\n\n
주어진 경로가 존재하지 않으면 require()
는 code
프로퍼티를\n'MODULE_NOT_FOUND'
로 설정해서 Error를 던질 것이다.\n\n
require()
에 넘어온 모듈 ID가 네이티브 모듈을 가리키는 것도 아니고, 그 모듈 ID가\n'/'
, './'
, '../'
로 시작하지도 않으면 Node는 그 모듈의 상위 디렉토리에서 찾기 시작한다.\n상위 디렉토리에 있는 /node_modules
에서 해당 모듈을 찾는다.\n\n
만약 못 찾으면 상위상위 디렉토리에서 찾고, 그래도 못 찾으면 상위상위상위 디렉토리에서 찾는다.\n루트 디렉토리에 다다를 때까지 계속 찾는다.\n\n
\n예를 들어, 'home/ry/projects/foo.js'
라는 파일에서 requre('bar.js')
라고 호출하면\n다음과 같은 순서로 모듈을 찾는다:\n\n
/home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
그래서 해당 프로그램만의 의존성을 독립적으로 관리할 수 있다. 다른 프로그램에 영향을 끼치지 않는다.\n\n
\n" }, { "textRaw": "Folders as Modules", "name": "Folders as Modules", "type": "misc", "desc": "모듈을 폴더로 관리하면 프로그램과 라이브러리를 묶음으로 관리할 수 있어 편리하다. 마치 한 파일로 된\n모듈처럼 취급한다. 모듈이 폴더일 때 require()
는 세 가지 방법으로 모듈을 찾는다.\n\n
프로그램 폴더에 package.json
파일을 만들고 main 모듈이 무엇인지 적는다:\n\n
{ "name" : "some-library",\n "main" : "./lib/some-library.js" }
\n이 파일이 ./some-library
라는 폴더에 있다고 하고, require('./some-library')
를 호출하면\n./some-library/lib/some-library.js
를 찾아 로드한다.\n\n
Node가 package.json을 읽고 사용하기 때문에 이런 게 가능하다.\n\n
\n그 디렉토리에 package.json 파일이 없으면 Node는 index.js
나 index.node
파일을 찾는다.\npackage.json 파일이 없으면 require('./some-library')
는 다음과 같은 파일을 로드한다:\n\n
./some-library/index.js
./some-library/index.node
한 번 로드한 모듈은 계속 캐싱한다. 그래서 require('foo')
을 여러 번 호출해도 계속 같은 객체를\n반환한다. 단, `require('foo')가 계속 같은 파일을 로드할 때만 그렇다.\n\n
require('foo')
를 여러 번 호출해도 해당 모듈 코드는 단 한 번만 호출된다. 그리고 아직 미완성인\n객체가 반환될 수 있다는 점까지 더하면 특정 모듈이 서로 의존하고 있어도 성공적으로 로드되는 마법이\n이루어진다.\n\n
어떤 코드가 꼭 여러 번 호출돼야 하면 함수 자체를 Export하고 그 함수를 여러 번 호출하라.\n\n
\n", "miscs": [ { "textRaw": "Module Caching Caveats", "name": "Module Caching Caveats", "type": "misc", "desc": "모듈은 찾은(resolved) 파일 이름을 키로 캐싱한다. node_modules
폴더에서 로딩하는 것이기 때문에\n같은 require 코드라도 호출하는 위치에 따라 찾은 파일이 다를 수 있다. 즉, require('foo')
가\n다른 파일을 찾아낸다면 다른 객체를 리턴한다.\n\n
require()
로 모듈을 찾을 때 정확한 파일 경로가 궁금하면 require.resolve()
함수로 얻어온다.\n\n
require.resolve가 정확히 어떻게 동작하는지 슈도 코드로 살펴보자. 이 슈도 코드는 여태까지\n설명한 것을 모두 합쳐 놓은 것이다:\n\n
\nrequire(X) from module at path Y\n1. If X is a core module,\n a. return the core module\n b. STOP\n2. If X begins with './' or '/' or '../'\n a. LOAD_AS_FILE(Y + X)\n b. LOAD_AS_DIRECTORY(Y + X)\n3. LOAD_NODE_MODULES(X, dirname(Y))\n4. THROW "not found"\n\nrequire(X) from module at path Y\n1. If X is a core module,\n a. return the core module\n b. STOP\n2. If X begins with './' or '/' or '../'\n a. LOAD_AS_FILE(Y + X)\n b. LOAD_AS_DIRECTORY(Y + X)\n3. LOAD_NODE_MODULES(X, dirname(Y))\n4. THROW "not found"\n\nLOAD_AS_FILE(X)\n1. If X is a file, load X as JavaScript text. STOP\n2. If X.js is a file, load X.js as JavaScript text. STOP\n3. If X.node is a file, load X.node as binary addon. STOP\n\nLOAD_AS_DIRECTORY(X)\n1. If X/package.json is a file,\n a. Parse X/package.json, and look for "main" field.\n b. let M = X + (json main field)\n c. LOAD_AS_FILE(M)\n2. If X/index.js is a file, load X/index.js as JavaScript text. STOP\n3. If X/index.node is a file, load X/index.node as binary addon. STOP\n\nLOAD_NODE_MODULES(X, START)\n1. let DIRS=NODE_MODULES_PATHS(START)\n2. for each DIR in DIRS:\n a. LOAD_AS_FILE(DIR/X)\n b. LOAD_AS_DIRECTORY(DIR/X)\n\nNODE_MODULES_PATHS(START)\n1. let PARTS = path split(START)\n2. let ROOT = index of first instance of "node_modules" in PARTS, or 0\n3. let I = count of PARTS - 1\n4. let DIRS = []\n5. while I > ROOT,\n a. if PARTS[I] = "node_modules" CONTINUE\n c. DIR = path join(PARTS[0 .. I] + "node_modules")\n b. DIRS = DIRS + DIR\n c. let I = I - 1\n6. return DIRS
\n"
},
{
"textRaw": "Loading from the global folders",
"name": "Loading from the global folders",
"type": "misc",
"desc": "Node는 모듈을 못 찾으면 환경변수 NODE_PATH
에 등록된 경로에서도 찾는다. 절대경로를\nNODE_PATH
에 할당하면 되는데 콜론(:
)으로 구분해서 절대경로를 여러 개 등록할 수 있다(주의:\n윈도우는 세미콜론(;
)으로 구분한다).\n\n
그리고 Node는 다른 디렉토리에서도 찾는다:\n\n
\n$HOME/.node_modules
$HOME/.node_libraries
$PREFIX/lib/node
$HOME
은 사용자의 홈 디렉토리이고 $PREFIX
는 노드에 설정된 node_prefix
를 말한다.\n\n
왜 그런지 말하자면 길다. 무엇보다 node_modules
폴더를 이용해 모듈을 로컬에 설치하는 것이 좋다.\n이 방법이 속도도 더 빠르고 더 안전하다.\n\n
node로 어떤 파일을 실행하면 require.main
은 그 파일의 module
객체를 가리킨다. 그래서\nNode로 파일을 직접 실행한 건지 아닌지 알 수 있다:\n\n
require.main === module
\nfoo.js
라는 파일에 이런 게 들어 있다고 하자. 이 구문의 결과는 node foo.js
로 실행하면\ntrue
이고 require('./foo')
로 실행하면 false
가 된다.\n\n
module
에는 filename
프로퍼티가 있어서(__filename
과 같은 값이다)\nrequire.main.filename
의 값을 확인하면 처음 실행한 파일을 무엇인지 알 수 있다.\n\n
require()
함수는 웬만한 디렉토리면 어디에서나 사용할 수 있다. dpkg
, rpm
같은 패키지\n매니저처럼 npm
도 네이티브 Node 패키지를 아무런 수정 없이 빌드하게 할 수 있다.\n\n
다음은 어떻게 디렉토리를 구성해야 모듈이 제대로 동작하는지 설명한다:\n\n
\n모듈은 /usr/lib/node/<some-package>/<some-version>
에 설치하는 것을 권장한다. 어떤\n패키지의 어떤 버전이 설치됐는지 한 눈에 알 수 있어 좋다.\n\n
패키지는 다른 패키지에 의존할 수도 있다. 예를 들어 foo
패키지를 설치하려면 bar
패키지도\n설치해야 한다. 그것도 특정 버전의 bar
패키지가 설치돼야 한다. 그리고 bar
패키지도 다른\n패키지에 의존할 수 있는데 충돌이 있거나 서로(cycle) 의존할 수도 있다.\n\n
Node는 로드할 모듈을 찾을 때 node_modules
폴더에서 필요한 모듈을 찾는다. 그중에 심볼릭 링크가\n있으면 그 링크가 가리키는 모듈도 잘 찾는다. 다음과 같이 모듈을 찾는 매커니즘은 매우 간단하다:\n\n
/usr/lib/node/foo/1.2.3/
- 버전이 1.2.3인 foo
패키지/usr/lib/node/bar/4.3.2/
- foo
가 의존하는 bar
패키지/usr/lib/node/foo/1.2.3/node_modules/bar
- /usr/lib/node/bar/4.3.2/
에 대한 심볼릭 링크/usr/lib/node/bar/4.3.2/node_modules/*
- bar
가 의존하는 패키지에 대한 심볼릭 링크그리고 상호 참조나 의존성 충돌이 있어도 모듈을 사용할 수만 있으면 잘 로드한다.\n\n
\nfoo
패키지에서 require('bar')
라고 하면\n/usr/lib/node/foo/1.2.3/node_modules/bar
가 가리키는 모듈을 가져온다. 또 그 bar
\n패키지에서 require('quux')
라고 호출하면\n/usr/lib/node/bar/4.3.2/node_modules/quux
가 가리키는 모듈을 가져온다.\n\n
최적화된 방법으로 모듈을 찾는 방법이 있는데 /usr/lib/node
디렉토리가 아니라\n/usr/lib/node_modules/<name>/<version>
에 모듈을 넣는다. 그러면 Node는\n/usr/node_modules
이나 /node_modules
에서는 모듈을 찾지 않는다.\n\n
/usr/lib/node_modules
폴더를 환경 변수 $NODE_PATH
에 넣으면 Node REPL에서도 모듈을\n사용할 수 있다. require()
를 호출한 파일이 있는 곳에서부터 상대경로로 node_modules
폴더에\n있는 모듈을 찾기 때문에 패키지는 그 node_modules
폴더 중 한 곳에 넣으면 된다.\n\n
모듈에서 module
변수는 해당 모듈 객체를 가리킨다. 특히 module.exports
는\nexports
전역모듈(module-global)로 접근할 수 있다. module
은 글로벌 변수가\n아니라 모듈마다 다른 객체를 가리키는 로컬 변수다.\n\n
module.exports
객체는 Module 시스템이 자동으로 만들어 준다. Export하려는 객체를\nmodule.exports
에 할당해서 직접 만든 객체가 반환되게 할 수도 있다.\n.js
라는 모듈을 만들어 보자:\n\n
var EventEmitter = require('events').EventEmitter;\n\nmodule.exports = new EventEmitter();\n\n// Do some work, and after some time emit\n// the 'ready' event from the module itself.\nsetTimeout(function() {\n module.exports.emit('ready');\n}, 1000);
\n이 모듈은 다음과 같이 사용한다:\n\n
\nvar a = require('./a');\na.on('ready', function() {\n console.log('module a is ready');\n});
\nmodule.exports
에 할당하는 것은 바로 실행되도록 해야 한다. 콜백으로 할당문이 실행되는 것을\n미루면 뜻대로 동작하지 않는다. 다음과 같이 하지 마라:\n\n
x.js:\n\n
\nsetTimeout(function() {\n module.exports = { a: "hello" };\n}, 0);
\ny.js:\n\n
\nvar x = require('./x');\nconsole.log(x.a);
\n"
},
{
"textRaw": "`id` {String} ",
"name": "id",
"desc": "모듈 ID인데 보통은 모듈 파일의 전체 경로를 사용한다.\n\n\n
\n" }, { "textRaw": "`filename` {String} ", "name": "filename", "desc": "모듈 파일의 전체 경로(fully resolved filename).\n\n\n
\n" }, { "textRaw": "`loaded` {Boolean} ", "name": "loaded", "desc": "모듈이 로드하고 있는 중인지 다 로드했는지를 나타낸다.\n\n\n
\n" }, { "textRaw": "`parent` {Module Object} ", "name": "parent", "desc": "모듈을 require한 모듈을 가리킨다.\n\n\n
\n" }, { "textRaw": "`children` {Array} ", "name": "children", "desc": "모듈이 require한 모듈 객체를 가리킨다.\n\n\n\n
\n" } ], "methods": [ { "textRaw": "module.require(id)", "type": "method", "name": "require", "signatures": [ { "return": { "textRaw": "Return: {객체} 처리된 모듈의 `module.exports` ", "name": "return", "type": "객체", "desc": "처리된 모듈의 `module.exports`" }, "params": [ { "textRaw": "`id` {문자열} ", "name": "id", "type": "문자열" } ] }, { "params": [ { "name": "id" } ] } ], "desc": "module.require
메소드로 모듈을 로드하면 해당 모듈에서 require()를 호출하는 것처럼 모듈을\n로드한다.\n\n
이 메소드를 호출하려면 일단 module
객체의 레퍼런스를 얻어야 한다. module
객체의 레퍼런스는\n해당 모듈에서만 접근할 수 있고 require()
는 module
이 아니라 module.exports
를 리턴하기\n때문에 해당 모듈에서 module 객체의 레퍼런스를 직접 리턴해야 한다.\n\n\n
애드온은 동적으로 공유 객체를 연결합니다. 애드온은 C나 C++ 라이브러리에 연결할 수 있다.\nAPI는(현 시점에) 여러 가지 라이브러리에 대한 지식을 포함해서 상당히 복잡하다.\n\n
\nV8 자바스트립트, C++ 라이브러리. 자바스크립트와 인터페이스로 연결하는데 사용한다:\n객체를 생성하고 함수를 호출하는 등. v8.h
헤더파일(Node 소스트리의\ndeps/v8/include/v8.h
)에 주로 문서화되어 있고\nonline에서도 확인할 수 있다.
libuv, C 이벤트루프 라이브러리. 파일 디스크립터가\n읽을 수 있게 되기를 기다린다거나 타이머를 기다리거나 받아야할 신호를 기다려야 할 때는\n언제든지 libuv와 인터페이스로 연결할 필요가 있을 것이다. 즉 어떤 I/O라도 수행한다면\nlibuv를 사용해야 한다.
\n내부 Node 라이브러리. 가장 중요한 것은 node::ObjectWrap
클래스이다. 아마\n이 클래스에서 파생하기를 원할 것이다.
그 밖에. 무엇을 사용할 수 있는지 알고 싶으면 deps/
를 봐라.
Node는 실행가능하도록 모든 의존성을 정적으로 컴파일한다. 모듈을 컴파일할 때 이러한\n라이브러리의 연결에 대해서 걱정할 필요가 없다.\n\n
\n아래의 예제는 모두 download에서\n다운받을 수 있고 자신만의 애드온을 작성할 때 시작지점으로 사용할 수 있다.\n\n
\n", "modules": [ { "textRaw": "Hello world", "name": "hello_world", "desc": "다음 자바스크립트 코드와 동일한 작은 애드온을 C++로 작성하면서 시작해 보자.\n\n
\nmodule.exports.hello = function() { return 'world'; };
\n우선 hello.cc
파일을 생성한다.\n\n
#include <node.h>\n#include <v8.h>\n\nusing namespace v8;\n\nHandle<Value> Method(const Arguments& args) {\n HandleScope scope;\n return scope.Close(String::New("world"));\n}\n\nvoid init(Handle<Object> exports) {\n exports->Set(String::NewSymbol("hello"),\n FunctionTemplate::New(Method)->GetFunction());\n}\nNODE_MODULE(hello, init)
\n모든 Node 애드온은 초기화 함수를 외부에 노출해야 한다.\n\n
\nvoid Initialize (Handle<Object> exports);\nNODE_MODULE(module_name, Initialize)
\n함수가 아니므로 NODE_MODULE
뒤에 세미콜론이 없다.(node.h
를 봐라.)\n\n
module_name
은 최종 바이너리의 파일명과 일치시켜야 한다.(.node 접미사는 제외하고)\n\n
소스코드는 바이너리 애드온인 hello.node
로 빌드되어야 한다. 이를 위해서\nJSON과 유사한 형식으로 모듈의 빌드 설정을 나타내는 binding.gyp
파일을 생성해야 한다.\n이 파일은 node-gyp가 컴파일한다.\n\n
{\n "targets": [\n {\n "target_name": "hello",\n "sources": [ "hello.cc" ]\n }\n ]\n}
\n다음 과정은 현재 플랫폼에 적절한 프로젝트 빌드 파일을 생성하는 것이다.\n빌드파일을 생성하기 위해서 node-gyp configure
를 사용해라.\n\n
이제 build/
디렉토리에 Makefile
(Unix 플랫폼)과 vcxproj
(Windows 플랫폼)가\n있을 것이다. 그 다음 node-gyp build
명령어를 실행한다.\n\n
컴파일된 .node
바인딩 파일을 얻었다! 컴파일된 파인딩 파일들은 build/Release/
에 있다.\n\n
최근에 빌드한 hello.node
모듈을 require
함으로써 Node 프로젝트 hello.js
에서 바이너리\n애드온을 사용할 수 있다.\n\n
var addon = require('./build/Release/hello');\n\nconsole.log(addon.hello()); // 'world'
\n더 많은 정보는 아래의 패턴들을 보거나 실사용 예제를 보려면\n
\nhttps://github.com/pietern/hiredis-node를 봐라.\n\n\n
\n", "type": "module", "displayName": "Hello world" }, { "textRaw": "Addon patterns", "name": "addon_patterns", "desc": "다음은 애드온 개발을 시작할 때 도움이 될만한 애드폰 패턴들이다. 여러 가지 v8 호출에 대해서는\n온라인 v8 reference를 참고하고 핸들, 범위, 함수 템플릿\n등과 같이 사용된 여러가지 개념에 대한 설명은 v8의\nEmbedder's Guide를 참고해라.\n\n
\n이 예제를 사용하려면 node-gyp
를 사용해서 컴파일해야 한다.\n다음과 같은 binding.gyp
파일을 생성해라.\n\n
{\n "targets": [\n {\n "target_name": "addon",\n "sources": [ "addon.cc" ]\n }\n ]\n}
\n하나 이상의 .cc
파일이 있는 경우에 sources
배열에 파일명을 다음과 같이 추가해라.\n\n
"sources": ["addon.cc", "myexample.cc"]
\nbinding.gyp
파일을 준비했으면 애드온을 설정하고 빌드할 수 있다.\n\n
$ node-gyp configure build
\n",
"modules": [
{
"textRaw": "Function arguments",
"name": "function_arguments",
"desc": "다음 패턴은 자바스크립트 함수 호출에서 어떻게 아규먼트들을 읽고 결과를 리턴하는 지 보여준다.\n다음 파일이 메인파일이고 소스파일인 addon.cc
만 필요하다.\n\n
#define BUILDING_NODE_EXTENSION\n#include <node.h>\n\nusing namespace v8;\n\nHandle<Value> Add(const Arguments& args) {\n HandleScope scope;\n\n if (args.Length() < 2) {\n ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));\n return scope.Close(Undefined());\n }\n\n if (!args[0]->IsNumber() || !args[1]->IsNumber()) {\n ThrowException(Exception::TypeError(String::New("Wrong arguments")));\n return scope.Close(Undefined());\n }\n\n Local<Number> num = Number::New(args[0]->NumberValue() +\n args[1]->NumberValue());\n return scope.Close(num);\n}\n\nvoid Init(Handle<Object> exports) {\n exports->Set(String::NewSymbol("add"),\n FunctionTemplate::New(Add)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
\n다음 자바스크립트 코드로 이를 테스트할 수 있다:\n\n
\nvar addon = require('./build/Release/addon');\n\nconsole.log( 'This should be eight:', addon.add(3,5) );
\n",
"type": "module",
"displayName": "Function arguments"
},
{
"textRaw": "Callbacks",
"name": "callbacks",
"desc": "C++ 함수에 자바스크립트 함수를 전달해서 C++ 함수에서 자바스크립트 함수를 실행할 수\n있다. 다음은 addon.cc
이다:\n\n
#define BUILDING_NODE_EXTENSION\n#include <node.h>\n\nusing namespace v8;\n\nHandle<Value> RunCallback(const Arguments& args) {\n HandleScope scope;\n\n Local<Function> cb = Local<Function>::Cast(args[0]);\n const unsigned argc = 1;\n Local<Value> argv[argc] = { Local<Value>::New(String::New("hello world")) };\n cb->Call(Context::GetCurrent()->Global(), argc, argv);\n\n return scope.Close(Undefined());\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n module->Set(String::NewSymbol("exports"),\n FunctionTemplate::New(RunCallback)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
\n이 예제는 전체 module
객체를 두번째 인자로 받는 두개의 인자를 갖는 형식의 Init()
를\n사용한다. 이는 애드온이 exports
의 프로퍼티로 함수를 추가하는 대신 하나의 함수로\nexports
를 완전히 덮어쓸 수 있게 한다.\n\n
다음 자바스크립트 코드를 실행해서 이를 테스트 할 수 있다:\n\n
\nvar addon = require('./build/Release/addon');\n\naddon(function(msg){\n console.log(msg); // 'hello world'\n});
\n",
"type": "module",
"displayName": "Callbacks"
},
{
"textRaw": "Object factory",
"name": "object_factory",
"desc": "createObject()
에 전달된 문자열을 출력하는 msg
프로퍼티를 가진 객체를 리턴하는\n이 addon.cc
패턴과 함께 C++ 함수내에서 새로운 객체를 생성해서 리턴할 수 있다.\n\n
#define BUILDING_NODE_EXTENSION\n#include <node.h>\n\nusing namespace v8;\n\nHandle<Value> CreateObject(const Arguments& args) {\n HandleScope scope;\n\n Local<Object> obj = Object::New();\n obj->Set(String::NewSymbol("msg"), args[0]->ToString());\n\n return scope.Close(obj);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n module->Set(String::NewSymbol("exports"),\n FunctionTemplate::New(CreateObject)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
\n자바스크립트에서 다음과 같이 테스트한다:\n\n
\nvar addon = require('./build/Release/addon');\n\nvar obj1 = addon('hello');\nvar obj2 = addon('world');\nconsole.log(obj1.msg+' '+obj2.msg); // 'hello world'
\n",
"type": "module",
"displayName": "Object factory"
},
{
"textRaw": "Function factory",
"name": "function_factory",
"desc": "이 패턴은 C++ 함수를 감싸는 자바스크립트 함수를 어떻게 생성하고 리턴하는지 보여준다:\n\n
\n#define BUILDING_NODE_EXTENSION\n#include <node.h>\n\nusing namespace v8;\n\nHandle<Value> MyFunction(const Arguments& args) {\n HandleScope scope;\n return scope.Close(String::New("hello world"));\n}\n\nHandle<Value> CreateFunction(const Arguments& args) {\n HandleScope scope;\n\n Local<FunctionTemplate> tpl = FunctionTemplate::New(MyFunction);\n Local<Function> fn = tpl->GetFunction();\n fn->SetName(String::NewSymbol("theFunction")); // omit this to make it anonymous\n\n return scope.Close(fn);\n}\n\nvoid Init(Handle<Object> exports, Handle<Object> module) {\n module->Set(String::NewSymbol("exports"),\n FunctionTemplate::New(CreateFunction)->GetFunction());\n}\n\nNODE_MODULE(addon, Init)
\n다음과 같이 테스트한다:\n\n
\nvar addon = require('./build/Release/addon');\n\nvar fn = addon();\nconsole.log(fn()); // 'hello world'
\n",
"type": "module",
"displayName": "Function factory"
},
{
"textRaw": "Wrapping C++ objects",
"name": "wrapping_c++_objects",
"desc": "new
오퍼레이터로 자바스크립트에서 인스턴스화할 수 있는 MyObject
C++ 객체/클래스에 대한\n랩퍼(wrapper)를 생성할 것이다. 우선 메인 모듈 addon.cc
를 준비하자.\n\n
#define BUILDING_NODE_EXTENSION\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nvoid InitAll(Handle<Object> exports) {\n MyObject::Init(exports);\n}\n\nNODE_MODULE(addon, InitAll)
\n그 다음 myobject.h
는 랩퍼가 node::ObjectWrap
를 상속받도록 한다:\n\n
#ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n static void Init(v8::Handle<v8::Object> exports);\n\n private:\n MyObject();\n ~MyObject();\n\n static v8::Handle<v8::Value> New(const v8::Arguments& args);\n static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);\n double counter_;\n};\n\n#endif
\n그리고 myobject.cc
에서 노출할 다양한 메서드를 구현한다.\n여기서 생성자의 프로토타입에 추가해서 plusOne
메서드를 노출했다.\n\n
#define BUILDING_NODE_EXTENSION\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nMyObject::MyObject() {};\nMyObject::~MyObject() {};\n\nvoid MyObject::Init(Handle<Object> exports) {\n // Prepare constructor template\n Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n tpl->SetClassName(String::NewSymbol("MyObject"));\n tpl->InstanceTemplate()->SetInternalFieldCount(1);\n // Prototype\n tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),\n FunctionTemplate::New(PlusOne)->GetFunction());\n\n Persistent<Function> constructor = Persistent<Function>::New(tpl->GetFunction());\n exports->Set(String::NewSymbol("MyObject"), constructor);\n}\n\nHandle<Value> MyObject::New(const Arguments& args) {\n HandleScope scope;\n\n MyObject* obj = new MyObject();\n obj->counter_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n obj->Wrap(args.This());\n\n return args.This();\n}\n\nHandle<Value> MyObject::PlusOne(const Arguments& args) {\n HandleScope scope;\n\n MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());\n obj->counter_ += 1;\n\n return scope.Close(Number::New(obj->counter_));\n}
\n다음 코드로 테스트한다:\n\n
\nvar addon = require('./build/Release/addon');\n\nvar obj = new addon.MyObject(10);\nconsole.log( obj.plusOne() ); // 11\nconsole.log( obj.plusOne() ); // 12\nconsole.log( obj.plusOne() ); // 13
\n",
"type": "module",
"displayName": "Wrapping C++ objects"
},
{
"textRaw": "Factory of wrapped objects",
"name": "factory_of_wrapped_objects",
"desc": "이는 자바스크립트에서 new
오퍼레이터로 명시적인 인스턴스화 없이 네이티브 객체를\n생성할 수 있도록 하고 싶을 때 유용하다.\n\n
var obj = addon.createObject();\n// 대신에:\n// var obj = new addon.Object();
\naddon.cc
에 createObject
메서드를 등록하자:\n\n
#define BUILDING_NODE_EXTENSION\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nHandle<Value> CreateObject(const Arguments& args) {\n HandleScope scope;\n return scope.Close(MyObject::NewInstance(args));\n}\n\nvoid InitAll(Handle<Object> exports, Handle<Object> module) {\n MyObject::Init();\n\n module->Set(String::NewSymbol("exports"),\n FunctionTemplate::New(CreateObject)->GetFunction());\n}\n\nNODE_MODULE(addon, InitAll)
\nmyobject.h
에서 객체의 인스턴스화를 처리하는 정적 메서드 NewInstance
를 도입한다.\n(예를 들어 자바스크립트에서 new
가 하는 일이다.)\n\n
#define BUILDING_NODE_EXTENSION\n#ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n static void Init();\n static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);\n\n private:\n MyObject();\n ~MyObject();\n\n static v8::Persistent<v8::Function> constructor;\n static v8::Handle<v8::Value> New(const v8::Arguments& args);\n static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);\n double counter_;\n};\n\n#endif
\nmyobject.cc
에서 구현체는 위와 유사하다:\n\n
#define BUILDING_NODE_EXTENSION\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nMyObject::MyObject() {};\nMyObject::~MyObject() {};\n\nPersistent<Function> MyObject::constructor;\n\nvoid MyObject::Init() {\n // 생성자 템플릿 준비\n Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n tpl->SetClassName(String::NewSymbol("MyObject"));\n tpl->InstanceTemplate()->SetInternalFieldCount(1);\n // 프로토타입\n tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),\n FunctionTemplate::New(PlusOne)->GetFunction());\n\n constructor = Persistent<Function>::New(tpl->GetFunction());\n}\n\nHandle<Value> MyObject::New(const Arguments& args) {\n HandleScope scope;\n\n MyObject* obj = new MyObject();\n obj->counter_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n obj->Wrap(args.This());\n\n return args.This();\n}\n\nHandle<Value> MyObject::NewInstance(const Arguments& args) {\n HandleScope scope;\n\n const unsigned argc = 1;\n Handle<Value> argv[argc] = { args[0] };\n Local<Object> instance = constructor->NewInstance(argc, argv);\n\n return scope.Close(instance);\n}\n\nHandle<Value> MyObject::PlusOne(const Arguments& args) {\n HandleScope scope;\n\n MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());\n obj->counter_ += 1;\n\n return scope.Close(Number::New(obj->counter_));\n}
\n다음으로 테스트한다:\n\n
\nvar createObject = require('./build/Release/addon');\n\nvar obj = createObject(10);\nconsole.log( obj.plusOne() ); // 11\nconsole.log( obj.plusOne() ); // 12\nconsole.log( obj.plusOne() ); // 13\n\nvar obj2 = createObject(20);\nconsole.log( obj2.plusOne() ); // 21\nconsole.log( obj2.plusOne() ); // 22\nconsole.log( obj2.plusOne() ); // 23
\n",
"type": "module",
"displayName": "Factory of wrapped objects"
},
{
"textRaw": "Passing wrapped objects around",
"name": "passing_wrapped_objects_around",
"desc": "C++ 객체를 감싸고 리턴하는 부분에 대해서 추가적으로 Node의 node::ObjectWrap::Unwrap
\n헬퍼 함수로 이 객체들을 풀어줌으로써(unwrapping) 전달할 수 있다.\n다음 addon.cc
에서 두 MyObject
객체받을 수 있는 add()
함수를 도입한다.\n\n
#define BUILDING_NODE_EXTENSION\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nHandle<Value> CreateObject(const Arguments& args) {\n HandleScope scope;\n return scope.Close(MyObject::NewInstance(args));\n}\n\nHandle<Value> Add(const Arguments& args) {\n HandleScope scope;\n\n MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>(\n args[0]->ToObject());\n MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(\n args[1]->ToObject());\n\n double sum = obj1->Val() + obj2->Val();\n return scope.Close(Number::New(sum));\n}\n\nvoid InitAll(Handle<Object> exports) {\n MyObject::Init();\n\n exports->Set(String::NewSymbol("createObject"),\n FunctionTemplate::New(CreateObject)->GetFunction());\n\n exports->Set(String::NewSymbol("add"),\n FunctionTemplate::New(Add)->GetFunction());\n}\n\nNODE_MODULE(addon, InitAll)
\n흥미롭게 myobject.h
에서 퍼블릭 메서드를 도입해서 객체를 풀어버린(unwrapping) 후\nprivate 값을 자세히 조사할 수 있다:\n\n
#define BUILDING_NODE_EXTENSION\n#ifndef MYOBJECT_H\n#define MYOBJECT_H\n\n#include <node.h>\n\nclass MyObject : public node::ObjectWrap {\n public:\n static void Init();\n static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);\n double Val() const { return val_; }\n\n private:\n MyObject();\n ~MyObject();\n\n static v8::Persistent<v8::Function> constructor;\n static v8::Handle<v8::Value> New(const v8::Arguments& args);\n double val_;\n};\n\n#endif
\nmyobject.cc
의 구현체는 이전과 유사하다:\n\n
#define BUILDING_NODE_EXTENSION\n#include <node.h>\n#include "myobject.h"\n\nusing namespace v8;\n\nMyObject::MyObject() {};\nMyObject::~MyObject() {};\n\nPersistent<Function> MyObject::constructor;\n\nvoid MyObject::Init() {\n // 생성자 템플릿 준비\n Local<FunctionTemplate> tpl = FunctionTemplate::New(New);\n tpl->SetClassName(String::NewSymbol("MyObject"));\n tpl->InstanceTemplate()->SetInternalFieldCount(1);\n\n constructor = Persistent<Function>::New(tpl->GetFunction());\n}\n\nHandle<Value> MyObject::New(const Arguments& args) {\n HandleScope scope;\n\n MyObject* obj = new MyObject();\n obj->val_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();\n obj->Wrap(args.This());\n\n return args.This();\n}\n\nHandle<Value> MyObject::NewInstance(const Arguments& args) {\n HandleScope scope;\n\n const unsigned argc = 1;\n Handle<Value> argv[argc] = { args[0] };\n Local<Object> instance = constructor->NewInstance(argc, argv);\n\n return scope.Close(instance);\n}
\n다음으로 테스트한다:\n\n
\nvar addon = require('./build/Release/addon');\n\nvar obj1 = addon.createObject(10);\nvar obj2 = addon.createObject(20);\nvar result = addon.add(obj1, obj2);\n\nconsole.log(result); // 30
\n",
"type": "module",
"displayName": "Passing wrapped objects around"
}
],
"type": "module",
"displayName": "Addon patterns"
}
],
"type": "module",
"displayName": "Addons"
},
{
"textRaw": "util",
"name": "util",
"stability": 4,
"stabilityText": "API Frozen",
"desc": "이 함수들은 'util'
모듈에 있다. 이 모듈에 접근하려면 require('util')
를 사용해야\n한다.\n\n\n
printf
같은 형식으로 첫 아규먼트를 사용해서 포매팅된 문자열을 반환한다.\n\n
첫 아규먼트는 플레이스홀더가 포함된 문자열이다.(플레이스 홀더는 없어도 된다.)\n각 플레이스 홀더는 대응되는 아규먼트의 값으로 대체된다. 플레이스 홀더는\n다음을 지원한다.\n\n
\n%s
- 문자열.%d
- 숫자 (integer 와 float를 모두 지원한다.).%j
- JSON.%
- 퍼센트기호 ('%'
). 이 기호는 플레이스홀더 아규먼트를 사용하지 않는다.플레이스 홀더에 대응되는 아규먼트가 없으면 플레이스홀더는 치환되지 않는다.\n\n
\nutil.format('%s:%s', 'foo'); // 'foo:%s'
\n플레이스홀더보다 많은 수의 아규먼트가 있으면 남는 아규먼트들은 util.inspect()
를 사용해서\n문자열로 변환되고 스페이스를 구분자로 이 문자열들을 이어붙힌다.\n\n
util.format('%s:%s', 'foo', 'bar', 'baz'); // 'foo:bar baz'
\n첫 아규먼트가 문자열이 아니라면 util.format()
은 모든 아규먼트를 공백문자로 이어붙혀서\n리턴한다. 각 아규먼트는 util.inspect()
를 통해 문자열로 변환한다.\n\n
util.format(1, 2, 3); // '1 2 3'
\n",
"signatures": [
{
"params": [
{
"name": "format"
},
{
"name": "...",
"optional": true
}
]
}
]
},
{
"textRaw": "util.debug(string)",
"type": "method",
"name": "debug",
"desc": "동기적인 출력함수. 프로세스를 블락할 것이고 stderr
에 즉각적으로\nstring
을 출력한다.\n\n
require('util').debug('message on stderr');
\n",
"signatures": [
{
"params": [
{
"name": "string"
}
]
}
]
},
{
"textRaw": "util.error([...])",
"type": "method",
"name": "error",
"desc": "즉시 모든 아규먼트를 stderr
에 출력한다는 점을 제외하면 util.debug()
와 같다.\n\n
동기적인 출력함수. 프로세스를 블락할 것이고 각 아규먼트마다 새로운 라인으로 stdout
에\n모든 아규먼트를 출력할 것이다.\n\n
동기적인 출력함수. 프로세스를 블락할 것이고 각 아규먼트를 문자열로 변환해서 stdout
에\n출력한다. 아규먼트마다 새로운 라인을 넣지 않는다.\n\n
stdout
에 타임스탬프를 출력한다.\n\n
require('util').log('Timestamped message.');
\n",
"signatures": [
{
"params": [
{
"name": "string"
}
]
}
]
},
{
"textRaw": "util.inspect(object, [options])",
"type": "method",
"name": "inspect",
"desc": "디버깅에 유용한 object
의 문자열 표현을 리턴한다.\n\n
포매팅된 문자열의 형식을 바꾸기 위해서 선택적인 options 객체를 전달한다.\n\n
\nshowHidden
- true
이면 객체의 enumerable하지 않는 프로퍼티도 보여준다.\n기본값은 false
이다.
depth
- 객체를 포매팅할 때 inspect
가 몇 번 재귀를 할 것인지를 지정한다.\n이 값은 크고 복잡한 객체를 검사할 때 유용하다. 기본값은 2
이다.\n무한으로 재귀하려면 null
를 전달해라.
colors
- true
이면 ANSI 색상코드로 스타일을 입혀서 출력한다.\n기본값은 false
이다. 색상은 커스터마이징 할 수 있는데 자세한 내용은 하단을 참고해라.
customInspect
- false
이면 검사하는 객체에 정의된 커스텀 inspect()
함수를\n호출하지 않는다. 기본값은 true
이다.
다음은 util
객체의 모든 프로퍼티를 검사하는 예제다:\n\n
var util = require('util');\n\nconsole.log(util.inspect(util, { showHidden: true, depth: null }));
\n",
"modules": [
{
"textRaw": "Customizing `util.inspect` colors",
"name": "customizing_`util.inspect`_colors",
"desc": "util.inspect
의 칼라 출력은 util.inspect.styles
와 util.inspect.colors
\n객체로 전역적으로 커스터마이징할 수 있다.\n\n
util.inspect.styles
는 util.inspect.colors
에서 각 색상 스타일을 할당하는 맵이다.\n강조된 스타일과 그 기본값은 다음과 같다.\n number
(yellow)\n boolean
(yellow)\n string
(green)\n date
(magenta)\n regexp
(red)\n null
(bold)\n undefined
(grey)\n special
- 여기서 유일한 함수 (cyan)\n * name
(의도적으로 스타일이 없다)\n\n
미리정의된 색상코드는 white
, grey
, black
, blue
, cyan
,\ngreen
, magenta
, red
, yellow
이다.\nbold
, italic
, underline
, inverse
도 있다.\n\n
객체들도 util.inspect()
가 호출해서 객체를 건사한 결과를 사용하는 자신만의\ninspect(depth)
함수를 정의할 수 있다.\n\n
var util = require('util');\n\nvar obj = { name: 'nate' };\nobj.inspect = function(depth) {\n return '{' + this.name + '}';\n};\n\nutil.inspect(obj);\n // "{nate}"
\n",
"type": "module",
"displayName": "Customizing `util.inspect` colors"
}
],
"signatures": [
{
"params": [
{
"name": "object"
},
{
"name": "options",
"optional": true
}
]
}
]
},
{
"textRaw": "util.isArray(object)",
"type": "method",
"name": "isArray",
"desc": "주어진 "object"가 Array
이면 true
를 리턴하고 Array
가 아니면 false
를\n리턴한다.\n\n
var util = require('util');\n\nutil.isArray([])\n // true\nutil.isArray(new Array)\n // true\nutil.isArray({})\n // false
\n",
"signatures": [
{
"params": [
{
"name": "object"
}
]
}
]
},
{
"textRaw": "util.isRegExp(object)",
"type": "method",
"name": "isRegExp",
"desc": "주어진 "object"가 RegExp
이면 true
를 리턴하고 RegExp
가 아니면\nfalse
를 리턴한다.\n\n
var util = require('util');\n\nutil.isRegExp(/some regexp/)\n // true\nutil.isRegExp(new RegExp('another regexp'))\n // true\nutil.isRegExp({})\n // false
\n",
"signatures": [
{
"params": [
{
"name": "object"
}
]
}
]
},
{
"textRaw": "util.isDate(object)",
"type": "method",
"name": "isDate",
"desc": "주어진 "object"가 Date
이면 true
를 리턴하고 Date
가 아니면\nfalse
를 리턴한다.\n\n
var util = require('util');\n\nutil.isDate(new Date())\n // true\nutil.isDate(Date())\n // false (without 'new' returns a String)\nutil.isDate({})\n // false
\n",
"signatures": [
{
"params": [
{
"name": "object"
}
]
}
]
},
{
"textRaw": "util.isError(object)",
"type": "method",
"name": "isError",
"desc": "주어진 "object"가 Error
이면 true
를 리턴하고 Error
가 아니면\nfalse
를 리턴한다.\n\n
var util = require('util');\n\nutil.isError(new Error())\n // true\nutil.isError(new TypeError())\n // true\nutil.isError({ name: 'Error', message: 'an error occurred' })\n // false
\n",
"signatures": [
{
"params": [
{
"name": "object"
}
]
}
]
},
{
"textRaw": "util.pump(readableStream, writableStream, [callback])",
"type": "method",
"name": "pump",
"stability": 0,
"stabilityText": "Deprecated: readableStream.pipe(writableStream)를 사용해라",
"desc": "readableStream
에서 데이터를 읽어서 읽은 데이터를 writableStream
으로 보낸다.\nwritableStream.write(data)
가 false
를 리턴하면 writableStream
에서\ndrain
이벤트가 발생할 때까지 readableStream
은 멈출 것이다. callback
은 유일한\n아규먼트로 error를 받고 writableStream
이 닫히거나 오류가 발생했을 때 호출된다.\n\n\n
한 객체의\n생성자\n에서 다른 객체로 프로토타입 메서드를 상속 받는다. constructor
의 프로토타입은\nsuperConstructor
에서 생성된 새로운 객체로 설정될 것이다.\n\n
superConstructor
는 constructor.super_
프로퍼티를\n통해서 편리하게 접근할 수 있다.\n\n
var util = require("util");\nvar events = require("events");\n\nfunction MyStream() {\n events.EventEmitter.call(this);\n}\n\nutil.inherits(MyStream, events.EventEmitter);\n\nMyStream.prototype.write = function(data) {\n this.emit("data", data);\n}\n\nvar stream = new MyStream();\n\nconsole.log(stream instanceof events.EventEmitter); // true\nconsole.log(MyStream.super_ === events.EventEmitter); // true\n\nstream.on("data", function(data) {\n console.log('Received data: "' + data + '"');\n})\nstream.write("It works!"); // Received data: "It works!"
\n",
"signatures": [
{
"params": [
{
"name": "constructor"
},
{
"name": "superConstructor"
}
]
}
]
}
],
"type": "module",
"displayName": "util"
},
{
"textRaw": "Events",
"name": "Events",
"stability": 4,
"stabilityText": "API Frozen",
"type": "module",
"desc": "노드의 많은 객체들은 이벤트를 발생시킨다. net.Server
는 서버에 연결이 생길 때마다\n이벤트를 발생시키고 fs.readStream
는 파일이 열렸을 때 이벤트를 발생시킨다.\n이벤트를 발생시키는 모든 객체들은 events.EventEmitter
의 인스턴스다.\nrequire("events");
를 사용해서 이 모듈에 접근할 수 있다.\n\n
보통 이벤트명은 카멜케이스의 문자열로 표시하지만 이벤트명에 어떤 제약사항은 없기 때문에\n어떤 문자열이라도 사용할 수 있다.\n\n
\n이벤트가 발생할 때 실행할 함수를 객체에 연결할 수 있다. 이러한 함수들을\n리스너(listener)라고 부른다. 리스너 함수 내부에서 this
는 리스너가 연결된\nEventEmitter
를 참조한다.\n\n\n
EventEmitter 클래스에 접근하려면 require('events').EventEmitter
를 사용한다.\n\n
EventEmitter
인스턴스에서 오류가 발생하면 보통 'error'
이벤트를 발생시킨다.\n노드는 오류 이벤트를 특별한 경우로 대한다. 오류 이벤트에 대한 리스너가 등록되어 있지 않은\n경우 기본 동작은 스택 트레이스를 출력하고 프로그램을 종료하는 것이다.\n\n
모든 이벤트이미터는 새로운 리스너를 추가되었을 때 'newListener'
이벤트를 발생시키고\n리스너가 제거되었을 때 'removeListener'
이벤트를 발생시킨다.\n\n
지정한 event에 대한 리스너 배열의 끝에 listener를 추가한다.\n\n
\nserver.on('connection', function (stream) {\n console.log('someone connected!');\n});
\n이미터를 반환하므로 호출을 체인으로 연결할 수 있다.\n\n
\n", "signatures": [ { "params": [ { "name": "event" }, { "name": "listener" } ] }, { "params": [ { "name": "event" }, { "name": "listener" } ] } ] }, { "textRaw": "emitter.on(event, listener)", "type": "method", "name": "on", "desc": "지정한 event에 대한 리스너 배열의 끝에 listener를 추가한다.\n\n
\nserver.on('connection', function (stream) {\n console.log('someone connected!');\n});
\n이미터를 반환하므로 호출을 체인으로 연결할 수 있다.\n\n
\n", "signatures": [ { "params": [ { "name": "event" }, { "name": "listener" } ] } ] }, { "textRaw": "emitter.once(event, listener)", "type": "method", "name": "once", "desc": "event에 일회성 listener를 추가한다. 이 리스너는\n이벤트가 다음 번에 발생했을 때 딱 한번만 실행된 후 제거된다.\n\n
\nserver.once('connection', function (stream) {\n console.log('Ah, we have our first user!');\n});
\n이미터를 반환하므로 호출을 체인으로 연결할 수 있다.\n\n
\n", "signatures": [ { "params": [ { "name": "event" }, { "name": "listener" } ] } ] }, { "textRaw": "emitter.removeListener(event, listener)", "type": "method", "name": "removeListener", "desc": "지정한 event에 대한 리스너 배열에서 listener를 제거한다.\n주의: 리스너보다 뒤쪽에서 리스너 배열의 배열인덱스를 수정해라.\n\n
\nvar callback = function(stream) {\n console.log('someone connected!');\n};\nserver.on('connection', callback);\n// ...\nserver.removeListener('connection', callback);
\n이미터를 반환하므로 호출을 체인으로 연결할 수 있다.\n\n
\n", "signatures": [ { "params": [ { "name": "event" }, { "name": "listener" } ] } ] }, { "textRaw": "emitter.removeAllListeners([event])", "type": "method", "name": "removeAllListeners", "desc": "event를 지정하지 않으면 모든 리스너를 제거하고 event를 지정하면 지정한 이벤트의\n모든 리스너를 제거한다.\n\n
\n이미터를 반환하므로 호출을 체인으로 연결할 수 있다.\n\n
\n", "signatures": [ { "params": [ { "name": "event", "optional": true } ] } ] }, { "textRaw": "emitter.setMaxListeners(n)", "type": "method", "name": "setMaxListeners", "desc": "기본적으로 EventEmitter는 특정 이벤트에 10개 이상의 리스너가 추가되면 경고메시지를\n출력할 것이다. 이 경고메시지는 메모리 누출을 찾는데 도움을 주는 유용한 기본기능이다.\n명백히 모든 이미터가 10개로 제한되어야 하는 것은 아닐 것이다. 이 함수로 이 리스너 제한을\n늘릴 수 있다. 0을 지정하면 무한대로 등록할 수 있다.\n\n\n
\n", "signatures": [ { "params": [ { "name": "n" } ] } ] }, { "textRaw": "emitter.listeners(event)", "type": "method", "name": "listeners", "desc": "지정한 이벤트의 리스너 배열을 리턴한다.\n\n
\nserver.on('connection', function (stream) {\n console.log('someone connected!');\n});\nconsole.log(util.inspect(server.listeners('connection'))); // [ [Function] ]
\n",
"signatures": [
{
"params": [
{
"name": "event"
}
]
}
]
},
{
"textRaw": "emitter.emit(event, [arg1], [arg2], [...])",
"type": "method",
"name": "emit",
"desc": "전달한 아규먼트의 순서대로 각 리스너를 실행한다.\n\n
\n이벤트가 리스너를 가지고 있으면 true
을 반환하고 가지고 있지 않으면 false
를 반환한다.\n\n
해당 이벤트의 리스터 갯수를 반환한다.\n\n\n
\n", "signatures": [ { "params": [ { "name": "emitter" }, { "name": "event" } ] } ] } ], "events": [ { "textRaw": "Event: 'newListener'", "type": "event", "name": "newListener", "params": [], "desc": "이 이벤트를 새로운 리스너가 어딘가에 추가될 때마다 발생한다.\nemitter.listeners(event)
가 반환한 리스트에 listener
있는지는 알려주지 않는다.\n\n
이 이벤트는 리스너를 제거할 때마다 발생한다.\nemitter.listeners(event)
가 반환한 리스트에 listener
있는지는 알려주지 않는다.\n\n
도메인은 하나의 그룹으로 여러 가지 다른 IO 작업을 다룰 수 있는 방법을 제공한다.\n도메인에 등록된 이벤트 이미터나 콜백 등에서 error
이벤트가 발생하거나 오류를\n던졌을 때 process.on('uncaughtException')
에서 오류의 컨텍스트를 읽어버리거나\n오류 코드로 프로그램이 즉시 종료되는 대신 도메인 객체가 이를 인지할 수 있다.\n\n
도메인 오류 핸들러는 오류 발생시 프로세스를 종료하는 것을 대체하지는 않는다.\n\n
\nJavaScript에서 throw
동작방식의 기본적인 특성으로 인해 참조를 누출하거나\nundefined같은 류의 깨지기 쉬운 상태를 생성하지 않은 채로 안전하게 "벗어난 곳이 어디인지를 찾아내는"\n방법이 거의 없다.\n\n
오류가 던져졌을 때 가장 안정한 반응은 프로세스를 종료하는 것이다. 물론 일반적인 웹서버에서\n다수의 연결을 얼어놓고 있을 것인데 어디선가 오류가 발생해서 갑자기 종료시켜버리는 것은\n합당하지는 않다.\n\n
\n더 좋은 접근방법은 오류를 발생시킨 요청에 오류 응답을 보내면서 다른 요청들은 정상적으로\n종료해고 해당 워커는 새로운 요청을 받아들이지 않도록 하는 것이다.\n\n
\n이 접근에서 워커가 오류를 만났을 때 마스터 프로세스가 새로운 워커를 만들 수 있으므로 domain
은\n클러스터 모듈과 친하다. 다중 머신으로 확장하는 node 프로그램에서 프록시나 서비스 등록을 종료하는 것은\n실패를 관리하고 적절하게 대응할 수 있다.\n\n
예를 들어 다음은 좋은 생각이 아니다.\n\n
\n// XXX WARNING! BAD IDEA!\n\nvar d = require('domain').create();\nd.on('error', function(er) {\n // This is no better than process.on('uncaughtException')!\n // 오류는 프로세스를 깨뜨리지는 않지만 오류가 하는하는 일은 더 좋지 않다!\n // 갑작스러운 프로세스의 재시작을 막더라도 이런 일이 발생하면 리소스를 노출하게 된다.\n // 이는 process.on('uncaughtException')보다 나을게 없다!\n console.log('error, but oh well', er.message);\n});\nd.run(function() {\n require('http').createServer(function(req, res) {\n handleRequest(req, res);\n }).listen(PORT);\n});
\n도메인의 컨텍스트와 프로그램을 다중 워커 프로세스로 분리하는 강력함을 사용해서\n적절하게 대응하고 훨신 더 안전하게 오류를 다룰 수 있다.\n\n
\n// 훨씬 좋다!\n\nvar cluster = require('cluster');\nvar PORT = +process.env.PORT || 1337;\n\nif (cluster.isMaster) {\n // 실환경에서는 2개 이상의 워커를 사용할 것이고 마스터와 워커를 같은 파일에\n // 두지 않을 것이다.\n //\n // 물론 DoS 공격이나 다른 공격행위를 차단하기 위해서 필요한 커스텀 로직을 구현하고\n // 로깅을 더 깔끔하게 할 수도 있다.\n //\n // 클러스터 문서의 옵션을 찾고해라.\n //\n // 중요한 점은 의도치않은 오류의 복구능력을 높히면서 마스터가 하는 일은\n // 아주 적다는 것이다.\n\n cluster.fork();\n cluster.fork();\n\n cluster.on('disconnect', function(worker) {\n console.error('disconnect!');\n cluster.fork();\n });\n\n} else {\n // 워커\n //\n // 버그를 넣을 곳이다!\n\n var domain = require('domain');\n\n // 요청을 처리하는 워커 프로세스를 사용하는 자세한 방법은 클러스터 문서를 참고해라.\n // 동작하는 방법이나 경고 등등\n\n var server = require('http').createServer(function(req, res) {\n var d = domain.create();\n d.on('error', function(er) {\n console.error('error', er.stack);\n\n // Note: 위험지역이다.\n // 당연히 원치않은 일이 일어난다.\n // 이제 어떤 일이든 발생할 수 있다! 조심해라!\n\n try {\n // 30초 내에 종료되었는지 확인한다\n var killtimer = setTimeout(function() {\n process.exit(1);\n }, 30000);\n // 하지만 이를 위해 프로세스를 열어둔 채 유지하지 말아라!\n killtimer.unref();\n\n // 새로운 요청을 받아들이는 것을 멈춘다.\n server.close();\n\n // 워커가 죽은 것을 마스터가 알도록 한다. 이는 클러스터 마스터에 'disconnect'를\n // 발생시키고 마스터가 새로운 워커를 포크할 것이다.\n cluster.worker.disconnect();\n\n // 문제을 일으킨 요청에 오류전송을 시도한다.\n res.statusCode = 500;\n res.setHeader('content-type', 'text/plain');\n res.end('Oops, there was a problem!\\n');\n } catch (er2) {\n // 여기서 할 수 있는 일은 많지 않다.\n console.error('Error sending 500!', er2.stack);\n }\n });\n\n // req와 res는 이 도메인이 존재하기 전에 생성되므로 명시적으로 req와 res를\n // 추가해야 한다. 아래의 암시적/명시적 바인딩의 설명을 참고해라.\n d.add(req);\n d.add(res);\n\n // 이제 도메인에서 핸들러 함수를 실행한다.\n d.run(function() {\n handleRequest(req, res);\n });\n });\n server.listen(PORT);\n}\n\n// 이 부분은 중요하지는 않다.그냥 라우팅 예제일 뿐이다.\n// 세련된 어플리케이션 로직을 여기에 둘 수 있다.\nfunction handleRequest(req, res) {\n switch(req.url) {\n case '/error':\n // 비동기 작업을 수행하고...\n setTimeout(function() {\n // Whoops!\n flerb.bark();\n });\n break;\n default:\n res.end('ok');\n }\n}
\n"
},
{
"textRaw": "Additions to Error objects",
"name": "Additions to Error objects",
"type": "misc",
"desc": "도데인으로 오류객체가 전달될 때 몇가지 추가적인 필드가 추가된다.\n\n
\nerror.domain
최초에 오류를 다루는 도메인.error.domainEmitter
오류 객체와 함게 'error' 이벤트를 발생시킨 이벤트 이미터.error.domainBound
도메인에 바인딩된 콜백함수로 첫 아규먼트로 오류객체를\n전달한다.error.domainThrown
오류가 던져졌는지 오류 이벤트가 발생했는지 바인딩된\n콜백함수로 전달되었는지를 나타내는 불리언 값.도메인을 사용하면 새로 생성되는 모든 EventEmitter 객체(스트림 객체, 요청, 응답등을\n포함해서)는 생성되면서 암묵적으로 활성화된 도메인에 바인딩 될 것이다.\n\n
\n게다가 저수준 이벤트 루프 요청(fs.open나 콜백을 받는 메서드같은)에 전달한 콜백은\n자동적으로 활성화된 도메인에 바인딩된다. 이 콜백이 예외를 던지면 도메인이\n이 오류를 잡아낸다.\n\n
\n과도한 메모리 사용을 막기 위해 도메인 객체 자체는 활성화된 도메인의 자식에\n암묵적으로 추가되지 않는다. 도메인 객체가 있다면 요청 객체와 응답객체가\n가비지 컬렉트되지 않도록 하는 것은 아주 쉽다.\n\n
\n부모 도메인의 자식처럼 중첩된 도메인 객체가 필요하다면 반드시 명시적으로\n추가해야 한다.\n\n
\n암묵적인 바인딩은 던져진 오류나 'error'
이벤트를 도메인의 error
이벤트로\n보내지만 도메인에 EventEmitter를 등록하지는 않기 때문에 domain.dispose()
를\n해도 EventEmitter를 종료하지 않을 것이다.\n암묵적인 바인딩은 던져진 오류나 'error'
이벤트만 처리한다.\n\n
때때로 사용중인 도메인을 특정 이벤트 이미터에서 사용하지 않아야 하는 경우가 있다.\n또는 이벤트 이미터가 한 도메인의 컨텍스트에서 생성되었지만 다른 도메인에 바인딩되어야\n하는 경우가 있다.\n\n
\n예를 들면 HTTP 서버에서 사용 중인 도메인이 있지만 각 요청마다 다른 도메인을\n사용하길 원할 수 있다.\n\n
\n이는 명시적으로 바인딩해서 할 수 있다.\n\n
\n예를 들면:\n\n
\n// 서버에 대한 최상위 도메인을 생성한다\nvar serverDomain = domain.create();\n\nserverDomain.run(function() {\n// 서버는 serverDomain의 범위내에서 생성되었다\n http.createServer(function(req, res) {\n // req와 res도 serverDomain의 범위내에서 생성되었지만\n // 요청마다 다른 도메인을 사용하길 원한다.\n // 먼저 도메인을 생성하고 req와 res를 도메인에 추가한다\n var reqd = domain.create();\n reqd.add(req);\n reqd.add(res);\n reqd.on('error', function(er) {\n console.error('Error', er, req.url);\n try {\n res.writeHead(500);\n res.end('Error occurred, sorry.');\n } catch (er) {\n console.error('Error sending 500', er, req.url);\n }\n });\n }).listen(1337);\n});
\n"
}
],
"methods": [
{
"textRaw": "domain.create()",
"type": "method",
"name": "create",
"signatures": [
{
"return": {
"textRaw": "return: {Domain} ",
"name": "return",
"type": "Domain"
},
"params": []
},
{
"params": []
}
],
"desc": "새로운 Domain 객체를 반환한다.\n\n
\n" } ], "classes": [ { "textRaw": "Class: Domain", "type": "class", "name": "Domain", "desc": "Domain 클래스는 오류와 잡지 못한 예외를 활성화된 도메인 객체로 보내는 기능을\n은닉한다.\n\n
\nDomain은 [EventEmitter][]의 자식 클래스이다. 도메인이 잡은 오류를 다루려면\n도메인의 error
이벤트에 리스너를 추가해라.\n\n
암묵적으로 모든 이벤트 이미터, 타이머, 해당 컨텍스트에서 생성된 저수준 요청을\n바인딩한 도메인의 컨텍스트에서 제공된 함수를 실행한다\n\n
\n이는 도메인을 사용하는 가장 기본적인 방법이다.\n\n
\n예제:\n\n
\nvar d = domain.create();\nd.on('error', function(er) {\n console.error('Caught error!', er);\n});\nd.run(function() {\n process.nextTick(function() {\n setTimeout(function() { // 여러 비동기의 작업들을 시뮤레이트한다\n fs.open('non-existent file', 'r', function(er, fd) {\n if (er) throw er;\n // 처리중...\n });\n }, 100);\n });\n});
\n이 예제에서 프로그램이 멈추는 대신에 d.on('error')
핸들러가 실행될 것이다.\n\n
명시적으로 이미터를 도메인에 추가한다. 이미터에서 호출된 이벤트 핸들러가 오류를\n던졌거나 이미터에서 error
이벤트가 발생했을 때 암묵적으로 바인딩한 것과 마찬가지로\n도메인의 error
이벤트로 전달된다.\n\n
이 함수는 setInterval
와 setTimeout
가 반환하는 타이머에서도 동작한다.\n타이머의 콜백함수가 예외를 던지면 도메인의 'error' 핸들러가 잡는다.\n\n
Timer나 EventEmitter가 도메인에 이미 바인딩되어 있으면 이전에 바인딩되어 있던\n도에인에서는 제거되고 이 도메인에 다시 바인딩된다.\n\n
\n" }, { "textRaw": "domain.remove(emitter)", "type": "method", "name": "remove", "signatures": [ { "params": [ { "textRaw": "`emitter` {EventEmitter | Timer} 도메인에서 제거할 이미터나 타이머 ", "name": "emitter", "type": "EventEmitter | Timer", "desc": "도메인에서 제거할 이미터나 타이머" } ] }, { "params": [ { "name": "emitter" } ] } ], "desc": "domain.add(emitter)
과는 반대로 지정한 이미터를 도메인에서 제거한다.\n\n
전달한 콜백함수를 감싸고 있는 랩퍼 함수를 반환한다. 반환된 함수를 호출했을 때\n던져지는 모든 오류는 도메인의 error
이벤트로 전달된다.\n\n
var d = domain.create();\n\nfunction readSomeFile(filename, cb) {\n fs.readFile(filename, 'utf8', d.bind(function(er, data) {\n // 여기서 오류를 던지면 도메인으로 전달된다.\n return cb(er, data ? JSON.parse(data) : null);\n }));\n}\n\nd.on('error', function(er) {\n // 어디선가 오류가 발생함.\n // 여기서 오류를 던지면 프로그램은 보통의 줄번호와\n // 스택 메시지와 함께 종료된다.\n});
\n"
},
{
"textRaw": "domain.intercept(callback)",
"type": "method",
"name": "intercept",
"signatures": [
{
"return": {
"textRaw": "return: {Function} 가로챈 함수 ",
"name": "return",
"type": "Function",
"desc": "가로챈 함수"
},
"params": [
{
"textRaw": "`callback` {Function} 콜백 함수 ",
"name": "callback",
"type": "Function",
"desc": "콜백 함수"
}
]
},
{
"params": [
{
"name": "callback"
}
]
}
],
"desc": "이 함수는 domain.bind(callback)
와 대부분 같지만 던져진 오류를 잡기 위해 함수의\n첫 아규먼트로 보낸 Error
객체를 가로챈다\n\n
이 방법을 통해 일반적인 if (er) return callback(er);
패턴을 하나의 오류\n핸들러로 바꿀 수 있다.\n\n
var d = domain.create();\n\nfunction readSomeFile(filename, cb) {\n fs.readFile(filename, 'utf8', d.intercept(function(data) {\n // 첫 아규먼트를 'Error' 라고 가정하지만 도메인이\n // 가로챘기 때문에 첫 아규먼트는 콜백에\n // 전달되지 않는다\n\n // 여기서 오류를 던지면 도메인으로 전달되기 때문에\n // 프로그램 곳곳에 반복해서 오류 핸들링 로직을 작성하는 대신에\n // 도메인의 'error' 이벤트로 오류 핸들링 로직을 옮길 수 있다\n return cb(null, JSON.parse(data));\n }));\n}\n\nd.on('error', function(er) {\n // 어디선가 오류가 발생함.\n // 여기서 오류를 던지면 프로그램은 보통의 줄번호와\n // 스택 메시지와 함께 종료된다.\n});
\n"
},
{
"textRaw": "domain.enter()",
"type": "method",
"name": "enter",
"desc": "enter
메서드는 활성화된 도메인을 설정하기 위해서 run
, bind
, intercept
메서드가\n사용하는 배관시설이라고 볼 수 있다. enter
는 domain.active
와 process.domain
를\n도메인에 설정하고 암묵적으로 도메인모듈이 관리하는 도메인 스택에 도메인을 추가한다.(도메인 스텍의\n자세한 내용은 domain.exit()
을 봐라.) enter
를 호출하면 도메인에 바인딩된 비동기 호출과\nI/O 작업 체인의 시작부분으로 경계를 설정한다.\n\n
enter
호출은 활성화된 도메인만 변경하고 도메인 자체는 바꾸지 않는다. 하나의 도메인에서\nenter
와 exit
를 여러 번 호출할 수 있다.\n\n
enter
가 호출된 도메인이 이미 폐기되었으면 enter
는 도메인을 설정하지 않고 끝날 것이다.\n\n
exit
메서드는 현재 도메인을 종료하고 도메인 스텍에서 현재 도메인을 제거한다. 비동기 호출의\n다른 체인의 컨텍스트로 바꿀 때마다 현재 도메인이 종료되었음을 보장하는 것은 중요하다. exit
\n호출은 도메인에 바인딩된 비동기 호출과 I/O 작업의 체인의 끝이나 체인을 중단하는 것으로 경계를\n설정한다.\n\n
현재 실행 컨텍스트에 여러 도메인이 중첩되어 있다면 exit
는 해당 도메인내에 중첩된 모든\n도메인을 종료할 것이다.\n\n
exit
를 호출하면 활성화된 도메인만 변경하고 도메인 자체는 변경하지 않는다. 하나의 도메인에서\nenter
와 exit
를 여러 번 호출할 수 있다.\n\n
exit
가 호출된 도메인이 이미 폐기되었으면 exit
는 도메인을 종료하지 않고 끝날 것이다.\n\n
dispose 함수는 도메인을 파괴하고 도메인과 연관된 모든 IO를 정리하려고 최선을\n다한다. 스트림은 중지되고 종료되고 닫힌 뒤 파괴된다. 타이머는 정리된다.\n명시적으로 바인딩된 콜백은 더이상 호출하지 않는다. 여기서 발생한 모든 오류 이벤트를\n무시한다.\n\n
\ndispose
호출의 의도는 보통 Domain 컨텍스트의 핵심 부분이 오류 상태라는 것을\n발견했을 때 연쇄적인 오류를 막기 위한 것이다.\n\n
도메인이 처분되었을 때 dispose
이벤트가 발생할 것이다.\n\n
IO는 여전히 수행될 것이다. 하지만 도메인이 처분되고 나면 도메인의 이미터에서 발생하는\n추가적인 오류는 무시할 것이다. 그래서 남아있는 작업이 진행중이더라도\nNode.js는 그러한 작업과 더이상 통신하지 않을 것이다.\n\n
\n", "signatures": [ { "params": [] } ] } ], "properties": [ { "textRaw": "`members` {Array} ", "name": "members", "desc": "도메인에 명시적으로 추가한 타이머와 이벤트 이미터의 배열\n\n
\n" } ] } ], "type": "module", "displayName": "Domain" }, { "textRaw": "Buffer", "name": "buffer", "stability": 3, "stabilityText": "Stable", "desc": "자바스크립트 자체는 유니코드에 친화적이지만 바이너리 데이터에는 별로 좋지 않다. TCP\n스트림이나 파일시스템을 다룰 때 옥텟(octet) 스트림을 다룰 필요가 있다. Node에는\n옥텟 스트림을 조작하고, 생성하고, 소비하는 여러 전략이 있다.\n\n
\n로우(raw) 데이터는 Buffer
클래스의 인스턴스에 저장된다. Buffer
는 정수(integer)\n배열과 비슷하지만 V8 heap 외부에 할당된 로우 메모리에 대응된다. Buffer
는 크기를\n다시 조정할 수 없다.\n\n
Buffer
클래스는 전역범위로 require('buffer')
가 필요한 경우는 매우 흔치 않다.\n\n
버퍼와 자바스크립트 문자열 객체간에 변환을 하려면 명시적인 인코딩 메서드가 필요하다.\n여러 가지 문자열 인코딩이 있다.\n\n
\n'ascii'
- 7 비트 ASCII 데이터 전용이다. 이 인코딩 메서드는 아주 빠르고 7비트가 넘는\n비트가 있는 경우 제거한다.
문자열을 버퍼로 변환하는 경우 이 인코딩은 null 문자('\\0'
나 '\\u0000'
)를\n0x20
(공백의 문자코드)로 변환한다. null 문자를 0x00
로 변환하려면 'utf8'
를\n사용해야 한다.
'utf8'
- 멀티바이트로 인코딩된 유니코드 문자다. 다수의 웹페이지와 문서 형식을\nUTF-8을 사용한다.
'utf16le'
- 2 바이트나 4바이트의 리들 엔디언(little endian)으로 인코딩된\n유니코드 문자이다. 대리쌍(surrogate pairs)을 지원한다.(U+10000 ~ U+10FFFF)
'ucs2'
- 'utf16le'
의 별칭이다.
'base64'
- Base64 문자열 인코딩.
'binary'
- 각 문자의 첫 8 비트만을 사용해서 로우(raw) 바이너리 데이터를 문자열로\n인코딩하는 방법이다. 이 인코딩 메서드는 폐기되었고 Buffer
객체가 가능한 곳에서 사용하지\n말아야 한다. 이 인코딩은 Node의 차기 버전에서는 제거될 것이다.
'hex'
- 각 바이트를 두 16진수 문자로 인코딩한다.
Buffer
객체는 타입있는 배열(typed array)과도 사용할 수 있다. 이 때 버퍼 객체는 타입있는\n배열을 지원하는 저장소로 사용하는 ArrayBuffer
로 복제(clone)된다. 버퍼의 메모리와\nArrayBuffer
는 공유되지 않는다.\n\n
NOTE: Node.js v0.8은 복제하는 대신 단순히 array.buffer
안에 버퍼에 대한 참조를 유지한다.\n\n
더 효율적이지만 타입있는 배열(typed array) 스펙과 미세하게 호환되지 않는다.\nArrayBuffer#slice()
가 slice의 복사본을 만드는 반면 Buffer#slice()
는\n뷰(view)를 생성한다.\n\n
Buffer 클래스는 바이너리 데이터를 직접 다루는 글로벌 타입니다.\n다양한 방법으로 생성할 수 있다.\n\n
\n", "classMethods": [ { "textRaw": "Class Method: Buffer.isEncoding(encoding)", "type": "classMethod", "name": "isEncoding", "signatures": [ { "params": [ { "textRaw": "`encoding` {문자열} 테스트할 인코딩 문자열 ", "name": "encoding", "type": "문자열", "desc": "테스트할 인코딩 문자열" } ] }, { "params": [ { "name": "encoding" } ] } ], "desc": "encoding
이 유효한 인코딩 인자라면 true를 반환하고 유효한 인코딩 인자가 아니면 false를\n반환한다.\n\n
obj
가 Buffer
인지 확인한다.\n\n
문자열의 실제 바이트 길이를 리턴한다. encoding
의 기본값은 'utf8'
이다.\nString.prototype.length
는 스트링에서 문자의 수를 리턴하기 때문에\nString.prototype.length
와 이 메서드는 같지 않다.\n\n
예제:\n\n
\nstr = '\\u00bd + \\u00bc = \\u00be';\n\nconsole.log(str + ": " + str.length + " characters, " +\n Buffer.byteLength(str, 'utf8') + " bytes");\n\n// ½ + ¼ = ¾: 9 characters, 12 bytes
\n"
},
{
"textRaw": "Class Method: Buffer.concat(list, [totalLength])",
"type": "classMethod",
"name": "concat",
"signatures": [
{
"params": [
{
"textRaw": "`list` {배열} 연결할 Buffer 객체의 리스트 ",
"name": "list",
"type": "배열",
"desc": "연결할 Buffer 객체의 리스트"
},
{
"textRaw": "`totalLength` {숫자} 연결된 버퍼의 전체 길이 ",
"name": "totalLength",
"type": "숫자",
"desc": "연결된 버퍼의 전체 길이",
"optional": true
}
]
},
{
"params": [
{
"name": "list"
},
{
"name": "totalLength",
"optional": true
}
]
}
],
"desc": "list의 모든 버퍼를 연결한 버퍼를 반환한다.\n\n
\nlist에 아이템이 없거나 totalLength가 0이면 길이가 0인 버퍼를 반환한다.\n\n
\nlist에 딱 하나의 아이템만 있으면 list의 첫 아이템을 반환한다.\n\n
\nlist에 하나 이상의 아이템에 있으면 새로운 Buffer가 생성된다.\n\n
\ntotalLength를 전달하지 않으면 list의 버퍼들에서 읽어들인다.\n하지만 이는 함수에 추가적인 루프가 생기므로 명시적으로 길이를 전달하는 것이\n더 빠르다.\n\n
\n" } ], "methods": [ { "textRaw": "buf.write(string, [offset], [length], [encoding])", "type": "method", "name": "write", "signatures": [ { "params": [ { "textRaw": "`string` 문자열 - 버퍼에 작성할 데이터 ", "name": "string", "desc": "문자열 - 버퍼에 작성할 데이터" }, { "textRaw": "`offset` 숫자, 선택사항, 기본값: 0 ", "name": "offset", "desc": "숫자, 선택사항, 기본값: 0", "optional": true }, { "textRaw": "`length` 숫자, 선택사항, 기본값: `buffer.length - offset` ", "name": "length", "desc": "숫자, 선택사항, 기본값: `buffer.length - offset`", "optional": true }, { "textRaw": "`encoding` 문자열, 선택사항, 기본값: 'utf8' ", "name": "encoding", "desc": "문자열, 선택사항, 기본값: 'utf8'", "optional": true } ] }, { "params": [ { "name": "string" }, { "name": "offset", "optional": true }, { "name": "length", "optional": true }, { "name": "encoding", "optional": true } ] } ], "desc": "주어진 인코딩을 사용해서 버퍼의 offset
위치에 string
을 작성한다.\noffset
의 기본값은 0
이고 encoding
의 기본값은 'utf8'
이다. length
는\n작성할 바이트의 수이다. 작성된 옥텟의 수를 반환한다. 전체 문자열을 작성하기에\nbuffer
가 충분한 공간을 가지고 있지 않다면 문자열의 일부만 작성할 것이다.\nlength
의 기본값은 buffer.length - offset
이다. 이 메서드는 문자의 일부만\n작성하지는 않는다.\n\n
buf = new Buffer(256);\nlen = buf.write('\\u00bd + \\u00bc = \\u00be', 0);\nconsole.log(len + " bytes: " + buf.toString('utf8', 0, len));
\n작성한 문자의 수(작성한 바이트의 수와는 다를 수 있다)는 Buffer._charsWritten
에\n설정되고 buf.write()
를 다음 번에 호출했을 때 덮어써질 것이다.\n\n\n
start
(기본값은 0
)부터 end
(기본값은 buffer.length
)까지 encoding
로\n인코딩된 버퍼 데이터를 디코딩해서 문자열을 리턴한다.\n\n
위의 buffer.write()
예제를 봐라.\n\n\n
Buffer 인스턴스의 JSON 표현을 반환하고 이 JSON 표현은 JSON 배열을 출력한 것과 동일하다.\nBuffer 인스턴스를 문자열화했을 때 JSON.stringify
가 암묵적으로 이 함수를 호출한다.\n\n
예제:\n\n
\nvar buf = new Buffer('test');\nvar json = JSON.stringify(buf);\n\nconsole.log(json);\n// '[116,101,115,116]'\n\nvar copy = new Buffer(JSON.parse(json));\n\nconsole.log(copy);\n// <Buffer 74 65 73 74>
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "buf.copy(targetBuffer, [targetStart], [sourceStart], [sourceEnd])",
"type": "method",
"name": "copy",
"signatures": [
{
"params": [
{
"textRaw": "`targetBuffer` Buffer 객체 - 복사할 Buffer다 ",
"name": "targetBuffer",
"desc": "Buffer 객체 - 복사할 Buffer다"
},
{
"textRaw": "`targetStart` 숫자, 선택사항, 기본값: 0 ",
"name": "targetStart",
"desc": "숫자, 선택사항, 기본값: 0",
"optional": true
},
{
"textRaw": "`sourceStart` 숫자, 선택사항, 기본값: 0 ",
"name": "sourceStart",
"desc": "숫자, 선택사항, 기본값: 0",
"optional": true
},
{
"textRaw": "`sourceEnd` 숫자, 선택사항, 기본값: `buffer.length` ",
"name": "sourceEnd",
"desc": "숫자, 선택사항, 기본값: `buffer.length`",
"optional": true
}
]
},
{
"params": [
{
"name": "targetBuffer"
},
{
"name": "targetStart",
"optional": true
},
{
"name": "sourceStart",
"optional": true
},
{
"name": "sourceEnd",
"optional": true
}
]
}
],
"desc": "버퍼들간에 복사를 한다. 소스영역과 타겟영역은 일치할 수도 있다.\ntargetStart
와 sourceStart
의 기본값은 0
이다.\nsourceEnd
의 기본값은 buffer.length
이다.\n\n
undefined
/NaN
이나 범위를 벗어난(out of bound) 값을 전달하면\n각각의 기본값을 설정한 것과 같다.\n\n
예제: 두 버퍼를 만들고 buf1
의 16 바이트부터 19 바이트까지를 buf2
의\n8번째 바이트위치에 복사한다.\n\n
buf1 = new Buffer(26);\nbuf2 = new Buffer(26);\n\nfor (var i = 0 ; i < 26 ; i++) {\n buf1[i] = i + 97; // 97 is ASCII a\n buf2[i] = 33; // ASCII !\n}\n\nbuf1.copy(buf2, 8, 16, 20);\nconsole.log(buf2.toString('ascii', 0, 25));\n\n// !!!!!!!!qrst!!!!!!!!!!!!!
\n"
},
{
"textRaw": "buf.slice([start], [end])",
"type": "method",
"name": "slice",
"signatures": [
{
"params": [
{
"textRaw": "`start` 숫자, 선택사항, 기본값: 0 ",
"name": "start",
"desc": "숫자, 선택사항, 기본값: 0",
"optional": true
},
{
"textRaw": "`end` 숫자, 선택사항, 기본값: `buffer.length` ",
"name": "end",
"desc": "숫자, 선택사항, 기본값: `buffer.length`",
"optional": true
}
]
},
{
"params": [
{
"name": "start",
"optional": true
},
{
"name": "end",
"optional": true
}
]
}
],
"desc": "기존의 버퍼가 참조하던 메모리와 같은 메모리를 참조하지만 start
(기본값은 0
)부터\nend
(기본값은 buffer.length
)의 인덱스로 잘려진 새로운 버퍼를 리턴한다.\n\n
새로운 버퍼 부분(slice)을 변경하면 기존 버퍼의 메모리를 변경할 것이다.!\n\n
\n예제: ASCII 알파벳으로 버퍼를 만들고 slice를 한 뒤 기존 버퍼의 한 바이트를\n수정한다.\n\n
\nvar buf1 = new Buffer(26);\n\nfor (var i = 0 ; i < 26 ; i++) {\n buf1[i] = i + 97; // 97 is ASCII a\n}\n\nvar buf2 = buf1.slice(0, 3);\nconsole.log(buf2.toString('ascii', 0, buf2.length));\nbuf1[0] = 33;\nconsole.log(buf2.toString('ascii', 0, buf2.length));\n\n// abc\n// !bc
\n"
},
{
"textRaw": "buf.readUInt8(offset, [noAssert])",
"type": "method",
"name": "readUInt8",
"signatures": [
{
"params": [
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
},
{
"textRaw": "반환타입: 숫자 ",
"name": "반환타입",
"desc": "숫자"
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에서 기호가 없은 8비트 정수(unsigned 8 bit integer)를\n읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\n\nbuf[0] = 0x3;\nbuf[1] = 0x4;\nbuf[2] = 0x23;\nbuf[3] = 0x42;\n\nfor (ii = 0; ii < buf.length; ii++) {\n console.log(buf.readUInt8(ii));\n}\n\n// 0x3\n// 0x4\n// 0x23\n// 0x42
\n"
},
{
"textRaw": "buf.readUInt16LE(offset, [noAssert])",
"type": "method",
"name": "readUInt16LE",
"signatures": [
{
"params": [
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
},
{
"textRaw": "반환타입: 숫자 ",
"name": "반환타입",
"desc": "숫자"
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에서 지정한 엔디언(endian) 형식으로 기호가 없는 16비트\n정수(unsigned 16 bit integer)를 읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\n\nbuf[0] = 0x3;\nbuf[1] = 0x4;\nbuf[2] = 0x23;\nbuf[3] = 0x42;\n\nconsole.log(buf.readUInt16BE(0));\nconsole.log(buf.readUInt16LE(0));\nconsole.log(buf.readUInt16BE(1));\nconsole.log(buf.readUInt16LE(1));\nconsole.log(buf.readUInt16BE(2));\nconsole.log(buf.readUInt16LE(2));\n\n// 0x0304\n// 0x0403\n// 0x0423\n// 0x2304\n// 0x2342\n// 0x4223
\n"
},
{
"textRaw": "buf.readUInt16BE(offset, [noAssert])",
"type": "method",
"name": "readUInt16BE",
"signatures": [
{
"params": [
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
},
{
"textRaw": "반환타입: 숫자 ",
"name": "반환타입",
"desc": "숫자"
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에서 지정한 엔디언(endian) 형식으로 기호가 없는 16비트\n정수(unsigned 16 bit integer)를 읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\n\nbuf[0] = 0x3;\nbuf[1] = 0x4;\nbuf[2] = 0x23;\nbuf[3] = 0x42;\n\nconsole.log(buf.readUInt16BE(0));\nconsole.log(buf.readUInt16LE(0));\nconsole.log(buf.readUInt16BE(1));\nconsole.log(buf.readUInt16LE(1));\nconsole.log(buf.readUInt16BE(2));\nconsole.log(buf.readUInt16LE(2));\n\n// 0x0304\n// 0x0403\n// 0x0423\n// 0x2304\n// 0x2342\n// 0x4223
\n"
},
{
"textRaw": "buf.readUInt32LE(offset, [noAssert])",
"type": "method",
"name": "readUInt32LE",
"signatures": [
{
"params": [
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
},
{
"textRaw": "반환타입: 숫자 ",
"name": "반환타입",
"desc": "숫자"
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에서 지정한 엔디언(endian) 형식으로 기호가 없는\n32비트 정수(unsigned 32 bit integer)를 읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\n\nbuf[0] = 0x3;\nbuf[1] = 0x4;\nbuf[2] = 0x23;\nbuf[3] = 0x42;\n\nconsole.log(buf.readUInt32BE(0));\nconsole.log(buf.readUInt32LE(0));\n\n// 0x03042342\n// 0x42230403
\n"
},
{
"textRaw": "buf.readUInt32BE(offset, [noAssert])",
"type": "method",
"name": "readUInt32BE",
"signatures": [
{
"params": [
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
},
{
"textRaw": "반환타입: 숫자 ",
"name": "반환타입",
"desc": "숫자"
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에서 지정한 엔디언(endian) 형식으로 기호가 없는\n32비트 정수(unsigned 32 bit integer)를 읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\n\nbuf[0] = 0x3;\nbuf[1] = 0x4;\nbuf[2] = 0x23;\nbuf[3] = 0x42;\n\nconsole.log(buf.readUInt32BE(0));\nconsole.log(buf.readUInt32LE(0));\n\n// 0x03042342\n// 0x42230403
\n"
},
{
"textRaw": "buf.readInt8(offset, [noAssert])",
"type": "method",
"name": "readInt8",
"signatures": [
{
"params": [
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
},
{
"textRaw": "반환타입: 숫자 ",
"name": "반환타입",
"desc": "숫자"
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼에서 지정한 offset에서 기호가 있는 8비트 정수(signed 8 bit integer)를\n읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
buffer.readUInt8
와 같이 동작하지만 버퍼의 내용을 2가지 완전한 기호가 있는 값으로\n다룬다는 점이 다르다.\n\n
버퍼에서 지정한 offset에서 기호가 있는 16비트 정수(signed 16 bit integer)를\n읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
buffer.readUInt16*
와 같이 동작하지만 버퍼의 내용을 2가지 완전한 기호가 있는 값으로\n다룬다는 점이 다르다.\n\n
버퍼에서 지정한 offset에서 기호가 있는 16비트 정수(signed 16 bit integer)를\n읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
buffer.readUInt16*
와 같이 동작하지만 버퍼의 내용을 2가지 완전한 기호가 있는 값으로\n다룬다는 점이 다르다.\n\n
버퍼에서 지정한 offset에서 기호가 있는 32비트 정수(signed 32 bit integer)를\n읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
buffer.readUInt32*
와 같이 동작하지만 버퍼의 내용을 2가지 완전한 기호가 있는 값으로\n다룬다는 점이 다르다.\n\n
버퍼에서 지정한 offset에서 기호가 있는 32비트 정수(signed 32 bit integer)를\n읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
buffer.readUInt32*
와 같이 동작하지만 버퍼의 내용을 2가지 완전한 기호가 있는 값으로\n다룬다는 점이 다르다.\n\n
버퍼의 지정한 offset에서 지정한 엔디언(endian) 형식으로 32비트 소수(32 bit float)를\n읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\n\nbuf[0] = 0x00;\nbuf[1] = 0x00;\nbuf[2] = 0x80;\nbuf[3] = 0x3f;\n\nconsole.log(buf.readFloatLE(0));\n\n// 0x01
\n"
},
{
"textRaw": "buf.readFloatBE(offset, [noAssert])",
"type": "method",
"name": "readFloatBE",
"signatures": [
{
"params": [
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
},
{
"textRaw": "반환타입: 숫자 ",
"name": "반환타입",
"desc": "숫자"
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에서 지정한 엔디언(endian) 형식으로 32비트 소수(32 bit float)를\n읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\n\nbuf[0] = 0x00;\nbuf[1] = 0x00;\nbuf[2] = 0x80;\nbuf[3] = 0x3f;\n\nconsole.log(buf.readFloatLE(0));\n\n// 0x01
\n"
},
{
"textRaw": "buf.readDoubleLE(offset, [noAssert])",
"type": "method",
"name": "readDoubleLE",
"signatures": [
{
"params": [
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
},
{
"textRaw": "반환타입: 숫자 ",
"name": "반환타입",
"desc": "숫자"
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에서 지정한 엔디언(endian) 형식으로 64 bit double을\n읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(8);\n\nbuf[0] = 0x55;\nbuf[1] = 0x55;\nbuf[2] = 0x55;\nbuf[3] = 0x55;\nbuf[4] = 0x55;\nbuf[5] = 0x55;\nbuf[6] = 0xd5;\nbuf[7] = 0x3f;\n\nconsole.log(buf.readDoubleLE(0));\n\n// 0.3333333333333333
\n"
},
{
"textRaw": "buf.readDoubleBE(offset, [noAssert])",
"type": "method",
"name": "readDoubleBE",
"signatures": [
{
"params": [
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
},
{
"textRaw": "반환타입: 숫자 ",
"name": "반환타입",
"desc": "숫자"
}
]
},
{
"params": [
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에서 지정한 엔디언(endian) 형식으로 64 bit double을\n읽는다.\n\n
\noffset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은 offset
이\n버퍼의 끝을 넘어갈 수도 있다는 의미다. 기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(8);\n\nbuf[0] = 0x55;\nbuf[1] = 0x55;\nbuf[2] = 0x55;\nbuf[3] = 0x55;\nbuf[4] = 0x55;\nbuf[5] = 0x55;\nbuf[6] = 0xd5;\nbuf[7] = 0x3f;\n\nconsole.log(buf.readDoubleLE(0));\n\n// 0.3333333333333333
\n"
},
{
"textRaw": "buf.writeUInt8(value, offset, [noAssert])",
"type": "method",
"name": "writeUInt8",
"signatures": [
{
"params": [
{
"textRaw": "`value` 숫자 ",
"name": "value",
"desc": "숫자"
},
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버터의 지정한 offset에 value
를 작성한다. value
는 반드시 유효한 기호가 없은 8비트\n정수여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\nbuf.writeUInt8(0x3, 0);\nbuf.writeUInt8(0x4, 1);\nbuf.writeUInt8(0x23, 2);\nbuf.writeUInt8(0x42, 3);\n\nconsole.log(buf);\n\n// <Buffer 03 04 23 42>
\n"
},
{
"textRaw": "buf.writeUInt16LE(value, offset, [noAssert])",
"type": "method",
"name": "writeUInt16LE",
"signatures": [
{
"params": [
{
"textRaw": "`value` 숫자 ",
"name": "value",
"desc": "숫자"
},
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
을 작성한다.\nvalue
는 반드시 유효한 기호가 없는 16비트 정수여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\nbuf.writeUInt16BE(0xdead, 0);\nbuf.writeUInt16BE(0xbeef, 2);\n\nconsole.log(buf);\n\nbuf.writeUInt16LE(0xdead, 0);\nbuf.writeUInt16LE(0xbeef, 2);\n\nconsole.log(buf);\n\n// <Buffer de ad be ef>\n// <Buffer ad de ef be>
\n"
},
{
"textRaw": "buf.writeUInt16BE(value, offset, [noAssert])",
"type": "method",
"name": "writeUInt16BE",
"signatures": [
{
"params": [
{
"textRaw": "`value` 숫자 ",
"name": "value",
"desc": "숫자"
},
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
을 작성한다.\nvalue
는 반드시 유효한 기호가 없는 16비트 정수여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\nbuf.writeUInt16BE(0xdead, 0);\nbuf.writeUInt16BE(0xbeef, 2);\n\nconsole.log(buf);\n\nbuf.writeUInt16LE(0xdead, 0);\nbuf.writeUInt16LE(0xbeef, 2);\n\nconsole.log(buf);\n\n// <Buffer de ad be ef>\n// <Buffer ad de ef be>
\n"
},
{
"textRaw": "buf.writeUInt32LE(value, offset, [noAssert])",
"type": "method",
"name": "writeUInt32LE",
"signatures": [
{
"params": [
{
"textRaw": "`value` 숫자 ",
"name": "value",
"desc": "숫자"
},
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값 : false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값 : false",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
을 작성한다.\nvalue
는 반드시 유효한 기호가 없는 32비트 정수여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\nbuf.writeUInt32BE(0xfeedface, 0);\n\nconsole.log(buf);\n\nbuf.writeUInt32LE(0xfeedface, 0);\n\nconsole.log(buf);\n\n// <Buffer fe ed fa ce>\n// <Buffer ce fa ed fe>
\n"
},
{
"textRaw": "buf.writeUInt32BE(value, offset, [noAssert])",
"type": "method",
"name": "writeUInt32BE",
"signatures": [
{
"params": [
{
"textRaw": "`value` 숫자 ",
"name": "value",
"desc": "숫자"
},
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값 : false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값 : false",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
을 작성한다.\nvalue
는 반드시 유효한 기호가 없는 32비트 정수여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\nbuf.writeUInt32BE(0xfeedface, 0);\n\nconsole.log(buf);\n\nbuf.writeUInt32LE(0xfeedface, 0);\n\nconsole.log(buf);\n\n// <Buffer fe ed fa ce>\n// <Buffer ce fa ed fe>
\n"
},
{
"textRaw": "buf.writeInt8(value, offset, [noAssert])",
"type": "method",
"name": "writeInt8",
"signatures": [
{
"params": [
{
"textRaw": "`value` 숫자 ",
"name": "value",
"desc": "숫자"
},
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에 value
를 작성한다. value
는 반드시 유효하고 기호가 있는 8비트\n정수여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
buffer.writeUInt8
와 같이 동작하지만 buffer
에 값을 2가지 완전한 기호가 있는 정수로\n작성한다는 점이 다르다.\n\n
버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
를 작성한다. value
는\n반드시 유효하고 기호가 있는 16비트 정수여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
buffer.writeUInt16*
와 같이 동작하지만 buffer
에 값을 2가지 완전한 기호가 있는 정수로\n작성한다는 점이 다르다.\n\n
버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
를 작성한다. value
는\n반드시 유효하고 기호가 있는 16비트 정수여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
buffer.writeUInt16*
와 같이 동작하지만 buffer
에 값을 2가지 완전한 기호가 있는 정수로\n작성한다는 점이 다르다.\n\n
버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
를 작성한다. value
는\n반드시 유효하고 기호가 있는 32비트 정수여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
buffer.writeUInt32*
와 같이 동작하지만 buffer
에 값을 2가지 완전한 기호가 있는 정수로\n작성한다는 점이 다르다.\n\n
버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
를 작성한다. value
는\n반드시 유효하고 기호가 있는 32비트 정수여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
buffer.writeUInt32*
와 같이 동작하지만 buffer
에 값을 2가지 완전한 기호가 있는 정수로\n작성한다는 점이 다르다.\n\n
버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
를 작성한다.\nvalue
가 32비트 실수가 아니라면 동작이 지정되지 않는다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\nbuf.writeFloatBE(0xcafebabe, 0);\n\nconsole.log(buf);\n\nbuf.writeFloatLE(0xcafebabe, 0);\n\nconsole.log(buf);\n\n// <Buffer 4f 4a fe bb>\n// <Buffer bb fe 4a 4f>
\n"
},
{
"textRaw": "buf.writeFloatBE(value, offset, [noAssert])",
"type": "method",
"name": "writeFloatBE",
"signatures": [
{
"params": [
{
"textRaw": "`value` 숫자 ",
"name": "value",
"desc": "숫자"
},
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
를 작성한다.\nvalue
가 32비트 실수가 아니라면 동작이 지정되지 않는다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(4);\nbuf.writeFloatBE(0xcafebabe, 0);\n\nconsole.log(buf);\n\nbuf.writeFloatLE(0xcafebabe, 0);\n\nconsole.log(buf);\n\n// <Buffer 4f 4a fe bb>\n// <Buffer bb fe 4a 4f>
\n"
},
{
"textRaw": "buf.writeDoubleLE(value, offset, [noAssert])",
"type": "method",
"name": "writeDoubleLE",
"signatures": [
{
"params": [
{
"textRaw": "`value` 숫자 ",
"name": "value",
"desc": "숫자"
},
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
를 작성한다. value
는\n반드시 유효한 64비트 더블이여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(8);\nbuf.writeDoubleBE(0xdeadbeefcafebabe, 0);\n\nconsole.log(buf);\n\nbuf.writeDoubleLE(0xdeadbeefcafebabe, 0);\n\nconsole.log(buf);\n\n// <Buffer 43 eb d5 b7 dd f9 5f d7>\n// <Buffer d7 5f f9 dd b7 d5 eb 43>
\n"
},
{
"textRaw": "buf.writeDoubleBE(value, offset, [noAssert])",
"type": "method",
"name": "writeDoubleBE",
"signatures": [
{
"params": [
{
"textRaw": "`value` 숫자 ",
"name": "value",
"desc": "숫자"
},
{
"textRaw": "`offset` 숫자 ",
"name": "offset",
"desc": "숫자"
},
{
"textRaw": "`noAssert` 불리언, 선택사항, 기본값: false ",
"name": "noAssert",
"desc": "불리언, 선택사항, 기본값: false",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset"
},
{
"name": "noAssert",
"optional": true
}
]
}
],
"desc": "버퍼의 지정한 offset에 지정한 엔디언(endian) 형식으로 value
를 작성한다. value
는\n반드시 유효한 64비트 더블이여야 한다.\n\n
value
와 offset
의 유효성 검사를 건너뛰려면 noAssert
을 true로 설정한다. 이 말은\n지정한 함수에 value
가 너무 크거나 offset
이 버퍼의 끝을 넘어가서 값들이 어떤 경고없이\n버려질 수 있다는 것을 의미한다. 확실히 정확함을 유지할 수 없다면 사용하지 말아야 한다.\n기본값은 false
다.\n\n
예제:\n\n
\nvar buf = new Buffer(8);\nbuf.writeDoubleBE(0xdeadbeefcafebabe, 0);\n\nconsole.log(buf);\n\nbuf.writeDoubleLE(0xdeadbeefcafebabe, 0);\n\nconsole.log(buf);\n\n// <Buffer 43 eb d5 b7 dd f9 5f d7>\n// <Buffer d7 5f f9 dd b7 d5 eb 43>
\n"
},
{
"textRaw": "buf.fill(value, [offset], [end])",
"type": "method",
"name": "fill",
"signatures": [
{
"params": [
{
"textRaw": "`value` ",
"name": "value"
},
{
"textRaw": "`offset` 숫자, 선택사항 ",
"name": "offset",
"desc": "숫자, 선택사항",
"optional": true
},
{
"textRaw": "`end` 숫자, 선택사항 ",
"name": "end",
"desc": "숫자, 선택사항",
"optional": true
}
]
},
{
"params": [
{
"name": "value"
},
{
"name": "offset",
"optional": true
},
{
"name": "end",
"optional": true
}
]
}
],
"desc": "버퍼를 지정한 값으로 채운다. offset
(기본값은 0
)과 end
(기본값은 buffer.length
)를\n전달하지 않으면 전체 버퍼를 채울 것이다.\n\n
var b = new Buffer(50);\nb.fill("h");
\n"
}
],
"properties": [
{
"textRaw": "buf[index]",
"name": "[index]",
"desc": "index
위치의 옥텟을 가져오거나 설정한다. 이 값들은 개별적인 바이트를 참조하므로\n0x00
부터 0xFF
의 16진수나 0
부터 255
사이의 적법한 범위이다.\n\n
예제: ASCII 문자열을 한번에 한 바이트씩 버퍼로 복사한다.\n\n
\nstr = "node.js";\nbuf = new Buffer(str.length);\n\nfor (var i = 0; i < str.length ; i++) {\n buf[i] = str.charCodeAt(i);\n}\n\nconsole.log(buf);\n\n// node.js
\n"
},
{
"textRaw": "`length` 숫자 ",
"name": "length",
"desc": "바이트로 나타낸 버퍼 크기. 이는 반드시 내용의 크기인 것은 아니다.\nlength
는 버퍼 객체가 할당된 메모리의 양을 참조한다.\n버퍼의 내용이 변경되었을 때도 변경되지 않는다.\n\n
buf = new Buffer(1234);\n\nconsole.log(buf.length);\nbuf.write("some string", 0, "ascii");\nconsole.log(buf.length);\n\n// 1234\n// 1234
\n",
"shortDesc": "숫자"
}
],
"signatures": [
{
"params": [
{
"textRaw": "`size` 숫자 ",
"name": "size",
"desc": "숫자"
}
],
"desc": "size
옥텟의 새로운 버퍼를 할당한다.\n\n
size
옥텟의 새로운 버퍼를 할당한다.\n\n
옥텟의 array
를 사용해서 새로운 버퍼를 할당한다.\n\n
옥텟의 array
를 사용해서 새로운 버퍼를 할당한다.\n\n
주어진 str
를 담고있는 새로운 버퍼를 할당한다.\nencoding
의 기본값은 'utf8'
이다.\n\n
주어진 str
를 담고있는 새로운 버퍼를 할당한다.\nencoding
의 기본값은 'utf8'
이다.\n\n
이 클래스는 주로 내부에서 사용한다. 자바스크립트 프로그램은 SlowBuffer 대신\nBuffer를 사용해야 한다.\n\n
\n서버가 운영되는 동안 메모리의 작은 블럭에 많은 C++ Buffer 객체들을 할당하는 오버헤드를\n피하려고 Node는 8Kb (8192 byte) 청크에 메모리를 할당한다. 버퍼가 이 크기보다 작으면\n부모 SlowBuffer 객체에가 보완할 것이다. 버퍼가 이 크기보다 크면 Node는 직접적으로\n버퍼에 SlowBuffer slab을 할당할 것이다.\n\n
\n" } ], "properties": [ { "textRaw": "`INSPECT_MAX_BYTES` 숫자, 기본값: 50 ", "name": "INSPECT_MAX_BYTES", "desc": "buffer.inspect()
가 호출되었을 때 얼마나 많은 바이트가 반환될 것인가를 지정한다.\n이 값은 사용자 모듈에서 오버라이드할 수 있다.\n\n
이 값은 Buffer 전역객체가 아니라 require('buffer')
에서 반환되는 버퍼모듈이나\n버퍼 인스턴스의 프로퍼티이다.\n\n
스트림은 Node에서 여러 가지 객체로 구현되는 추상 인터페이스다. 예를 들어 HTTP 서버에 대한\n요청은 [stdout][]과 같은 스트림이다.\n스트림은 읽을수 있거나 쓸 수 있고 때로는 둘 다 가능하다.\n모든 스트림은 [EventEmitter][]의 인스턴스다.\n\n
\nrequire('stream')
을 사용해서 기반 Stream 클래스를 로드할 수 있다.\n[Readable][] 스트림, [Writable][] 스트림, [Duplex][] 스트림, [Transform][]\n스트림을 위한 기반 클래스들이 존재한다.\n\n
이 문서는 세 부분으로 나뉜다. 첫번째 부분은 프로그램에서 스트림을 사용하려면 알아야 하는\nAPI를 설명한다. 스트리밍 API를 직접 구현하지 않는다면 이 부분을 건너띌 수 있다.\n\n
\n두번째 부분은 커스텀 스트림을 구현한다면 사용해야 하는 API을 설명한다.\nAPI는 커스텀 스트림을 쉽게 만들 수 있도록 설계되었다.\n\n
\n세번째 부분은 스트림이 어떻게 동작하는지 자세히 살펴보고 여기서 내부 메카니즘과\n수정하는 부분을 확실히 알지 못한다면 수정하지 않아야 하는 함수를 설명한다.\n\n\n
\n", "classes": [ { "textRaw": "Class: stream.Readable", "type": "class", "name": "stream.Readable", "desc": "Readable 스트림 인터페이스는 데이터를 읽어 오는 소스에 대한 추상화이다. 다시 말하면\nReadable 스트림에서 데이터가 온다.\n\n
\nReadable 스트림은 데이터를 받을 준비가 되었다고 알려줄 때까지 데이터를 보내지 않는다.\n\n
\nReadable 스트림에는 flowing 모드와 non-flowing 모드 두 가지 "모드"가 있다.\nflowing mode에서는 기반시스템에서 데이터를 읽어와서 가능한한 빨리 프로그램에 제공한다.\nnon-flowing 모드에서 데이터 청크를 받으려면 stream.read()
를 명시적으로 호출해야 한다.\n\n
readable 스트림의 예제에는 다음이 포함되어 있다.\n\n
\n스트림에서 데이터의 청크를 읽을 수 있을 때 'readable'
이벤트를 발생시킬 것이다.\n\n
몇몇 경우에서는 'readable'
이벤트를 처리할 때 데이터가 기존에 없다면 데이터를\n의존 시스템에서 내부 퍼버로 읽도록 할 것이다.\n\n
var readable = getReadableStreamSomehow();\nreadable.on('readable', function() {\n // 이제 읽을 데이터가 있다.\n})
\n내부 버퍼가 비워지면 추가적인 데이터가 있을 때 readable
이벤트를 다시 발생시킨다.\n\n
data
이벤트 리스너를 추가하면 스트림이 flowing 모드로 바뀌고 데이터를 사용할 수 있게\n되면 바로 핸들러로 전달할 것이다.\n\n
가능한한 빨리 스트림에서 데이터를 모두 받으려면 다음과 같이 하는 것이 가장 좋은 방법이다.\n\n
\nvar readable = getReadableStreamSomehow();\nreadable.on('data', function(chunk) {\n console.log('got %d bytes of data', chunk.length);\n})
\n"
},
{
"textRaw": "Event: 'end'",
"type": "event",
"name": "end",
"desc": "더 이상 데이터가 없으면 이 이벤트가 발생한다.\n\n
\n데이터를 완전히 소비하지 않는 한 end
이벤트는 발생하지 않는다. 이는 flowing\n모드로 바꾸거나 끝까지 반복해서 read()
를 호출해서 데이터를 모두 소비할 수 있다.\n\n
var readable = getReadableStreamSomehow();\nreadable.on('data', function(chunk) {\n console.log('got %d bytes of data', chunk.length);\n})\nreadable.on('end', function() {\n console.log('there will be no more data.');\n});
\n",
"params": []
},
{
"textRaw": "Event: 'close'",
"type": "event",
"name": "close",
"desc": "의존 리소스(예를 들어 기반(backing) 파일 디스크립터)가 닫혔을 때 발생한다. 모든 스크림은\n이 이벤트를 발생할 것이다.\n\n
\n", "params": [] }, { "textRaw": "Event: 'error'", "type": "event", "name": "error", "desc": "데이터를 받을 때 오류가 있으면 발생한다.\n\n
\n", "params": [] } ], "methods": [ { "textRaw": "readable.read([size])", "type": "method", "name": "read", "signatures": [ { "return": { "textRaw": "Return {String | Buffer | null} ", "name": "return", "type": "String | Buffer | null" }, "params": [ { "textRaw": "`size` {Number} 읽을 데이터의 양을 지정하기 위한 선택적인 인자. ", "name": "size", "type": "Number", "desc": "읽을 데이터의 양을 지정하기 위한 선택적인 인자.", "optional": true } ] }, { "params": [ { "name": "size", "optional": true } ] } ], "desc": "read()
메서드는 내부 버퍼에서 데이터를 가져와서 반환한다. 데이터가 없다면\nnull
을 반환할 것이다.\n\n
size
인자를 전달하면 size
만큼의 바이트를 반환할 것이다.\nsize
만큼의 데이터가 없다면 null
을 반환할 것이다.\n\n
size
인자를 지정하지 않으면 내부 버퍼의 데이터 모두를 반환할 것이다.\n\n
이 메서드는 non-flowing 모드에서만 호출해야 한다. flowing 모드에서\n이 메서드는 내부 버퍼가 비워질 때까지 자동으로 호출된다.\n\n
\nvar readable = getReadableStreamSomehow();\nreadable.on('readable', function() {\n var chunk;\n while (null !== (chunk = readable.read())) {\n console.log('got %d bytes of data', chunk.length);\n }\n});
\n"
},
{
"textRaw": "readable.setEncoding(encoding)",
"type": "method",
"name": "setEncoding",
"signatures": [
{
"params": [
{
"textRaw": "`encoding` {String} 사용할 인코딩. ",
"name": "encoding",
"type": "String",
"desc": "사용할 인코딩."
}
]
},
{
"params": [
{
"name": "encoding"
}
]
}
],
"desc": "이 함수를 호출하면 스트림이 Buffer 객체 대신 지정한 인코딩의 문자열을 반환하도록 한다.\n예를 들어, readable.setEncoding('utf8')
를 실행하면 출력데이터를 UTF-8로\n인터프리팅해서 문자열을 반환한다. readable.setEncoding('hex')
를 실행하면\n데이터를 16진수 문자열 형식으로 인코딩할 것이다.\n\n
이 함수는 버퍼를 가져와서 그냥 buf.toString(encoding)
를 실행하는 경우 엉망이\n될 가능성이 있는 멀티바이트 문자를 잘 다룬다. 문자열로 데이터를 읽으려면 이 메서드를\n항상 사용해라.\n\n
var readable = getReadableStreamSomehow();\nreadable.setEncoding('utf8');\nreadable.on('data', function(chunk) {\n assert.equal(typeof chunk, 'string');\n console.log('got %d characters of string data', chunk.length);\n})
\n"
},
{
"textRaw": "readable.resume()",
"type": "method",
"name": "resume",
"desc": "이 메서드는 readable 스트림이 다시 data
이벤트를 발생키실 수 있게 한다.\n\n
이 메서드는 스트림을 flowing-mode로 바꿀 것이다. 스트림에서 데이터를 소비하기를\n원치 않지만 end
이벤트는 받기를 원한다면 데이터의 흐름(flow)를 여는\nreadable.resume()
를 호출할 수 있다.\n\n
var readable = getReadableStreamSomehow();\nreadable.resume();\nreadable.on('end', function(chunk) {\n console.log('got to the end, but did not read anything');\n})
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "readable.pause()",
"type": "method",
"name": "pause",
"desc": "이 메서드는 flowing-mode의 스트림이 data
이벤트 발생을 멈추도록 할 것이다.\n사용가능한 모든 데이터는 내부 버퍼에 남아있을 것이다.\n\n
이 메서드는 flowing mode에서만 유효한 메서드이다. non-flowing 스트림에서\n호출한 경우 flowing mode로 바꾸고 멈춘 채로 유지할 것이다.\n\n
\nvar readable = getReadableStreamSomehow();\nreadable.on('data', function(chunk) {\n console.log('got %d bytes of data', chunk.length);\n readable.pause();\n console.log('there will be no more data for 1 second');\n setTimeout(function() {\n console.log('now data will start flowing again');\n readable.resume();\n }, 1000);\n})
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "readable.pipe(destination, [options])",
"type": "method",
"name": "pipe",
"signatures": [
{
"params": [
{
"textRaw": "`destination` {[Writable][] Stream} 데이터를 쓰는 목적지 ",
"name": "destination",
"type": "[Writable][] Stream",
"desc": "데이터를 쓰는 목적지"
},
{
"textRaw": "`options` {Object} Pipe 옵션 ",
"options": [
{
"textRaw": "`end` {Boolean} reader가 종료되면 writer도 종료한다. 기본값은 `true`이다. ",
"name": "end",
"type": "Boolean",
"desc": "reader가 종료되면 writer도 종료한다. 기본값은 `true`이다."
}
],
"name": "options",
"type": "Object",
"desc": "Pipe 옵션",
"optional": true
}
]
},
{
"params": [
{
"name": "destination"
},
{
"name": "options",
"optional": true
}
]
}
],
"desc": "이 메서드는 readable 스트림에서 오는 데이터를 모두 가져오고 제공된 목적지에 데이터를\n작성하고 빠른 readable 스트림이 목적지를 장악하지 않도록 흐름을 자동으로 관리한다.\n\n
\n안전을 위해서 여러 목적지를 파이프로 연결할 수 있다.\n\n
\nvar readable = getReadableStreamSomehow();\nvar writable = fs.createWriteStream('file.txt');\n// readable에서 오는 모든 데이터는 'file.txt'로 간다\nreadable.pipe(writable);
\n이 함수는 목적지 스트림을 반환하므로 다음과 같이 파이프 체인을 설정할 수 있다.\n\n
\nvar r = fs.createReadStream('file.txt');\nvar z = zlib.createGzip();\nvar w = fs.createWriteStream('file.txt.gz');\nr.pipe(z).pipe(w);
\n예를 들면 다음과 같이 Unix cat
명령어를 에뮬레이팅할 수 있다.\n\n
process.stdin.pipe(process.stdout);
\n기본적으로 소스 스트림이 end
를 발생시켰을 때 목적지에서 [end()
][]가 호출되므로\ndestination
는 더이상 writable이 아니다. 목적지 스트림을 열어둔 채로 두려면\noptions
으로 { end: false }
를 전달해라.\n\n
이 코드는 마지막에 "Goodbye"를 쓸 수 있게 writer
를 열어둔 채로 둔다.\n\n
reader.pipe(writer, { end: false });\nreader.on('end', function() {\n writer.end('Goodbye\\n');\n});
\nprocess.stderr
와 process.stdout
는 옵션에 상관없이 프로세스가 종료되기\n전에는 절대 닫히지 않는다.\n\n
이 메서드는 이전에 호출한 pipe()
를 설정하는 훅을 제거할 것이다.\n\n
목적지를 지정하지 않으면 모든 파이프를 제거한다.\n\n
\n목적지를 지정했지만 목적지에 파이프가 설정되어 있지 않으면 아무런 동작도 일어나지 않는다.\n\n
\nvar readable = getReadableStreamSomehow();\nvar writable = fs.createWriteStream('file.txt');\n// readable에서 오는 모든 데이터를 딱 1초동안만\n// 'file.txt'로 보낸다.\nreadable.pipe(writable);\nsetTimeout(function() {\n console.log('stop writing to file.txt');\n readable.unpipe(writable);\n console.log('manually close the file stream');\n writable.end();\n}, 1000);
\n"
},
{
"textRaw": "readable.unshift(chunk)",
"type": "method",
"name": "unshift",
"signatures": [
{
"params": [
{
"textRaw": "`chunk` {Buffer | String} 읽기 큐에서 언쉬프트할 데이터의 청크 ",
"name": "chunk",
"type": "Buffer | String",
"desc": "읽기 큐에서 언쉬프트할 데이터의 청크"
}
]
},
{
"params": [
{
"name": "chunk"
}
]
}
],
"desc": "이 함수는 소스에서 데이터를 가져와서 일부 데이터는 "소비하지 않아야" 하고 스트림을 다른\n어딘가로 전달할 수 있는 파서가 스트림을 사용하는 등의 특수한 경우에 유용하다.\n\n
\n프로그램에서 stream.unshift(chunk)
를 호출해야만 한다면 [Transform][] 스트림을\n구현하는 걸 고려해 봐라. (아래 API for Stream Implementors 참고.)\n\n
// \\n\\n를 경계로 헤더를 분리한다.\n// 너무 많이 받았다면 unshift()를 사용해라.\n// (error, header, stream)로 callback을 호출한다.\nvar StringDecoder = require('string_decoder').StringDecoder;\nfunction parseHeader(stream, callback) {\n stream.on('error', callback);\n stream.on('readable', onReadable);\n var decoder = new StringDecoder('utf8');\n var header = '';\n function onReadable() {\n var chunk;\n while (null !== (chunk = stream.read())) {\n var str = decoder.write(chunk);\n if (str.match(/\\n\\n/)) {\n // 헤더 경계를 찾았다\n var split = str.split(/\\n\\n/);\n header += split.shift();\n var remaining = split.join('\\n\\n');\n var buf = new Buffer(remaining, 'utf8');\n if (buf.length)\n stream.unshift(buf);\n stream.removeListener('error', callback);\n stream.removeListener('readable', onReadable);\n // 이제 메시지의 바디를 스트림에서 읽을 수 있다.\n callback(null, header, stream);\n } else {\n // 아직 헤더를 읽는 중이다\n header += str;\n }\n }\n }\n}
\n"
},
{
"textRaw": "readable.wrap(stream)",
"type": "method",
"name": "wrap",
"signatures": [
{
"params": [
{
"textRaw": "`stream` {Stream} \"예전 방식의\" readable 스트림 ",
"name": "stream",
"type": "Stream",
"desc": "\"예전 방식의\" readable 스트림"
}
]
},
{
"params": [
{
"name": "stream"
}
]
}
],
"desc": "Node v0.10 이전 버전의 스트림은 지금의 스트림 API 전체를 구현하지 않았다. 자세한 내용은\n아래 "Compatibility"를 참고해라.)\n\n
\n'data'
이벤트를 발생시키고 경고(advisory) 전용인 pause()
메서드를 가지는\n과거 버전의 Node 라이브러리를 사용하고 있다면 데이터 소스로 과거의 스트림을 사용하는\n[Readable][] 스크림을 생성하기 위해 wrap()
메서드를 사용할 수 있다.\n\n
이 함수를 호출해야 하는 경우는 극히 드물 것이지만 오래된 Node 프로그램과 라이브러리와 상호작용이\n\n
\n예를 들면 다음과 같다.\n\n
\nvar OldReader = require('./old-api-module.js').OldReader;\nvar oreader = new OldReader;\nvar Readable = require('stream').Readable;\nvar myReader = new Readable().wrap(oreader);\n\nmyReader.on('readable', function() {\n myReader.read(); // etc.\n});
\n"
}
]
},
{
"textRaw": "Class: stream.Writable",
"type": "class",
"name": "stream.Writable",
"desc": "Writable 스트림 인터페이스는 데이터를 작성할 목적지에 대한 추상화다.\n\n
\nwritable 스트림 예제는 다음을 포함하고 있다.\n\n
\n이 메서드는 기반 시스템에 데이터를 작성하고 데이터를 완전히 처리하고나면 전달받은\n콜백함수를 호출한다.\n\n
\n반환값은 바로 이어서 작성해야 하는지를 나타낸다. 데이터가 내부적으로 버퍼링되었다면 false
를\n반환할 것이고 그렇지 않으면 true
를 반환할 것이다.\n\n
이 반환값이 나타내는 경고는 엄격하다. 이 함수가 false
를 반환했더라도 계속해서 작성이 가능할\n수도 있다. 하지만 작성은 메모리에 버퍼링될 것이므로 지나치게 이렇게 하지 않는 것이 좋다.\n대신 추가적인 데이터를 작성하기 전에 drain
에빈트를 기다려라.\n\n
스트림에 작성할 데이터가 더이상 없을 때 이 함수를 호출해라. 콜백함수를 전달하면 finish
\n이벤트의 리스너로 등록된다.\n\n
[end()
][]를 호출한 뒤에 [write()
][]를 호출하면 오류가 발생할 것이다.\n\n
// 'hello, '를 작성한 뒤 'world!'로 종료한다.\nhttp.createServer(function (req, res) {\n res.write('hello, ');\n res.end('world!');\n // 더이상 데이터를 작성할 수 없다!\n});
\n"
}
],
"events": [
{
"textRaw": "Event: 'drain'",
"type": "event",
"name": "drain",
"desc": "[writable.write(chunk)
][] 호출이 false를 반환한 뒤 스트림에 추가적인 데이터를\n시작해도 될 때를 나타내기 위해서 drain
이벤트가 발생한다.\n\n
// 제공된 writable 스트림에 백만번 데이터를 작성한다.\n// 역압력(back-pressure)부분을 주의깊게 봐라.\nfunction writeOneMillionTimes(writer, data, encoding, callback) {\n var i = 1000000;\n write();\n function write() {\n var ok = true;\n do {\n i -= 1;\n if (i === 0) {\n // 마지막!\n writer.write(data, encoding, callback);\n } else {\n // 계속할 지 기다릴지 확인\n // 아직 완료되지 않았으므로 callback을 전달하지 않는다.\n ok = writer.write(data, encoding);\n }\n } while (i > 0 && ok);\n if (i > 0) {\n // 일찍 마쳐야 한다!\n // drain되면 추가적인 데이터를 작성한다\n writer.once('drain', write);\n }\n }\n}
\n",
"params": []
},
{
"textRaw": "Event: 'finish'",
"type": "event",
"name": "finish",
"desc": "[end()
][] 메서드가 호출되었을 때 모든 데이터를 의존 시스템으로 내보내고 이 이벤트가 발생한다.\n\n
var writer = getWritableStreamSomehow();\nfor (var i = 0; i < 100; i ++) {\n writer.write('hello, #' + i + '!\\n');\n}\nwriter.end('this is the end\\n');\nwrite.on('finish', function() {\n console.error('all writes are now complete.');\n});
\n",
"params": []
},
{
"textRaw": "Event: 'pipe'",
"type": "event",
"name": "pipe",
"params": [],
"desc": "이 이벤트는 readable 스트림에서 pipe()
메서드가 호출될 때마다 해당 writable 스트림을\n목적지로 설정하면서 발생한다.\n\n
var writer = getWritableStreamSomehow();\nvar reader = getReadableStreamSomehow();\nwriter.on('pipe', function(src) {\n console.error('something is piping into the writer');\n assert.equal(src, reader);\n});\nreader.pipe(writer);
\n"
},
{
"textRaw": "Event: 'unpipe'",
"type": "event",
"name": "unpipe",
"params": [],
"desc": "이 이벤트는 readable 스트림에서 [unpipe()
][] 메서드를 호출할 때마다 해당 writable\n스트림을 목적지에서 제거하면서 발생한다.\n\n
var writer = getWritableStreamSomehow();\nvar reader = getReadableStreamSomehow();\nwriter.on('unpipe', function(src) {\n console.error('something has stopped piping into the writer');\n assert.equal(src, reader);\n});\nreader.pipe(writer);\nreader.unpipe(writer);
\n"
}
]
},
{
"textRaw": "Class: stream.Duplex",
"type": "class",
"name": "stream.Duplex",
"desc": "Duplex 스트림은 [Readable][] 인터페이스와 [Writable][] 인터페이스를 모두 구현한\n스트림이다. 사용방법은 윗 부분을 봐라.\n\n
\nDuplex 스트림의 예제는 다음을 포함하고 있다.\n\n
\nTransform 스트림은 입력을 어떤 방법으로 계산해서 출력하는 [Duplex][] 스트림이다.\nTransform은 [Readable][] 인터페이스와 [Writable][] 인터페이스를 모두 구현한다.\n사용방법은 윗 부분을 봐라.\n\n
\nTransform 스트림 예제는 다음을 포함하고 있다.\n\n
\n스트림은 [Readable][], [Writable][]이 될 수 있고 둘 다([Duplex][]) 가능할 수도 있다.\n\n
\n모든 스트림은 EventEmitter지만 추가적인 커스텀 메서드들과 프로퍼티들이 있고 이는\nReadable, Writable, Duplex냐에 따라 약간씩 다르다.\n\n
\n스트림이 Readable이면서 Writable이면 아래 나와있는 모든 메서드와 이벤트를 구현한다.\n그러므로 [Duplex][]나 [Transform][]도 이 API에서 완전히 설명하고 있지만\n이 둘의 구현은 약간 다르다.\n\n
\n프로그램에서 스트림을 사용하려고 Stream 인터페이스를 구현할 필요는 없다. 프로그램에서\n스트리밍 인터페이스를 구현한다면 아래의 [API for Stream Implementors][]도\n참고해라.\n\n
\n거의 대부분의 Node 프로그램(얼마나 간단하냐에 상관없이)은 어떤 방법으로든 Stream을\n사용한다. 다음은 Node 프로그램에서 Stream을 사용하는 예제이다.\n\n
\nvar http = require('http');\n\nvar server = http.createServer(function (req, res) {\n // req는 Readable 스트림인 http.IncomingMessage 이다.\n // res는 Writable 스트림인 http.ServerResponse 이다.\n\n var body = '';\n // utf8 문자열로 데이터를 받기 원한다.\n // 인코딩을 설정하지 않으면 Buffer 객체를 받을 것이다.\n req.setEncoding('utf8');\n\n // 리스너를 추가했으면 Readable 스트림은 'data' 이벤트를 발생시킨다.\n req.on('data', function (chunk) {\n body += chunk;\n })\n\n // end 이벤트는 바디 전체를 받았다고 알려준다.\n req.on('end', function () {\n try {\n var data = JSON.parse(body);\n } catch (er) {\n // json 형식이 잘못됐다.\n res.statusCode = 400;\n return res.end('error: ' + er.message);\n }\n\n // 사용자에게 데이터를 작성해서 돌려준다.:\n res.write(typeof data);\n res.end();\n })\n})\n\nserver.listen(1337);\n\n// $ curl localhost:1337 -d '{}'\n// object\n// $ curl localhost:1337 -d '"foo"'\n// string\n// $ curl localhost:1337 -d 'not json'\n// error: Unexpected token o
\n",
"classes": [
{
"textRaw": "Class: stream.Readable",
"type": "class",
"name": "stream.Readable",
"desc": "Readable 스트림 인터페이스는 데이터를 읽어 오는 소스에 대한 추상화이다. 다시 말하면\nReadable 스트림에서 데이터가 온다.\n\n
\nReadable 스트림은 데이터를 받을 준비가 되었다고 알려줄 때까지 데이터를 보내지 않는다.\n\n
\nReadable 스트림에는 flowing 모드와 non-flowing 모드 두 가지 "모드"가 있다.\nflowing mode에서는 기반시스템에서 데이터를 읽어와서 가능한한 빨리 프로그램에 제공한다.\nnon-flowing 모드에서 데이터 청크를 받으려면 stream.read()
를 명시적으로 호출해야 한다.\n\n
readable 스트림의 예제에는 다음이 포함되어 있다.\n\n
\n스트림에서 데이터의 청크를 읽을 수 있을 때 'readable'
이벤트를 발생시킬 것이다.\n\n
몇몇 경우에서는 'readable'
이벤트를 처리할 때 데이터가 기존에 없다면 데이터를\n의존 시스템에서 내부 퍼버로 읽도록 할 것이다.\n\n
var readable = getReadableStreamSomehow();\nreadable.on('readable', function() {\n // 이제 읽을 데이터가 있다.\n})
\n내부 버퍼가 비워지면 추가적인 데이터가 있을 때 readable
이벤트를 다시 발생시킨다.\n\n
data
이벤트 리스너를 추가하면 스트림이 flowing 모드로 바뀌고 데이터를 사용할 수 있게\n되면 바로 핸들러로 전달할 것이다.\n\n
가능한한 빨리 스트림에서 데이터를 모두 받으려면 다음과 같이 하는 것이 가장 좋은 방법이다.\n\n
\nvar readable = getReadableStreamSomehow();\nreadable.on('data', function(chunk) {\n console.log('got %d bytes of data', chunk.length);\n})
\n"
},
{
"textRaw": "Event: 'end'",
"type": "event",
"name": "end",
"desc": "더 이상 데이터가 없으면 이 이벤트가 발생한다.\n\n
\n데이터를 완전히 소비하지 않는 한 end
이벤트는 발생하지 않는다. 이는 flowing\n모드로 바꾸거나 끝까지 반복해서 read()
를 호출해서 데이터를 모두 소비할 수 있다.\n\n
var readable = getReadableStreamSomehow();\nreadable.on('data', function(chunk) {\n console.log('got %d bytes of data', chunk.length);\n})\nreadable.on('end', function() {\n console.log('there will be no more data.');\n});
\n",
"params": []
},
{
"textRaw": "Event: 'close'",
"type": "event",
"name": "close",
"desc": "의존 리소스(예를 들어 기반(backing) 파일 디스크립터)가 닫혔을 때 발생한다. 모든 스크림은\n이 이벤트를 발생할 것이다.\n\n
\n", "params": [] }, { "textRaw": "Event: 'error'", "type": "event", "name": "error", "desc": "데이터를 받을 때 오류가 있으면 발생한다.\n\n
\n", "params": [] } ], "methods": [ { "textRaw": "readable.read([size])", "type": "method", "name": "read", "signatures": [ { "return": { "textRaw": "Return {String | Buffer | null} ", "name": "return", "type": "String | Buffer | null" }, "params": [ { "textRaw": "`size` {Number} 읽을 데이터의 양을 지정하기 위한 선택적인 인자. ", "name": "size", "type": "Number", "desc": "읽을 데이터의 양을 지정하기 위한 선택적인 인자.", "optional": true } ] }, { "params": [ { "name": "size", "optional": true } ] } ], "desc": "read()
메서드는 내부 버퍼에서 데이터를 가져와서 반환한다. 데이터가 없다면\nnull
을 반환할 것이다.\n\n
size
인자를 전달하면 size
만큼의 바이트를 반환할 것이다.\nsize
만큼의 데이터가 없다면 null
을 반환할 것이다.\n\n
size
인자를 지정하지 않으면 내부 버퍼의 데이터 모두를 반환할 것이다.\n\n
이 메서드는 non-flowing 모드에서만 호출해야 한다. flowing 모드에서\n이 메서드는 내부 버퍼가 비워질 때까지 자동으로 호출된다.\n\n
\nvar readable = getReadableStreamSomehow();\nreadable.on('readable', function() {\n var chunk;\n while (null !== (chunk = readable.read())) {\n console.log('got %d bytes of data', chunk.length);\n }\n});
\n"
},
{
"textRaw": "readable.setEncoding(encoding)",
"type": "method",
"name": "setEncoding",
"signatures": [
{
"params": [
{
"textRaw": "`encoding` {String} 사용할 인코딩. ",
"name": "encoding",
"type": "String",
"desc": "사용할 인코딩."
}
]
},
{
"params": [
{
"name": "encoding"
}
]
}
],
"desc": "이 함수를 호출하면 스트림이 Buffer 객체 대신 지정한 인코딩의 문자열을 반환하도록 한다.\n예를 들어, readable.setEncoding('utf8')
를 실행하면 출력데이터를 UTF-8로\n인터프리팅해서 문자열을 반환한다. readable.setEncoding('hex')
를 실행하면\n데이터를 16진수 문자열 형식으로 인코딩할 것이다.\n\n
이 함수는 버퍼를 가져와서 그냥 buf.toString(encoding)
를 실행하는 경우 엉망이\n될 가능성이 있는 멀티바이트 문자를 잘 다룬다. 문자열로 데이터를 읽으려면 이 메서드를\n항상 사용해라.\n\n
var readable = getReadableStreamSomehow();\nreadable.setEncoding('utf8');\nreadable.on('data', function(chunk) {\n assert.equal(typeof chunk, 'string');\n console.log('got %d characters of string data', chunk.length);\n})
\n"
},
{
"textRaw": "readable.resume()",
"type": "method",
"name": "resume",
"desc": "이 메서드는 readable 스트림이 다시 data
이벤트를 발생키실 수 있게 한다.\n\n
이 메서드는 스트림을 flowing-mode로 바꿀 것이다. 스트림에서 데이터를 소비하기를\n원치 않지만 end
이벤트는 받기를 원한다면 데이터의 흐름(flow)를 여는\nreadable.resume()
를 호출할 수 있다.\n\n
var readable = getReadableStreamSomehow();\nreadable.resume();\nreadable.on('end', function(chunk) {\n console.log('got to the end, but did not read anything');\n})
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "readable.pause()",
"type": "method",
"name": "pause",
"desc": "이 메서드는 flowing-mode의 스트림이 data
이벤트 발생을 멈추도록 할 것이다.\n사용가능한 모든 데이터는 내부 버퍼에 남아있을 것이다.\n\n
이 메서드는 flowing mode에서만 유효한 메서드이다. non-flowing 스트림에서\n호출한 경우 flowing mode로 바꾸고 멈춘 채로 유지할 것이다.\n\n
\nvar readable = getReadableStreamSomehow();\nreadable.on('data', function(chunk) {\n console.log('got %d bytes of data', chunk.length);\n readable.pause();\n console.log('there will be no more data for 1 second');\n setTimeout(function() {\n console.log('now data will start flowing again');\n readable.resume();\n }, 1000);\n})
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "readable.pipe(destination, [options])",
"type": "method",
"name": "pipe",
"signatures": [
{
"params": [
{
"textRaw": "`destination` {[Writable][] Stream} 데이터를 쓰는 목적지 ",
"name": "destination",
"type": "[Writable][] Stream",
"desc": "데이터를 쓰는 목적지"
},
{
"textRaw": "`options` {Object} Pipe 옵션 ",
"options": [
{
"textRaw": "`end` {Boolean} reader가 종료되면 writer도 종료한다. 기본값은 `true`이다. ",
"name": "end",
"type": "Boolean",
"desc": "reader가 종료되면 writer도 종료한다. 기본값은 `true`이다."
}
],
"name": "options",
"type": "Object",
"desc": "Pipe 옵션",
"optional": true
}
]
},
{
"params": [
{
"name": "destination"
},
{
"name": "options",
"optional": true
}
]
}
],
"desc": "이 메서드는 readable 스트림에서 오는 데이터를 모두 가져오고 제공된 목적지에 데이터를\n작성하고 빠른 readable 스트림이 목적지를 장악하지 않도록 흐름을 자동으로 관리한다.\n\n
\n안전을 위해서 여러 목적지를 파이프로 연결할 수 있다.\n\n
\nvar readable = getReadableStreamSomehow();\nvar writable = fs.createWriteStream('file.txt');\n// readable에서 오는 모든 데이터는 'file.txt'로 간다\nreadable.pipe(writable);
\n이 함수는 목적지 스트림을 반환하므로 다음과 같이 파이프 체인을 설정할 수 있다.\n\n
\nvar r = fs.createReadStream('file.txt');\nvar z = zlib.createGzip();\nvar w = fs.createWriteStream('file.txt.gz');\nr.pipe(z).pipe(w);
\n예를 들면 다음과 같이 Unix cat
명령어를 에뮬레이팅할 수 있다.\n\n
process.stdin.pipe(process.stdout);
\n기본적으로 소스 스트림이 end
를 발생시켰을 때 목적지에서 [end()
][]가 호출되므로\ndestination
는 더이상 writable이 아니다. 목적지 스트림을 열어둔 채로 두려면\noptions
으로 { end: false }
를 전달해라.\n\n
이 코드는 마지막에 "Goodbye"를 쓸 수 있게 writer
를 열어둔 채로 둔다.\n\n
reader.pipe(writer, { end: false });\nreader.on('end', function() {\n writer.end('Goodbye\\n');\n});
\nprocess.stderr
와 process.stdout
는 옵션에 상관없이 프로세스가 종료되기\n전에는 절대 닫히지 않는다.\n\n
이 메서드는 이전에 호출한 pipe()
를 설정하는 훅을 제거할 것이다.\n\n
목적지를 지정하지 않으면 모든 파이프를 제거한다.\n\n
\n목적지를 지정했지만 목적지에 파이프가 설정되어 있지 않으면 아무런 동작도 일어나지 않는다.\n\n
\nvar readable = getReadableStreamSomehow();\nvar writable = fs.createWriteStream('file.txt');\n// readable에서 오는 모든 데이터를 딱 1초동안만\n// 'file.txt'로 보낸다.\nreadable.pipe(writable);\nsetTimeout(function() {\n console.log('stop writing to file.txt');\n readable.unpipe(writable);\n console.log('manually close the file stream');\n writable.end();\n}, 1000);
\n"
},
{
"textRaw": "readable.unshift(chunk)",
"type": "method",
"name": "unshift",
"signatures": [
{
"params": [
{
"textRaw": "`chunk` {Buffer | String} 읽기 큐에서 언쉬프트할 데이터의 청크 ",
"name": "chunk",
"type": "Buffer | String",
"desc": "읽기 큐에서 언쉬프트할 데이터의 청크"
}
]
},
{
"params": [
{
"name": "chunk"
}
]
}
],
"desc": "이 함수는 소스에서 데이터를 가져와서 일부 데이터는 "소비하지 않아야" 하고 스트림을 다른\n어딘가로 전달할 수 있는 파서가 스트림을 사용하는 등의 특수한 경우에 유용하다.\n\n
\n프로그램에서 stream.unshift(chunk)
를 호출해야만 한다면 [Transform][] 스트림을\n구현하는 걸 고려해 봐라. (아래 API for Stream Implementors 참고.)\n\n
// \\n\\n를 경계로 헤더를 분리한다.\n// 너무 많이 받았다면 unshift()를 사용해라.\n// (error, header, stream)로 callback을 호출한다.\nvar StringDecoder = require('string_decoder').StringDecoder;\nfunction parseHeader(stream, callback) {\n stream.on('error', callback);\n stream.on('readable', onReadable);\n var decoder = new StringDecoder('utf8');\n var header = '';\n function onReadable() {\n var chunk;\n while (null !== (chunk = stream.read())) {\n var str = decoder.write(chunk);\n if (str.match(/\\n\\n/)) {\n // 헤더 경계를 찾았다\n var split = str.split(/\\n\\n/);\n header += split.shift();\n var remaining = split.join('\\n\\n');\n var buf = new Buffer(remaining, 'utf8');\n if (buf.length)\n stream.unshift(buf);\n stream.removeListener('error', callback);\n stream.removeListener('readable', onReadable);\n // 이제 메시지의 바디를 스트림에서 읽을 수 있다.\n callback(null, header, stream);\n } else {\n // 아직 헤더를 읽는 중이다\n header += str;\n }\n }\n }\n}
\n"
},
{
"textRaw": "readable.wrap(stream)",
"type": "method",
"name": "wrap",
"signatures": [
{
"params": [
{
"textRaw": "`stream` {Stream} \"예전 방식의\" readable 스트림 ",
"name": "stream",
"type": "Stream",
"desc": "\"예전 방식의\" readable 스트림"
}
]
},
{
"params": [
{
"name": "stream"
}
]
}
],
"desc": "Node v0.10 이전 버전의 스트림은 지금의 스트림 API 전체를 구현하지 않았다. 자세한 내용은\n아래 "Compatibility"를 참고해라.)\n\n
\n'data'
이벤트를 발생시키고 경고(advisory) 전용인 pause()
메서드를 가지는\n과거 버전의 Node 라이브러리를 사용하고 있다면 데이터 소스로 과거의 스트림을 사용하는\n[Readable][] 스크림을 생성하기 위해 wrap()
메서드를 사용할 수 있다.\n\n
이 함수를 호출해야 하는 경우는 극히 드물 것이지만 오래된 Node 프로그램과 라이브러리와 상호작용이\n\n
\n예를 들면 다음과 같다.\n\n
\nvar OldReader = require('./old-api-module.js').OldReader;\nvar oreader = new OldReader;\nvar Readable = require('stream').Readable;\nvar myReader = new Readable().wrap(oreader);\n\nmyReader.on('readable', function() {\n myReader.read(); // etc.\n});
\n"
}
]
},
{
"textRaw": "Class: stream.Writable",
"type": "class",
"name": "stream.Writable",
"desc": "Writable 스트림 인터페이스는 데이터를 작성할 목적지에 대한 추상화다.\n\n
\nwritable 스트림 예제는 다음을 포함하고 있다.\n\n
\n이 메서드는 기반 시스템에 데이터를 작성하고 데이터를 완전히 처리하고나면 전달받은\n콜백함수를 호출한다.\n\n
\n반환값은 바로 이어서 작성해야 하는지를 나타낸다. 데이터가 내부적으로 버퍼링되었다면 false
를\n반환할 것이고 그렇지 않으면 true
를 반환할 것이다.\n\n
이 반환값이 나타내는 경고는 엄격하다. 이 함수가 false
를 반환했더라도 계속해서 작성이 가능할\n수도 있다. 하지만 작성은 메모리에 버퍼링될 것이므로 지나치게 이렇게 하지 않는 것이 좋다.\n대신 추가적인 데이터를 작성하기 전에 drain
에빈트를 기다려라.\n\n
스트림에 작성할 데이터가 더이상 없을 때 이 함수를 호출해라. 콜백함수를 전달하면 finish
\n이벤트의 리스너로 등록된다.\n\n
[end()
][]를 호출한 뒤에 [write()
][]를 호출하면 오류가 발생할 것이다.\n\n
// 'hello, '를 작성한 뒤 'world!'로 종료한다.\nhttp.createServer(function (req, res) {\n res.write('hello, ');\n res.end('world!');\n // 더이상 데이터를 작성할 수 없다!\n});
\n"
}
],
"events": [
{
"textRaw": "Event: 'drain'",
"type": "event",
"name": "drain",
"desc": "[writable.write(chunk)
][] 호출이 false를 반환한 뒤 스트림에 추가적인 데이터를\n시작해도 될 때를 나타내기 위해서 drain
이벤트가 발생한다.\n\n
// 제공된 writable 스트림에 백만번 데이터를 작성한다.\n// 역압력(back-pressure)부분을 주의깊게 봐라.\nfunction writeOneMillionTimes(writer, data, encoding, callback) {\n var i = 1000000;\n write();\n function write() {\n var ok = true;\n do {\n i -= 1;\n if (i === 0) {\n // 마지막!\n writer.write(data, encoding, callback);\n } else {\n // 계속할 지 기다릴지 확인\n // 아직 완료되지 않았으므로 callback을 전달하지 않는다.\n ok = writer.write(data, encoding);\n }\n } while (i > 0 && ok);\n if (i > 0) {\n // 일찍 마쳐야 한다!\n // drain되면 추가적인 데이터를 작성한다\n writer.once('drain', write);\n }\n }\n}
\n",
"params": []
},
{
"textRaw": "Event: 'finish'",
"type": "event",
"name": "finish",
"desc": "[end()
][] 메서드가 호출되었을 때 모든 데이터를 의존 시스템으로 내보내고 이 이벤트가 발생한다.\n\n
var writer = getWritableStreamSomehow();\nfor (var i = 0; i < 100; i ++) {\n writer.write('hello, #' + i + '!\\n');\n}\nwriter.end('this is the end\\n');\nwrite.on('finish', function() {\n console.error('all writes are now complete.');\n});
\n",
"params": []
},
{
"textRaw": "Event: 'pipe'",
"type": "event",
"name": "pipe",
"params": [],
"desc": "이 이벤트는 readable 스트림에서 pipe()
메서드가 호출될 때마다 해당 writable 스트림을\n목적지로 설정하면서 발생한다.\n\n
var writer = getWritableStreamSomehow();\nvar reader = getReadableStreamSomehow();\nwriter.on('pipe', function(src) {\n console.error('something is piping into the writer');\n assert.equal(src, reader);\n});\nreader.pipe(writer);
\n"
},
{
"textRaw": "Event: 'unpipe'",
"type": "event",
"name": "unpipe",
"params": [],
"desc": "이 이벤트는 readable 스트림에서 [unpipe()
][] 메서드를 호출할 때마다 해당 writable\n스트림을 목적지에서 제거하면서 발생한다.\n\n
var writer = getWritableStreamSomehow();\nvar reader = getReadableStreamSomehow();\nwriter.on('unpipe', function(src) {\n console.error('something has stopped piping into the writer');\n assert.equal(src, reader);\n});\nreader.pipe(writer);\nreader.unpipe(writer);
\n"
}
]
},
{
"textRaw": "Class: stream.Duplex",
"type": "class",
"name": "stream.Duplex",
"desc": "Duplex 스트림은 [Readable][] 인터페이스와 [Writable][] 인터페이스를 모두 구현한\n스트림이다. 사용방법은 윗 부분을 봐라.\n\n
\nDuplex 스트림의 예제는 다음을 포함하고 있다.\n\n
\nTransform 스트림은 입력을 어떤 방법으로 계산해서 출력하는 [Duplex][] 스트림이다.\nTransform은 [Readable][] 인터페이스와 [Writable][] 인터페이스를 모두 구현한다.\n사용방법은 윗 부분을 봐라.\n\n
\nTransform 스트림 예제는 다음을 포함하고 있다.\n\n
\n어떤 종류의 스트림이든지 스트림을 구현하기 위한 패턴은 동일하다.\n\n
\nutil.inherits
][]\n메서드는 이 부분에 유용하다.)작성하는 스트림 클래스의 종류에 따라 상속받을 클래스와 구현할 메서드가 다르다.\n\n
\n\n 사용처 \n | \n \n 클래스 \n | \n \n 구현할 메서드 \n | \n
---|---|---|
\n 읽기 전용 \n | \n \n \n | \n\n
| \n
\n 쓰기 전용 \n | \n \n \n | \n\n
| \n
\n 읽기/쓰기 \n | \n \n \n | \n\n
| \n
\n 작성한 데이터를 처리 후 결과를 읽어들인다 \n | \n \n \n | \n\n
| \n
구현 코드에서는 위의 [API for Stream Consumers][]에서 설명한 메서드를 호출하지 않는\n것이 아주 중요하다. 호출한다면 스트리밍 인터페이스를 사용하는 프로그렘에서 부작용이 발생할\n잠재성을 갖게 된다.\n\n
\n", "examples": [ { "textRaw": "Class: stream.Readable", "type": "example", "name": "stream.Readable", "desc": "stream.Readable
은 [_read(size)
][] 메서드의 의존 구현체를 확장도록 설계된\n추상 클래스다.\n\n
프로그램에서 스트림을 사용하는 방법은 위의 [API for Stream Consumers][]를 참고해라.\n이어서 프로그램에서 Readable 스트림을 어떻게 구현하는지 설명한다.\n\n
\n다음은 Readable 스트림의 기본적인 예제다. 이 예제는 순차적으로 1부터\n1,000,000까지 숫자를 발생시키고 끝난다.\n\n
\nvar Readable = require('stream').Readable;\nvar util = require('util');\nutil.inherits(Counter, Readable);\n\nfunction Counter(opt) {\n Readable.call(this, opt);\n this._max = 1000000;\n this._index = 1;\n}\n\nCounter.prototype._read = function() {\n var i = this._index++;\n if (i > this._max)\n this.push(null);\n else {\n var str = '' + i;\n var buf = new Buffer(str, 'ascii');\n this.push(buf);\n }\n};
\n이는 위에서 설명한 parseHeader
함수와 비슷하지만 커스텀 스트림으로 구현되었다.\n그리고 이 구현체는 들어오는 데이터를 문자열로 변환하지 않는다.\n\n
하지만 이는 [Transform][] 스트림으로 구현하는 것이 더 좋다.\n더 좋은 구현체는 아래 부분을 참고해라.\n\n
\n// 간단한 데이터 프로토콜에 대한 파서.\n// "header"는 JSON 객체이고 이어서 두개의 \\n 문자가 오로고 이어서 메시지 바디가 온다.\n//\n// Note: 이는 Transform 스트림으로 훨씬 간단히 할 수 있다!\n// 이를 위해 Readable를 직접 사용하는 것이 차선책이다. 이에 대한 예제은 아래의\n// Transform 부분을 참고해라.\n\nvar Readable = require('stream').Readable;\nvar util = require('util');\n\nutil.inherits(SimpleProtocol, Readable);\n\nfunction SimpleProtocol(source, options) {\n if (!(this instanceof SimpleProtocol))\n return new SimpleProtocol(options);\n\n Readable.call(this, options);\n this._inBody = false;\n this._sawFirstCr = false;\n\n // 소스는 소켓이나 파일같은 readable 스트림이다\n this._source = source;\n\n var self = this;\n source.on('end', function() {\n self.push(null);\n });\n\n // 소스를 읽을 수 있을 때마다 무시한다.\n // read(0)은 바이트를 전혀 소비하지 않을 것이다\n source.on('readable', function() {\n self.read(0);\n });\n\n this._rawHeader = [];\n this.header = null;\n}\n\nSimpleProtocol.prototype._read = function(n) {\n if (!this._inBody) {\n var chunk = this._source.read();\n\n // 소스에 데이터가 없으면 아직 데이터를 갖지 않는다.\n if (chunk === null)\n return this.push('');\n\n // 청크가 \\n\\n를 가졌는지 검사한다\n var split = -1;\n for (var i = 0; i < chunk.length; i++) {\n if (chunk[i] === 10) { // '\\n'\n if (this._sawFirstCr) {\n split = i;\n break;\n } else {\n this._sawFirstCr = true;\n }\n } else {\n this._sawFirstCr = false;\n }\n }\n\n if (split === -1) {\n // 아직 \\n\\n를 기다리고 있다\n // 청크를 치워두고 다시 시도한다.\n this._rawHeader.push(chunk);\n this.push('');\n } else {\n this._inBody = true;\n var h = chunk.slice(0, split);\n this._rawHeader.push(h);\n var header = Buffer.concat(this._rawHeader).toString();\n try {\n this.header = JSON.parse(header);\n } catch (er) {\n this.emit('error', new Error('invalid simple protocol data'));\n return;\n }\n // 이제 어떤 추가적인 데이터를 가졌으므로 컨슈머가 볼 수 있도록\n // 읽기 큐에 남은 부분을 다시 unshift한다.\n var b = chunk.slice(split);\n this.unshift(b);\n\n // 그리고 헤더 파싱을 완료했다는 것을 알려준다.\n this.emit('header', this.header);\n }\n } else {\n // 여기서 단순히 컨슈머에게 데이터를 제공한다.\n // push(null)이 EOF를 의미하므로 push(null)을 사용하지 않도록 조심해라.\n var chunk = this._source.read();\n if (chunk) this.push(chunk);\n }\n};\n\n// 사용방법:\n// var parser = new SimpleProtocol(source);\n// 이제 파서는 파싱된 헤더 데이터를 가진 'header'를 발생시킬\n// readable 스트림이다.
\n",
"methods": [
{
"textRaw": "new stream.Readable([options])",
"type": "method",
"name": "Readable",
"signatures": [
{
"params": [
{
"textRaw": "`options` {Object} ",
"options": [
{
"textRaw": "`highWaterMark` {Number} 사용하는 리소스에서 읽기를 중단하기 전에 내부 버퍼에 저장할 최대 바이트 수. 기본값=16kb ",
"name": "highWaterMark",
"type": "Number",
"desc": "사용하는 리소스에서 읽기를 중단하기 전에 내부 버퍼에 저장할 최대 바이트 수. 기본값=16kb"
},
{
"textRaw": "`encoding` {String} 이 값을 지정하면 지정한 인코딩으로 버퍼를 문자열로 디코드한다. 기본값=null ",
"name": "encoding",
"type": "String",
"desc": "이 값을 지정하면 지정한 인코딩으로 버퍼를 문자열로 디코드한다. 기본값=null"
},
{
"textRaw": "`objectMode` {Boolean} 이 스트림이 객체의 스트림처럼 동작해야 하는지 여부. 즉, stream.read(n)이 n 크기의 Buffer 대신 문자열 값을 반환한다는 것을 의미한다. ",
"name": "objectMode",
"type": "Boolean",
"desc": "이 스트림이 객체의 스트림처럼 동작해야 하는지 여부. 즉, stream.read(n)이 n 크기의 Buffer 대신 문자열 값을 반환한다는 것을 의미한다."
}
],
"name": "options",
"type": "Object",
"optional": true
}
]
},
{
"params": [
{
"name": "options",
"optional": true
}
]
}
],
"desc": "Readable 클래스를 확장하는 클래스에서 버퍼링 설정을 적절하게 초기화할 수 있도록\nReadable 생성자를 꼭 호출해라.\n\n
\n" }, { "textRaw": "readable.\\_read(size)", "type": "method", "name": "\\_read", "signatures": [ { "params": [ { "textRaw": "`size` {Number} 비동기적으로 읽을 바이트 수 ", "name": "size", "type": "Number", "desc": "비동기적으로 읽을 바이트 수" } ] }, { "params": [ { "name": "size" } ] } ], "desc": "Note: 이 함수를 구현하되 직접 호출하지는 마라.\n\n
\n이 함수는 직접 호출하지 말아야 한다. 이 함수는 자식 클래스에서 구현해야 하고\nReadable 클래스 내부 함수에서만 호출해야 한다.\n\n
\n모든 Readable 스트림 구현체는 사용하는 리소스에서 데이터를 가져오는 _read
메서드를\n반드시 제공해야 한다.\n\n
이 함수는 클래스는 내부에서만 사용할 목적이므로 언더스코어 접두사가 붙어있고 사용자\n프로그램에서 직접 호출하지 않아야 한다. 하지만 자신만의 확장 클래스에서 이 메서드를\n오버라이드하기 원할 수도 있다.\n\n
\n데이터를 사용할 수 있을 때 readable.push(chunk)
를 호출해서 읽기 큐에 데이터를 넣는다.\npush
가 false를 반환하면 읽기를 멈춰야 한다. _read
가 다시 호출됐을 때 추가적인\n데이터를 큐에 넣기 시작해야 한다.\n\n
size
아규먼트는 권고사항이다. "read"는 데이터를 반환하는 하나의 호출인\n구현체에서 얼마나 많은 데이터를 가여와야 하는지 지정하는데 이 값을 사용한다. TCP나 TLS처럼\n관련이 없는 구현체는 이 인자를 무시하고 데이터를 이용할 수 있을때마다 제공할 것이다. 예를 들면\n[stream.push(chunk)
][]를 호출하기 전에 size
바이트가 사용가능할 때까지\n"기다릴" 필요가 없다.\n\n
Note: 이 함수는 Readable 구현체에서 호출해야 지 Readable 스트림를 소비하는 쪽에서\n호출하면 안된다.\n\n
\npush(chunk)
가 최소 한번 실행될 때까지는 _read()
함수는 다시 호출되지\n않을 것이다.\n\n
나중에 'readable'
이벤트가 발생했을 때 read()
메서드를 호출해서 데이터를 꺼내도록\nReadable
클래스는 읽기 큐에 데이터를 넣어서 동작한다.\n\n
push()
메서드는 데이터를 읽기 큐에 명시적으로 넣을 것이다. 이 함수를 null
로 호출하면\n데이터가 끝났다는(EOF) 신호가 올 것이다.\n\n
이 API는 최대한 유연하게 설계되었다. 예를 들어 어떤 종류의 pause/resume 메카니즘과 데이터\n콜백을 가진 저수준 소스를 감싸고 있다고 해보자. 이러한 경우 다음과 같이 해서 저수준 소스를\n감쌀 수 있다.\n\n
\n// source는 readStop(), readStart() 메서드와\n// source가 데이터를 가졌을 때 호출되는 `ondata` 멤버,\n// 데이터가 끝났을 때 호출되는 `onend` 멤버를 가진 객체이다.\n\nutil.inherits(SourceWrapper, Readable);\n\nfunction SourceWrapper(options) {\n Readable.call(this, options);\n\n this._source = getLowlevelSourceObject();\n var self = this;\n\n // 데이터가 있을 때마다 내부 버퍼에 데이터를 넣는다.\n this._source.ondata = function(chunk) {\n // push()가 false를 반환하면 source에서 읽기를 멈춰야 한다\n if (!self.push(chunk))\n self._source.readStop();\n };\n\n // source가 끝났을 때 EOF를 알리는 `null` 청크를 넣는다.\n this._source.onend = function() {\n self.push(null);\n };\n}\n\n// 이 경우에 권고사항인 size 인자를 무시하고 스트림이 추가적인 데이터를\n// 가져오도록 하고 싶을 때 _read를 호출할 것이다.\nSourceWrapper.prototype._read = function(size) {\n this._source.readStart();\n};
\n"
}
]
}
],
"classes": [
{
"textRaw": "Class: stream.Writable",
"type": "class",
"name": "stream.Writable",
"desc": "stream.Writable
는 [_write(chunk, encoding, callback)
][] 메서드의\n의존 구현체로 확장하도록 설계된 추상 클래스다.\n\n
프로그램에서 writable 스트림을 사용하는 방법은 위의 [API for Stream Consumers][]\n부분을 참고해라. 여기서는 프로그램에서 Writable 스트림을 구현하는 방법을 설명한다.\n\n
\n", "methods": [ { "textRaw": "new stream.Writable([options])", "type": "method", "name": "Writable", "signatures": [ { "params": [ { "textRaw": "`options` {Object} ", "options": [ { "textRaw": "`highWaterMark` {Number} [`write()`][]가 false를 반환하기 시작했을 때 Buffer 레벨. 기본값=16kb ", "name": "highWaterMark", "type": "Number", "desc": "[`write()`][]가 false를 반환하기 시작했을 때 Buffer 레벨. 기본값=16kb" }, { "textRaw": "`decodeStrings` {Boolean} 문자열을 [`_write()`][]에 전달하기 전에 Buffer로 디코딩할 것인지 여부. 기본값=true ", "name": "decodeStrings", "type": "Boolean", "desc": "문자열을 [`_write()`][]에 전달하기 전에 Buffer로 디코딩할 것인지 여부. 기본값=true" } ], "name": "options", "type": "Object", "optional": true } ] }, { "params": [ { "name": "options", "optional": true } ] } ], "desc": "Writable 클래스를 확장한 클래스에서는 버퍼링 설정이 적절하게 초기화될 수 있도록\n꼭 생성자를 호출해라.\n\n
\n" }, { "textRaw": "writable.\\_write(chunk, encoding, callback)", "type": "method", "name": "\\_write", "signatures": [ { "params": [ { "textRaw": "`chunk` {Buffer | String} 작성할 청크. `decodeStrings` 옵션이 `false`로 설정하지 않았다면 항상 버퍼가 될 것이다. ", "name": "chunk", "type": "Buffer | String", "desc": "작성할 청크. `decodeStrings` 옵션이 `false`로 설정하지 않았다면 항상 버퍼가 될 것이다." }, { "textRaw": "`encoding` {String} 청크가 문자열인경우 인코딩 종류. 청크가 버퍼이면 무시한다. `decodeStrings` 옵션을 명시적으로 `false`로 설정하지 않았다면 청크는 **항상** 버퍼가 될 것이다. ", "name": "encoding", "type": "String", "desc": "청크가 문자열인경우 인코딩 종류. 청크가 버퍼이면 무시한다. `decodeStrings` 옵션을 명시적으로 `false`로 설정하지 않았다면 청크는 **항상** 버퍼가 될 것이다." }, { "textRaw": "`callback` {Function} 전달된 청크를 모두 처리했을 때 이 함수(선택적으로 오류 인자와 함께)를 호출한다. ", "name": "callback", "type": "Function", "desc": "전달된 청크를 모두 처리했을 때 이 함수(선택적으로 오류 인자와 함께)를 호출한다." } ] }, { "params": [ { "name": "chunk" }, { "name": "encoding" }, { "name": "callback" } ] } ], "desc": "모든 Writable 스트림 구현체는 기반 리소스에 데이터를 전송하기 위해서\n[_write()
][] 메서드를 제공해야 한다.\n\n
Note: 이 함수는 직접 호출하지 말아야 한다. 이는 자식 클래스에서 구현되어야 하고\nWritable 클래스 내부 메서드만 호출해야 한다.\n\n
\n작성이 성공적으로 완료되었거나 오류가 발생했다는 신호로 표준 callback(error)
\n패턴을 사용해서 콜백을 호출한다.\n\n
생성자 옵션에서 decodeStrings
플래그를 설정했다면 chunk
는 버퍼가 아니라\n문자열이 되고 encoding
은 문자열의 종류를 나타내게 된다. 이는 특정 문자열 데이터\n인코딩에 대한 최적화 처리를 하는 구현체를 지원하기 위함이다. 명시적으로 decodeStrings
\n옵션을 false
로 설정하지 않았다면 encoding
인자를 무시하고 chunk
가 항상\nBuffer라고 생각할 수 있다.\n\n
이 메서드는 정의된 클래스 내부용이므로 언더스코어 접두사가 붙어있다. 그래서 사용자\n프로그램이 직접 호출하지 말아야 한다. 하지만 자신의 확장 클래스에서 이 함수를\n오버라이드하기 원할 수도 있다.\n\n\n
\n" } ] }, { "textRaw": "Class: stream.Duplex", "type": "class", "name": "stream.Duplex", "desc": ""duplex" 스트림은 TCP 소켓 연결처럼 Readable이면서 Writable인 스트림이다.\n\n
\nstream.Duplex
는 Readable 스트림 클래스나 Writable 스트림 클래스에서 했듯이\n_read(size)
와 [_write(chunk, encoding, callback)
][] 메서드의\n의존 구현체로 확장하도록 설계된 추상 클래스다.\n\n
자바스크립트가 프로토타입 다중 상속을 지원하지 않으므로 이 클래스는 Readable을\n프로토타입으로 상속받은 뒤 Writable이 기생하는 식으로 동작한다. 그러므로 확장 duplex\n클래스에서 저수준 [_write(chunk, encoding, callback)
][] 메서드와\n저수준 _read(n)
를 사용자가 모두 구현했는가에 달려있다.\n\n
Duplex 클래스를 확장한 클래스에서는 버퍼링 설정을 적절히 초기화할 수 있도록\n생성자를 꼭 호출해야 한다.\n\n\n
\n" } ] }, { "textRaw": "Class: stream.Transform", "type": "class", "name": "stream.Transform", "desc": ""transform" 스트림은 [zlib][] 스트림이나 [crypto][] 스트림처럼 출력이\n어떤 식으로든 입력에 연결되는 duplex 스트림이다.\n\n
\n출력이 입력과 같은 크기이거나 청크의 수가 같거나 동시에 도착해야 한다는 등의 요구사항은 없다.\n예를 들면 Hash 스트림은 입력이 종료되었을 때 제공된 출력의 단일 청크만을 가질 것이다.\nzlib 스트림은 입력코다 아주 작거나 아주 큰 출력을 보낼 것이다.\n\n
\nTransform 클래스는 [_read()
][]와 [_write()
][] 메서드를 구현하기 보다는\n_transform()
메서드를 구현해야 하고 선택적으로 _flush()
메서드를\n구현할 수도 있다.(하단 참조)\n\n
Transform 클래스를 확장한 클래스에서는 버퍼링 설정을 적절하게 초기화할 수 있도록\n생성자를 호출해야 한다.\n\n
\n" }, { "textRaw": "transform.\\_transform(chunk, encoding, callback)", "type": "method", "name": "\\_transform", "signatures": [ { "params": [ { "textRaw": "`chunk` {Buffer | String} 변환할 청크. `decodeStrings` 옵션을 `false`로 설정하지 않는한 항상 버퍼가 될 것이다. ", "name": "chunk", "type": "Buffer | String", "desc": "변환할 청크. `decodeStrings` 옵션을 `false`로 설정하지 않는한 항상 버퍼가 될 것이다." }, { "textRaw": "`encoding` {String} 청크가 문자열인 경우 이 인코딩 타입이다. (`decodeStrings` 청크가 버퍼이면 무시한다.) ", "name": "encoding", "type": "String", "desc": "청크가 문자열인 경우 이 인코딩 타입이다. (`decodeStrings` 청크가 버퍼이면 무시한다.)" }, { "textRaw": "`callback` {Function} 제공된 청크의 처리가 끝났을 때 이 함수를 호출한다. (선택적으로 오류 인자와 함께) ", "name": "callback", "type": "Function", "desc": "제공된 청크의 처리가 끝났을 때 이 함수를 호출한다. (선택적으로 오류 인자와 함께)" } ] }, { "params": [ { "name": "chunk" }, { "name": "encoding" }, { "name": "callback" } ] } ], "desc": "Note: 이 함수는 절대로 직접 호출하지 말아야 한다. 자식 클래스가 구현하거나\n내부 Transform 클래스 메서드만 호출해야 한다.\n\n
\n모든 Transform 스트림 구현체는 입력을 받고 출력을 생산하도록 _transform
를\n제공해야 한다.\n\n
해당 Transform 클래스가 무엇을 하던지 간에 쓰여진 바이트를 다루고 인터페이스의 읽기\n쪽에 이를 전달하도록 _transform
을 수행해야 한다. 비동기 I/O를 수행하거나\n어떤 것을 처리하는 등이다.\n\n
해당 입력 청크에서 출력을 생성하도록 해당 청크의 결과로 얼마나 많은 데이터를 출력하기\n원하는지에 따라 transform.push(outputChunk)
를 0번이나 여러번 호출해라.\n\n
현재 청크가 완전히 소비되었을 때만 callback 함수를 호출한다. 특정 입력 청크의\n결과와 출력이 같을 수도 있고 같지 않을수도 있다.\n\n
\n이 메서드는 메서드를 정의한 클래스 내부에서 사용하고 사용자 프로그램이 직접 호출하면\n안되기 때문에 언더스코어로 시작한다. 하지만 자신의 확장 클래스에서 이 메서드를\n오버라이드할 수 있다.\n\n
\n" }, { "textRaw": "transform.\\_flush(callback)", "type": "method", "name": "\\_flush", "signatures": [ { "params": [ { "textRaw": "`callback` {Function} 남아있는 데이터를 모두 내보냈을 때 이 함수를 호출한다. (선택적으로 오류 인자와 함께) ", "name": "callback", "type": "Function", "desc": "남아있는 데이터를 모두 내보냈을 때 이 함수를 호출한다. (선택적으로 오류 인자와 함께)" } ] }, { "params": [ { "name": "callback" } ] } ], "desc": "Note: 이 함수는 절대로 직접 호출하지 말아야 한다. 자식 클래스가 구현할 수도 있는데\n자식 클래스가 구현했다면 내부 Transform 클래스 메서드만 호출할 것이다.\n\n
\n일부의 경우 변환 작업이 스트림의 끝에서 약간 더 많은 데이터를 발생시키도록 해야할 수도 있다.\n예를 들어 Zlib
압축 스트림은 출력을 최적화해서 압축할 수 있도록 어떤 내부 상태를 저장할\n것이다. 하지만 결국에는 데이터가 완료될 수 있도록 남아있는 것으로 최선의 작업을 해야할\n필요가 있다.\n\n
이러한 경우 쓰진 데이터를 모두 소비했지만 읽기 쪽에 끝났음을 알리는 end
를 발생하기 전인\n아주 마지막에 호출될 _flush
메서드를 구현할 수 있다. _transform
와 마찬가지로 적절하게\n0번이나 여러번 transform.push(chunk)
를 호출하고 flush작업이 완료되었을 때\ncallback
을 호출해라.\n\n
이 메서드는 메서드를 정의한 클래스 내부에서 사용하고 사용자 프로그램이 직접 호출하면\n안되기 때문에 언더스코어로 시작한다. 하지만 자신의 확장 클래스에서 이 메서드를\n오버라이드할 수 있다.\n\n
\nSimpleProtocol
parser v2위의 간단한 프로토콜 파서 예제를 고수준의 [Transform][] 스트림 클래스를 사용해서\n간단하게 구현할 수 있고 이는 위의 parseHeader
와 SimpleProtocol v1
예제와\n비슷하다.\n\n
이 예제에서는 인자로 입력을 제공하기 보다는 더 이상적인 Node 스트림 접근으로\n파서에 파이프를 연결한다.\n\n
\nvar util = require('util');\nvar Transform = require('stream').Transform;\nutil.inherits(SimpleProtocol, Transform);\n\nfunction SimpleProtocol(options) {\n if (!(this instanceof SimpleProtocol))\n return new SimpleProtocol(options);\n\n Transform.call(this, options);\n this._inBody = false;\n this._sawFirstCr = false;\n this._rawHeader = [];\n this.header = null;\n}\n\nSimpleProtocol.prototype._transform = function(chunk, encoding, done) {\n if (!this._inBody) {\n // 청크가 \\n\\n를 가졌는지 검사한다\n var split = -1;\n for (var i = 0; i < chunk.length; i++) {\n if (chunk[i] === 10) { // '\\n'\n if (this._sawFirstCr) {\n split = i;\n break;\n } else {\n this._sawFirstCr = true;\n }\n } else {\n this._sawFirstCr = false;\n }\n }\n\n if (split === -1) {\n // 여전히 \\n\\n를 기다린다\n // 청크를 치워두고 다시 시도한다.\n this._rawHeader.push(chunk);\n } else {\n this._inBody = true;\n var h = chunk.slice(0, split);\n this._rawHeader.push(h);\n var header = Buffer.concat(this._rawHeader).toString();\n try {\n this.header = JSON.parse(header);\n } catch (er) {\n this.emit('error', new Error('invalid simple protocol data'));\n return;\n }\n // 헤더 파싱이 끝났음을 알려준다.\n this.emit('header', this.header);\n\n // 일부 추가적인 데이터를 얻었으므로 이를 먼저 발생시킨다.\n this.push(chunk.slice(split));\n }\n } else {\n // 여기서 기존처럼 컨슈머에 데이터를 제공한다.\n this.push(chunk);\n }\n done();\n};\n\n// 사용방법:\n// var parser = new SimpleProtocol();\n// source.pipe(parser)\n// 이제 파서는 파싱된 헤더 데이터를 가진 'header'를 발생시킬\n// readable 스트림이다.
\n"
}
]
},
{
"textRaw": "Class: stream.PassThrough",
"type": "class",
"name": "stream.PassThrough",
"desc": "이는 입력 바이트를 출력으로 단순히 전달하는 [Transform][] 스트림의 별로 중요치 않은 구현체이다.\n이 클래스의 목적은 주로 예제나 테스트이지만 새로운 스트림에 대한 블럭을 구성하는 경우처럼\n가끔은 유용한 경우가 있다.\n\n\n
\n" } ] }, { "textRaw": "Streams: Under the Hood", "name": "Streams: Under the Hood", "type": "misc", "miscs": [ { "textRaw": "Buffering", "name": "Buffering", "type": "misc", "desc": "Writable 스트림과 Readable 스트림은 _writableState.buffer
나\n_readableState.buffer
를 각각 호출해서 내부 객체에 데이터를 버퍼링할 것이다.\n\n
버퍼될 데이터의 양은 생성자에 전달한 highWaterMark
옵션에 따라 다르다.\n\n
Readable 스트림에서는 구현체가 [stream.push(chunk)
][]를 호출했을 때 버퍼링이 일어난다.\n스트림의 컨슈머가 stream.read()
를 호출하지 않은 경우 데이터가 소비될 때까지 데이터는\n내부 큐에 있을 것이다.\n\n
Writable 스트림에서는 사용자가 [stream.write(chunk)
][]를 반복적으로\n호출했을 때(write()
가 false
를 반환하더라도) 버퍼링이 일어난다.\n\n
스트림의 목적은(특히 pipe()
메서드) 데이터 버퍼링을 수긍할만한 수준으로 제한해서 속도가\n제각각인 소스와 목적지가 사용가능한 메모리를 넘어서지 않게 하기 위함이다.\n\n
데이터는 실제로 소비하지 않으면서 사용하는 readable 스트림의 메카니즘을 갱신하고자 하는\n경우가 있다. 이러한 경우에는 항상 null을 반환하는 stream.read(0)
를 호출할 수 있다.\n\n
내부 읽기 버퍼가 highWaterMark
보다 작고 스트림이 읽고 있는 중이 아닌 경우 read(0)
를\n호출하면 저수준의 _read
호출이 발생할 것이다.\n\n
이렇게 해야하는 경우는 거의 없지만 Node 내부에서 이러한 작업을 하는 경우를\n볼 수 있을 것이다.(특히 Readable 스트림 클래스의 내부에서)\n\n
\n", "type": "misc", "displayName": "`stream.read(0)`" }, { "textRaw": "`stream.push('')`", "name": "`stream.push('')`", "desc": "0 바이트 문자열이나 버퍼를 밀어넣을 때([Object mode][]가 아닌 경우) 흥미로운 부가작용이\n일어난다. 이는 [stream.push()
][]를 호출한 것이므로 reading
과정을 종료할 것이다.\n하지만 읽기 가능한 버퍼에는 어떤 데이터도 추가하지 않으므로 유저가 사용할 수 있는 데이터는\n전혀 없다.\n\n
아주 드물게 지금은 제공할 데이터가 없지만 스트림의 컨슈머(또는 자신의 코드의 다른 곳에서)는\nstream.read(0)
를 호출해서 언제 다시 확인해 봐야 하는지 알아야 하는 경우가 있다.\n이러한 경우 stream.push('')
를 호출할 것이다.\n\n
지금까지는 이 기능을 유일하게 사용한 곳이 Node v0.12에서는 폐기된 [tls.CryptoStream][]\n클래스다. stream.push('')
를 사용해야 한다면 무언가 크게 잘못될 가능성이 아주 크므로\n다른 접근이 없는지 생각해 보기를 바란다.\n\n
Node v0.10 이전 버전에서는 Readable 스트림 인터페이스가 더 간단하지만 동시에\n덜 강력하고 덜 유용하다.\n\n
\nread()
메서드를 호출하기를 기다리기 보다는 'data'
이벤트가 바로 발생하기 시작할\n것이다. 데이터를 다루는 방법을 결정하기 위해서 I/O를 사용해야 한다면 데이터를 잃어버리지\n않기 위해 어떤 종류든 버퍼에 청크를 저장해야 한다.pause()
메서드는 보장된다기 보다는 권고사항이다. 즉, 스트림이 멈춰진 상태에 있더라도\n'data'
이벤트를 받을 준비를 하고 있어야 한다.Node v0.10에는 아래에서 설명한 Readable 클래스가 추가되었다. 오래된 Node 프로그램과의\n하위 호환성때문에 'data'
이벤트 핸들러가 추가되거나 pause()
혹은 resume()
\n메서드가 호출되었을 때 Readable 스트림은 "flowing mode"로 바뀐다. 그래서 새로운\nread()
메서드와 'readable'
이벤트를 사용하지 않더라도 'data'
청크를\n잃어버릴 걱정을 하지 않아도 된다.\n\n
대부분의 프로그램은 정상적으로 잘 동작할 것이지만 이 기능은 다음과 같은 상황에\n대처한다.\n\n
\n'data'
이벤트 핸들러가 추가되지 않았을 때.pause()
와 resume()
메서드가 호출되지 않았을 때.에를 들면 다음 코드를 생각해 보자.\n\n
\n// 주의! 동작하지 않음!\nnet.createServer(function(socket) {\n\n // 'end' 메서드를 추가했지만 데이터를 소비하지 않는다\n socket.on('end', function() {\n // 이 코드는 실행되지 않는다.\n socket.end('I got your message (but didnt read it)\\n');\n });\n\n}).listen(1337);
\nNode v0.10 이전 버전에서 들어오는 메시지 데이터는 그냥 버려진다.\n하지만 Node v0.10 이상에서는 소켓이 영원히 멈춰진 상태로 남게 된다.\n\n
\n이 상황을 해결하려면 "old mode"로 동작하도록 resume()
을 호출해야 한다.\n\n
// 해결 방법\nnet.createServer(function(socket) {\n\n socket.on('end', function() {\n socket.end('I got your message (but didnt read it)\\n');\n });\n\n // 데이터의 흐름이 시작되고 데이터를 버린다.\n socket.resume();\n\n}).listen(1337);
\nflowing-mode로 변경되는 새로운 Readable 스트림에 추가적으로 v0.10 이전 방식의 스트림은\nwrap()
메서드를 사용해서 Readable 클래스로 감쌀 수 있다.\n\n\n
일반적으로 스트림은 문자열이나 버퍼에서만 동작한다.\n\n
\nobject 모드의 스트림은 버퍼나 문자열이 아닌 일반적인 자바스크립트 값을\n발생시킬 수 있다.\n\n
\nobject 모드의 Readable 스트림은 size 인자의 크기에 상관없이\nstream.read(size)
호출에서 항상 하나의 아이템을 반환할 것이다.\n\n
object 모드의 Writable 스트림은 stream.write(data, encoding)
의\nencoding
인자를 항상 무시할 것이다.\n\n
특별한 값인 null
은 object 모드 스트림에서도 여전히 특별한 값이다. 즉, object 모드의\nreadable 스트림에서 stream.read()
이 반환한 null
은 더이상 데이터가 없음을\n의미하고 [stream.push(null)
][]은 스트림 데이터가 끝났다(EOF
)는 신호로 사용한다.\n\n
Node 코어에서 object 모드인 스트림은 없다.\n이 방식은 사용자의 스트리밍 라이브러리에서만 사용한다.\n\n
\n스트 자식 클래스 생성자에서 옵션 객체에 objectMode
를 설정해야 했다.\n중간 스트림에 objectMode
를 설정하는 것은 안전하지 않다.\n\n
[Readable][] 스트림은 _readableState
라는 멤버 객체를 가진다.\n[Writable][] 스트림은 _writableState
라는 멤버 객체를 가진다.\n[Duplex][] 스트림은 위의 두 멤버 객체를 모두 가진다.\n\n
이러한 객체는 일반적으로 자식 클래스에서 수정하면 안된다.\n하지만 읽는 쪽이 objectMode
이고 쓰는 쪽은 objectMode
가 아닌 Duplex나\nTransform 스트림이라면 적절한 상태 객체에 명시적으로 플래그를 설정해서 생성자에서\n수정해야 한다.\n\n
var util = require('util');\nvar StringDecoder = require('string_decoder').StringDecoder;\nvar Transform = require('stream').Transform;\nutil.inherits(JSONParseStream, Transform);\n\n// \\n으로 구분된 JSON 문자열 데이터를 가져오고 파싱된 객체를 보낸다.\nfunction JSONParseStream(options) {\n if (!(this instanceof JSONParseStream))\n return new JSONParseStream(options);\n\n Transform.call(this, options);\n this._writableState.objectMode = false;\n this._readableState.objectMode = true;\n this._buffer = '';\n this._decoder = new StringDecoder('utf8');\n}\n\nJSONParseStream.prototype._transform = function(chunk, encoding, cb) {\n this._buffer += this._decoder.write(chunk);\n // newline으로 분리한다\n var lines = this._buffer.split(/\\r?\\n/);\n // 버퍼링된 마지막 부분의 라인을 유지한다\n this._buffer = lines.pop();\n for (var l = 0; l < lines.length; l++) {\n var line = lines[l];\n try {\n var obj = JSON.parse(line);\n } catch (er) {\n this.emit('error', er);\n return;\n }\n // 읽을 수 있는 컨슈머로 파싱된 객체를 밀어넣는다\n this.push(obj);\n }\n cb();\n};\n\nJSONParseStream.prototype._flush = function(cb) {\n // 남은 부분을 처리한다\n var rem = this._buffer.trim();\n if (rem) {\n try {\n var obj = JSON.parse(rem);\n } catch (er) {\n this.emit('error', er);\n return;\n }\n // 읽을 수 있는 컨슈머로 파싱된 객체를 밀어넣는다\n this.push(obj);\n }\n cb();\n};
\n상태 객체에는 프로그램에서 스트림의 상태를 디버깅할 수 있는 유용한 정보가 담겨있다. 이 객체를\n살펴보는 건 안전하지만 생성자에서 옵션 플래스를 설정하는 것을 넘어서서 객체를 수정하는 것은\n안전하지 않다.\n\n\n
\n", "type": "misc", "displayName": "State Objects" } ] } ], "examples": [ { "textRaw": "Class: stream.Readable", "type": "example", "name": "stream.Readable", "desc": "stream.Readable
은 [_read(size)
][] 메서드의 의존 구현체를 확장도록 설계된\n추상 클래스다.\n\n
프로그램에서 스트림을 사용하는 방법은 위의 [API for Stream Consumers][]를 참고해라.\n이어서 프로그램에서 Readable 스트림을 어떻게 구현하는지 설명한다.\n\n
\n다음은 Readable 스트림의 기본적인 예제다. 이 예제는 순차적으로 1부터\n1,000,000까지 숫자를 발생시키고 끝난다.\n\n
\nvar Readable = require('stream').Readable;\nvar util = require('util');\nutil.inherits(Counter, Readable);\n\nfunction Counter(opt) {\n Readable.call(this, opt);\n this._max = 1000000;\n this._index = 1;\n}\n\nCounter.prototype._read = function() {\n var i = this._index++;\n if (i > this._max)\n this.push(null);\n else {\n var str = '' + i;\n var buf = new Buffer(str, 'ascii');\n this.push(buf);\n }\n};
\n이는 위에서 설명한 parseHeader
함수와 비슷하지만 커스텀 스트림으로 구현되었다.\n그리고 이 구현체는 들어오는 데이터를 문자열로 변환하지 않는다.\n\n
하지만 이는 [Transform][] 스트림으로 구현하는 것이 더 좋다.\n더 좋은 구현체는 아래 부분을 참고해라.\n\n
\n// 간단한 데이터 프로토콜에 대한 파서.\n// "header"는 JSON 객체이고 이어서 두개의 \\n 문자가 오로고 이어서 메시지 바디가 온다.\n//\n// Note: 이는 Transform 스트림으로 훨씬 간단히 할 수 있다!\n// 이를 위해 Readable를 직접 사용하는 것이 차선책이다. 이에 대한 예제은 아래의\n// Transform 부분을 참고해라.\n\nvar Readable = require('stream').Readable;\nvar util = require('util');\n\nutil.inherits(SimpleProtocol, Readable);\n\nfunction SimpleProtocol(source, options) {\n if (!(this instanceof SimpleProtocol))\n return new SimpleProtocol(options);\n\n Readable.call(this, options);\n this._inBody = false;\n this._sawFirstCr = false;\n\n // 소스는 소켓이나 파일같은 readable 스트림이다\n this._source = source;\n\n var self = this;\n source.on('end', function() {\n self.push(null);\n });\n\n // 소스를 읽을 수 있을 때마다 무시한다.\n // read(0)은 바이트를 전혀 소비하지 않을 것이다\n source.on('readable', function() {\n self.read(0);\n });\n\n this._rawHeader = [];\n this.header = null;\n}\n\nSimpleProtocol.prototype._read = function(n) {\n if (!this._inBody) {\n var chunk = this._source.read();\n\n // 소스에 데이터가 없으면 아직 데이터를 갖지 않는다.\n if (chunk === null)\n return this.push('');\n\n // 청크가 \\n\\n를 가졌는지 검사한다\n var split = -1;\n for (var i = 0; i < chunk.length; i++) {\n if (chunk[i] === 10) { // '\\n'\n if (this._sawFirstCr) {\n split = i;\n break;\n } else {\n this._sawFirstCr = true;\n }\n } else {\n this._sawFirstCr = false;\n }\n }\n\n if (split === -1) {\n // 아직 \\n\\n를 기다리고 있다\n // 청크를 치워두고 다시 시도한다.\n this._rawHeader.push(chunk);\n this.push('');\n } else {\n this._inBody = true;\n var h = chunk.slice(0, split);\n this._rawHeader.push(h);\n var header = Buffer.concat(this._rawHeader).toString();\n try {\n this.header = JSON.parse(header);\n } catch (er) {\n this.emit('error', new Error('invalid simple protocol data'));\n return;\n }\n // 이제 어떤 추가적인 데이터를 가졌으므로 컨슈머가 볼 수 있도록\n // 읽기 큐에 남은 부분을 다시 unshift한다.\n var b = chunk.slice(split);\n this.unshift(b);\n\n // 그리고 헤더 파싱을 완료했다는 것을 알려준다.\n this.emit('header', this.header);\n }\n } else {\n // 여기서 단순히 컨슈머에게 데이터를 제공한다.\n // push(null)이 EOF를 의미하므로 push(null)을 사용하지 않도록 조심해라.\n var chunk = this._source.read();\n if (chunk) this.push(chunk);\n }\n};\n\n// 사용방법:\n// var parser = new SimpleProtocol(source);\n// 이제 파서는 파싱된 헤더 데이터를 가진 'header'를 발생시킬\n// readable 스트림이다.
\n",
"methods": [
{
"textRaw": "new stream.Readable([options])",
"type": "method",
"name": "Readable",
"signatures": [
{
"params": [
{
"textRaw": "`options` {Object} ",
"options": [
{
"textRaw": "`highWaterMark` {Number} 사용하는 리소스에서 읽기를 중단하기 전에 내부 버퍼에 저장할 최대 바이트 수. 기본값=16kb ",
"name": "highWaterMark",
"type": "Number",
"desc": "사용하는 리소스에서 읽기를 중단하기 전에 내부 버퍼에 저장할 최대 바이트 수. 기본값=16kb"
},
{
"textRaw": "`encoding` {String} 이 값을 지정하면 지정한 인코딩으로 버퍼를 문자열로 디코드한다. 기본값=null ",
"name": "encoding",
"type": "String",
"desc": "이 값을 지정하면 지정한 인코딩으로 버퍼를 문자열로 디코드한다. 기본값=null"
},
{
"textRaw": "`objectMode` {Boolean} 이 스트림이 객체의 스트림처럼 동작해야 하는지 여부. 즉, stream.read(n)이 n 크기의 Buffer 대신 문자열 값을 반환한다는 것을 의미한다. ",
"name": "objectMode",
"type": "Boolean",
"desc": "이 스트림이 객체의 스트림처럼 동작해야 하는지 여부. 즉, stream.read(n)이 n 크기의 Buffer 대신 문자열 값을 반환한다는 것을 의미한다."
}
],
"name": "options",
"type": "Object",
"optional": true
}
]
},
{
"params": [
{
"name": "options",
"optional": true
}
]
}
],
"desc": "Readable 클래스를 확장하는 클래스에서 버퍼링 설정을 적절하게 초기화할 수 있도록\nReadable 생성자를 꼭 호출해라.\n\n
\n" }, { "textRaw": "readable.\\_read(size)", "type": "method", "name": "\\_read", "signatures": [ { "params": [ { "textRaw": "`size` {Number} 비동기적으로 읽을 바이트 수 ", "name": "size", "type": "Number", "desc": "비동기적으로 읽을 바이트 수" } ] }, { "params": [ { "name": "size" } ] } ], "desc": "Note: 이 함수를 구현하되 직접 호출하지는 마라.\n\n
\n이 함수는 직접 호출하지 말아야 한다. 이 함수는 자식 클래스에서 구현해야 하고\nReadable 클래스 내부 함수에서만 호출해야 한다.\n\n
\n모든 Readable 스트림 구현체는 사용하는 리소스에서 데이터를 가져오는 _read
메서드를\n반드시 제공해야 한다.\n\n
이 함수는 클래스는 내부에서만 사용할 목적이므로 언더스코어 접두사가 붙어있고 사용자\n프로그램에서 직접 호출하지 않아야 한다. 하지만 자신만의 확장 클래스에서 이 메서드를\n오버라이드하기 원할 수도 있다.\n\n
\n데이터를 사용할 수 있을 때 readable.push(chunk)
를 호출해서 읽기 큐에 데이터를 넣는다.\npush
가 false를 반환하면 읽기를 멈춰야 한다. _read
가 다시 호출됐을 때 추가적인\n데이터를 큐에 넣기 시작해야 한다.\n\n
size
아규먼트는 권고사항이다. "read"는 데이터를 반환하는 하나의 호출인\n구현체에서 얼마나 많은 데이터를 가여와야 하는지 지정하는데 이 값을 사용한다. TCP나 TLS처럼\n관련이 없는 구현체는 이 인자를 무시하고 데이터를 이용할 수 있을때마다 제공할 것이다. 예를 들면\n[stream.push(chunk)
][]를 호출하기 전에 size
바이트가 사용가능할 때까지\n"기다릴" 필요가 없다.\n\n
Note: 이 함수는 Readable 구현체에서 호출해야 지 Readable 스트림를 소비하는 쪽에서\n호출하면 안된다.\n\n
\npush(chunk)
가 최소 한번 실행될 때까지는 _read()
함수는 다시 호출되지\n않을 것이다.\n\n
나중에 'readable'
이벤트가 발생했을 때 read()
메서드를 호출해서 데이터를 꺼내도록\nReadable
클래스는 읽기 큐에 데이터를 넣어서 동작한다.\n\n
push()
메서드는 데이터를 읽기 큐에 명시적으로 넣을 것이다. 이 함수를 null
로 호출하면\n데이터가 끝났다는(EOF) 신호가 올 것이다.\n\n
이 API는 최대한 유연하게 설계되었다. 예를 들어 어떤 종류의 pause/resume 메카니즘과 데이터\n콜백을 가진 저수준 소스를 감싸고 있다고 해보자. 이러한 경우 다음과 같이 해서 저수준 소스를\n감쌀 수 있다.\n\n
\n// source는 readStop(), readStart() 메서드와\n// source가 데이터를 가졌을 때 호출되는 `ondata` 멤버,\n// 데이터가 끝났을 때 호출되는 `onend` 멤버를 가진 객체이다.\n\nutil.inherits(SourceWrapper, Readable);\n\nfunction SourceWrapper(options) {\n Readable.call(this, options);\n\n this._source = getLowlevelSourceObject();\n var self = this;\n\n // 데이터가 있을 때마다 내부 버퍼에 데이터를 넣는다.\n this._source.ondata = function(chunk) {\n // push()가 false를 반환하면 source에서 읽기를 멈춰야 한다\n if (!self.push(chunk))\n self._source.readStop();\n };\n\n // source가 끝났을 때 EOF를 알리는 `null` 청크를 넣는다.\n this._source.onend = function() {\n self.push(null);\n };\n}\n\n// 이 경우에 권고사항인 size 인자를 무시하고 스트림이 추가적인 데이터를\n// 가져오도록 하고 싶을 때 _read를 호출할 것이다.\nSourceWrapper.prototype._read = function(size) {\n this._source.readStart();\n};
\n"
}
]
}
],
"type": "module",
"displayName": "Stream"
},
{
"textRaw": "Crypto",
"name": "crypto",
"desc": "Stability: 2 - Unstable; 차기 버전에서 API 변경을 논의 중이다.\n호환성을 깨뜨리는 정도의 변경은 최소화할 것이다. 하단을 참고해라.
\n이 모듈에 접근하려면 require('crypto')
를 사용해라.\n\n
crypto 모듈은 안정한 HTTPS net이나 http 연결에서 사용되는\n안정한 인증서를 캡슐화하는 방법을 제공한다.\n\n
\nOpenSSL의 hash, hmac, cipher, decipher, sign, verify 메서드의 랩퍼(wrapper)도\n제공한다.\n\n
\n메서드에 대한 래퍼(wrapper) 세트를 제공한다.\n\n\n
\n", "methods": [ { "textRaw": "crypto.getCiphers()", "type": "method", "name": "getCiphers", "desc": "지원하는 암호화 이름의 배열을 반환한다.\n\n
\n예제:\n\n
\nvar ciphers = crypto.getCiphers();\nconsole.log(ciphers); // ['AES-128-CBC', 'AES-128-CBC-HMAC-SHA1', ...]
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "crypto.getHashes()",
"type": "method",
"name": "getHashes",
"desc": "지원하는 해시 알고리즘 이름의 배열을 반환한다.\n\n
\n예제:\n\n
\nvar hashes = crypto.getHashes();\nconsole.log(hashes); // ['sha', 'sha1', 'sha1WithRSAEncryption', ...]
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "crypto.createCredentials(details)",
"type": "method",
"name": "createCredentials",
"desc": "인증서 객체를 생성한다. 선택사항인 details는 키를 가진 딕셔너리가 된다.\n\n
\npfx
: PFX나 PKCS12로 암호화된 개인키, 인증서, CA 증명서를 담고 있는 문자열이나 버퍼key
: PEM으로 암호화된 개인키를 담고 있는 문자열passphrase
: 개인키나 pfx에 대한 암호문(passphrase) 문자열cert
: PEM으로 암호화된 증명서를 담고 있는 문자열ca
: PEM으로 암호화된 믿을 수 있는 CA 증명서의 문자열이나 리스트crl
: PEM으로 암호화된 CRL(Certificate Revocation List)의 문자열 혹은 문자열의 리스트ciphers
: 사용하거나 제외할 암호(cipher)를 설명하는 문자열. 자세한 형식은\nhttp://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT를 참조해라.'ca'에 대한 세부내용을 전달하지 않는다면 node.js는 공개적으로 신뢰할 수 있는 CA의 리스트를 기본으로\n
\nhttp://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt에서\n받아서 사용할 것이다.\n\n\n
\n", "signatures": [ { "params": [ { "name": "details" } ] } ] }, { "textRaw": "crypto.createHash(algorithm)", "type": "method", "name": "createHash", "desc": "해시 객체를 생성하고 반환한다. 전달한 algorithm의 암호화 해시는 해시 다이제스트를\n생성하는 데 사용할 수 있다.\n\n
\nalgorithm
은 플랫폼상의 OpenSSL 버전에서 사용할 수 있는 알고리즘에 의존한다.\n'sha1'
, 'md5'
, 'sha256'
, 'sha512'
등이 있다. 최근 릴리즈에서는\nopenssl list-message-digest-algorithms
로 사용할 수 있는 다이제스트 알로리즘을 볼 수 있다.\n\n
예제: 이 프로그램은 파일의 sha1 합을 생성한다.\n\n
\nvar filename = process.argv[2];\nvar crypto = require('crypto');\nvar fs = require('fs');\n\nvar shasum = crypto.createHash('sha1');\n\nvar s = fs.ReadStream(filename);\ns.on('data', function(d) {\n shasum.update(d);\n});\n\ns.on('end', function() {\n var d = shasum.digest('hex');\n console.log(d + ' ' + filename);\n});
\n",
"signatures": [
{
"params": [
{
"name": "algorithm"
}
]
}
]
},
{
"textRaw": "crypto.createHmac(algorithm, key)",
"type": "method",
"name": "createHmac",
"desc": "hmac 객체를 생성하고 반환한다. 전달한 algorithm과 key의 암호화 해시이다.\n\n
\n이는 읽고 쓸 수 있는 stream이다. hmac을 계산하는데 쓰여진 데이터를 사용한다.\n스트림의 쓰기 가능한 쪽이 종료되고 나면 계산한 다이제스트를 얻는데 read()
메서드를 사용해라.\n레거시 update
와 digest
메서드도 지원한다.\n\n
algorithm
는 OpenSSL에서 사용할 수 있는 알고리즘에 의존한다. -- 위의 createHash를 봐라.\nkey
는 사용할 hmac 키이다.\n\n
전달한 algorithm과 password로 암호화한 암호화 객체를 생성하고 반환한다.\n\n
\nalgorithm
는 OpenSSL에 의존적이다. 'aes192'
등이 있다.\nOpenSSL 최근 릴리즈에서는 openssl list-cipher-algorithms
로 사용할 수 있는\n암호화 알고리즘을 볼 수 있다.\npassword
는 key와 IV를 얻는데 사용하고 반드시 'binary'
로 인코딩된 문자열이나\nbuffer이어야 한다.\n\n
이는 읽고 쓸 수 있는 stream이다. 해시를 계산하는데 작성된 데이터를 사용한다.\n스트림의 쓰기 가능한 쪽이 종료되면 계산된 해시 다이제스트를 얻을 때 read()
메서드를 사용해라.\n레거시 update
와 digest
메서드도 지원한다.\n\n
전달한 algorithm, key, iv로 암호화된 암호화 객체를 생성하고 반환한다.\n\n
\nalgorithm
은 createCipher()의
algorithm와 같다.
key는 algorithm에서 사용하는 로우 키(raw key)\n이다.
iv`는 초기화\n벡터(Initialization vector)이다.\n\n
key
와 iv
는 반드시 'binary'
로 인코딩된\n문자열이나 buffers여야 한다.\n\n
전달한 algorithm와 key로 decipher 객체를 생성하고 반환한다.\n이 함수는 위의 [createCipher()][]의 반영이다.\n\n
\n", "signatures": [ { "params": [ { "name": "algorithm" }, { "name": "password" } ] } ] }, { "textRaw": "crypto.createDecipheriv(algorithm, key, iv)", "type": "method", "name": "createDecipheriv", "desc": "전달한 algorithm, key, iv로 decipher 객체를 생성하고 반환한다.\n이 함수는 위의 [createCipheriv()][]의 반영이다.\n\n
\n", "signatures": [ { "params": [ { "name": "algorithm" }, { "name": "key" }, { "name": "iv" } ] } ] }, { "textRaw": "crypto.createSign(algorithm)", "type": "method", "name": "createSign", "desc": "전달한 algorithm으로 서명된 객체를 생성하고 반환한다.\n최근 OpenSSL 릴리즈에서 openssl list-public-key-algorithms
로 사용할 수 있는\n서명된 알고리즘을 볼 수 있다. 예를 들면 'RSA-SHA256'
가 있다.\n\n
전달한 algorithm으로 검증 객체를 생성하고 반환한다.\n이 함수는 위의 서명객체의 반영이다.\n\n
\n", "signatures": [ { "params": [ { "name": "algorithm" } ] } ] }, { "textRaw": "crypto.createDiffieHellman(prime_length)", "type": "method", "name": "createDiffieHellman", "desc": "Diffie-Hellman 키 교환 객체를 생성하고 전달한 비트 길이의 소수를 생성한다.\n사용된 제너레이터는 2
이다.\n\n
제공된 소수를 사용해서 Diffie-Hellman 키 교환 객체를 생성한다. 사용된 제너레이터는\n2
이다. 인코딩은 'binary'
, 'hex'
, 'base64'
가 될 수 있다.\n인코딩을 지정하지 않으면 버퍼라고 가정한다.\n\n
미리 정의된 Diffie-Hellman 키 교환 객체를 생성한다.\n지원하는 그룹은 'modp1'
, 'modp2'
, 'modp5'
\n([RFC 2412][]에 정의되어 있다.)\n와 'modp14'
, 'modp15'
, 'modp16'
, 'modp17'
, 'modp18'
\n([RFC 3526][]에 정의되어 있다.)이다.\n반환된 객체는 위의 [crypto.createDiffieHellman()][]가 생성한 객체의\n인터페이스와 비슷하지만 키를 변경할 수 없다.(예를 들면\n[diffieHellman.setPublicKey()][]를 사용해서)\n이 루틴을 사용했을 때의 이점은 관련자들이 미리 그룹 규칙을 생성하지 않고\n교환하지도 않아서 프로세서와 통신 시간을 모두 아낄 수 있다.\n\n
공유된 비밀키를 얻는 예제:\n\n
\nvar crypto = require('crypto');\nvar alice = crypto.getDiffieHellman('modp5');\nvar bob = crypto.getDiffieHellman('modp5');\n\nalice.generateKeys();\nbob.generateKeys();\n\nvar alice_secret = alice.computeSecret(bob.getPublicKey(), null, 'hex');\nvar bob_secret = bob.computeSecret(alice.getPublicKey(), null, 'hex');\n\n/* alice_secret와 bob_secret는 같아야 한다. */\nconsole.log(alice_secret == bob_secret);
\n",
"signatures": [
{
"params": [
{
"name": "group_name"
}
]
}
]
},
{
"textRaw": "crypto.pbkdf2(password, salt, iterations, keylen, callback)",
"type": "method",
"name": "pbkdf2",
"desc": "비동기적인 PBKDF2가 전달한 password, salt, iterations에서 전달한 길이의 키를 얻기 위해\n의사난수의(pseudorandom) 함수 HMAC-SHA1를 적용한다.\ncallback은 2개의 아규먼트 (err, derivedKey)
를 받는다.\n\n
동기 PBKDF2 함수. derivedKey를 반환하거나 오류를 던진다.\n\n
\n", "signatures": [ { "params": [ { "name": "password" }, { "name": "salt" }, { "name": "iterations" }, { "name": "keylen" } ] } ] }, { "textRaw": "crypto.randomBytes(size, [callback])", "type": "method", "name": "randomBytes", "desc": "강력한 암호의 의사난수(pseudo-random) 데이터를 생성한다. 사용법:\n\n
\n// async\ncrypto.randomBytes(256, function(ex, buf) {\n if (ex) throw ex;\n console.log('Have %d bytes of random data: %s', buf.length, buf);\n});\n\n// sync\ntry {\n var buf = crypto.randomBytes(256);\n console.log('Have %d bytes of random data: %s', buf.length, buf);\n} catch (ex) {\n // handle error\n}
\n",
"signatures": [
{
"params": [
{
"name": "size"
},
{
"name": "callback",
"optional": true
}
]
}
]
},
{
"textRaw": "crypto.pseudoRandomBytes(size, [callback])",
"type": "method",
"name": "pseudoRandomBytes",
"desc": "암호가 아닌 강력한 임의의 의사 데이터(pseudo-random data)를 생성한다.\n데이터가 충분히 길다면 반환된 데이터는 유일한 값이 될 것이지만 반드시 예측할 수 없는 것은\n아니다. 이 때문에 이 함수의 출력은 암호화된 키의 생성처럼 예측불가능성이 중요한 곳에서는\n사용하지 말아야 한다.\n\n
\n반면 사용방법은 crypto.randomBytes
의 반대이다.\n\n
데이터의 해시 다이제스트를 생성하는 클래스다.\n\n
\n읽고 쓸 수 있는 stream이다. 해시를 계산하는데 작성된 데이터를 사용한다.\n스트림의 작성가능한 쪽이 종료되고 나면 계산된 해시 다이제스트를 얻는데 read()
메서드를\n사용해라. 레거시 update
와 digest
메서드도 지원한다.\n\n
crypto.createHash
가 반환하는 클래스다.\n\n
전달한 input_encoding
의 data
로 해시 내용을 갱신한다.\n전달한 input_encoding
인코딩은 'utf8'
, 'ascii'
, 'binary'
가 될 수 있다.\n인코딩을 지정하지 않으면 버퍼라고 가정한다.\n\n
이 함수는 스트림처럼 새로운 데이터가 올 때마다 여러 번 호출될 수 있다.\n\n
\n", "signatures": [ { "params": [ { "name": "data" }, { "name": "input_encoding", "optional": true } ] } ] }, { "textRaw": "hash.digest([encoding])", "type": "method", "name": "digest", "desc": "해시되어야 하는 전달한 데이터의 모든 다이제스트를 계산한다.\nencoding
은 'hex'
, 'binary'
, 'base64'
가 될 수 있다.\n인코딩을 지정하지 않으면 버퍼를 반환한다.\n\n
Note: hash
객체는 digest()
메서드가 호출한 후에는 사용할 수 없다.\n\n\n
암호화 hmac 내용을 생성하는 클래스다.\n\n
\ncrypto.createHmac
가 리턴하는 클래스다.\n\n
전달한 data
로 hmac 내용을 갱신한다.\n이 함수는 스트림처럼 새로운 데이터가 올 때마다 여러번 호출될 수 있다.\n\n
hmac이 되어야 하는 전달한 데이터의 모든 다이제스트를 계산한다.\nencoding
은 'hex'
, 'binary'
, 'base64'
가 될 수 있다.\n인코딩을 지정하지 않으면 버퍼를 반환한다.\n\n
Note: hmac
객체는 digest()
메서드가 호출한 후에는 사용할 수 없다.\n\n\n
데이터를 암호화하는 클래스이다.\n\n
\ncrypto.createCipher
와 crypto.createCipheriv
가 반환하는 객체다.\n\n
Cipher 객체는 읽고 쓸 수 있는 streams이다. 읽기 가능한 쪽에서\n암호화된 데이터를 생성할 때 작성한 평범한 텍스트 데이터를 사용한다. 레거시 update
와\nfinal
메서드도 지원한다.\n\n
전달한 input_encoding
의 인코딩의 data
로 cipher를 갱신한다.\ninput_encoding
는 'utf8'
, 'ascii'
, 'binary'
가 될 수 있다.\n인코딩을 지정하지 않으면 버퍼라고 가정한다.\n\n
output_encoding
는 암호화된 데이터의 출력형식을 지정하고 'binary'
, 'base64'
,\n'hex'
가 될 수 있다. 기본값은 'binary'
이다.\n\n
암호화된 내용을 반환하고 스트림처럼 새로운 데이터로 여러번 호출할 수 있다.\n\n
\n", "signatures": [ { "params": [ { "name": "data" }, { "name": "input_encoding", "optional": true }, { "name": "output_encoding", "optional": true } ] } ] }, { "textRaw": "cipher.final([output_encoding])", "type": "method", "name": "final", "desc": "'binary'
, 'base64'
, 'hex'
중의 하나인 output_encoding
로 남아있는 모든\n암호화된 내용을 반환한다. 인코딩을 지정하지 않으면 버퍼를 반환한다.\n\n
Note: cipher
객체는 final()
메서드를 호출한 후에는 사용할 수 없다.\n\n
입력데이터의 자동 패딩을 사용하지 않고 블럭 크기를 사용한다. auto_padding
가 false이면 전체 입력데이터의 길이는 cipher의 블럭 크기의 배수가 되어야 하고 그렇지 않으면 final
는 실패할 것이다.\n표준이 아닌 패딩은 유용한데 예를 들어 PKCS 패딩 대신 0x0
를 사용할 수 있다. 이 함수는 반드시 cipher.final
이전에 호출해야 한다.\n\n\n
데이터를 복호화하는 클래스다.\n\n
\ncrypto.createDecipher
와 crypto.createDecipheriv
가 반환하는 클래스다.\n\n
Decipher 객체는 읽고 쓸 수 있는 streams이다. 읽기 가능한 쪽에서\n평범한 텍스트 데이터를 생성할 때 작성한 암호화된 데이터를 사용한다. 레거시 update
와\nfinal
메서드도 지원한다.\n\n
'binary',
'base64',
'hex'로 인코딩된
data`로 decipher를 갱신한다.\n인코딩을 지정하지 않으면 버퍼라고 가정한다.\n\n
output_decoding
는 반환할 복호화된 평문의 형식을 지정한다. 'binary'
, 'ascii'
,\n'utf8'
가 될 수 있고 버퍼를 지정하지 않으면 버퍼를 반환한다.\n\n
'binary'
, 'ascii'
, 'utf8'
중에 하나가 될 수 있는 output_encoding
로 남아있는\n모든 복호화된 평문을 반환한다. 인코딩을 지정하지 않으면 버퍼를 반환한다.\n\n
Note: decipher
객체는 final()
메서드가 호출된 후에는 사용할 수 없다.\n\n
표준 블럭 패팅없이 암호화된 데이터를 decipher.final
가 확인하고 제거하지 않도록 자동 패딩을 사용하지 않을 수 있다. 입력데이터의 길이가 cipher 블락 크기의 배수일 때만 동작한다.\n이 함수는 반드시 데이터를 decipher.update
로 스트리밍하기 전에 호출해야 한다.\n\n\n
서명을 생성하는 클래스다.\n\n
\ncrypto.createSign
가 반환하는 클래스이다.\n\n
Sign 객체는 쓸 수 있는 streams이다. 사그니처를 생성할 때 작성한 데이터를\n사용한다. 모든 데이터를 쓰고 나면 sign
메서드가 시그니처를 반환할 것이다.\n레거시 update
메서드도 지원한다.\n\n
data로 sign 객체를 갱신한다.\n이 함수는 스트림처럼 새로운 데이터가 올 때마다 여러 번 호출할 수 있다.\n\n
\n", "signatures": [ { "params": [ { "name": "data" } ] } ] }, { "textRaw": "sign.sign(private_key, [output_format])", "type": "method", "name": "sign", "desc": "전달한 갱신 데이터 모두를 sign을 통해서 서명을 계산한다.\nprivate_key
는 서명에 사용할 PEM 인코딩된 개인키를 담고 있는 문자열이다.\n\n
'binary'
, 'hex'
, 'base64'
가 될 수 있는 output_format
의 서명을 반환한다.\n인코딩을 지정하지 않으면 버퍼를 반환한다.\n\n
Note: sign
객체는 sign()
메서드를 호출한 후에는 사용할 수 없다.\n\n
서명을 검증하는 클래스다.\n\n
\ncrypto.createVerify
가 반환하는 클래스이다.\n\n
Verify 객체는 쓰기 가능한 streams이다. 제공된 시그니처로 유효성 검사를\n할 때 작성한 데이터를 사용한다. 모든 데이터를 쓰고 나서 제공된 시그니처가 유효한 경우\nverify
메서드가 true를 반환할 것이다. 레거시 update
메서드도 지원한다.\n\n
data로 verifier 객체를 갱신한다.\n이 함수는 스트림처럼 새로운 데이터가 올 때마다 여러 번 호출할 수 있다.\n\n
\n", "signatures": [ { "params": [ { "name": "data" } ] } ] }, { "textRaw": "verifier.verify(object, signature, [signature_format])", "type": "method", "name": "verify", "desc": "object
와 signature
를 사용해서 서명된 데이터를 검증한다. object
는 RSA 공개키,\nDSA 공개키, X.509 인증서 중 하나가 될 수 있는 PEM으로 인코딩된 객체를 담고 있는 문자열이다.\nsignature
는 'binary'
, 'hex'
, 'base64'
가 될 수 있는 signature_format
의\n데이터에 대해 이전에 계산한 서명이다.\n인코딩을 지정하지 않으면 버퍼라고 가정한다.\n\n
데이터와 공개키에 대한 서명의 유효성에 따라 true나 false를 반환한다.\n\n
\nNote: verifier
객체는 verify()
메서드를 호출한 뒤에는 사용할 수 없다.\n\n
Diffie-Hellman 키 교환을 생성하는 클래스이다.\n\n
\ncrypto.createDiffieHellman
가 반환하는 클래스이다.\n\n
개인 Diffie-Hellman 키값과 공개 Diffie-Hellman 키값을 생성하고 지정한 인코딩으로\n공개키를 반환한다. 이 키는 다른 관련자에게 이동할 수 있다. 인코딩은 'binary'
,\n'hex'
, 'base64'
가 될 수 있다.\n인코딩을 지정하지 않으면 버퍼를 반환한다.\n\n
다른 관련자의 공개키로 other_public_key
를 사용하는 공유 시크릿을 계산하고 계산된\n공유 시크릿을 반환한다. 제공된 키는 지정한 input_encoding
를 사용해서 해석된다. 시크릿은\n지정한 output_encoding
을 사용하서 인코딩된다. 인코딩은 'binary'
, 'hex'
,\n'base64'
가 될 수 있고 입력 인코딩을 지정하지 않으면 버퍼로 간주한다.\n\n
출력인코딩을 지정하지 않으면 버퍼를 반환한다.\n\n
\n", "signatures": [ { "params": [ { "name": "other_public_key" }, { "name": "input_encoding", "optional": true }, { "name": "output_encoding", "optional": true } ] } ] }, { "textRaw": "diffieHellman.getPrime([encoding])", "type": "method", "name": "getPrime", "desc": "'binary'
, 'hex'
, 'base64'
가 될 수 있는 지정한 인코딩의 Diffie-Hellman 소수를\n반환한다. 인코딩을 지정하지 않으면 버퍼를 반환한다.\n\n
'binary'
, 'hex'
, 'base64'
가 될 수 있는 지정한 인코딩의 Diffie-Hellman 제너레이터를\n반환한다. 인코딩을 지정하지 않으면 버퍼를 반환한다.\n\n
'binary'
, 'hex'
, 'base64'
가 될 수 있는 지정한 인코딩의 Diffie-Hellman 공개키를\n반환한다. 인코딩을 지정하지 않으면 버퍼를 반환한다.\n\n
'binary'
, 'hex'
, 'base64'
가 될 수 있는 지정한 인코딩의 Diffie-Hellman 개인키를\n반환한다. 인코딩을 지정하지 않으면 버퍼를 반환한다.\n\n
Diffie-Hellman 공개키를 설정한다. 키 인코딩은 'binary'
, 'hex'
, 'base64'
가\n될 수 있다. 인코딩을 지정하지 않으면 버퍼로 간주한다.\n\n
Diffie-Hellman 개인키를 설정한다. 키 인코딩은 'binary'
, 'hex'
, 'base64'
가\n될 수 있다. 인코딩을 지정하지 않으면 버퍼로 간주한다.\n\n
문자열이나 버퍼를 받을 수 있는 함수에 사용하는 기본 인코딩. 기본값은 Buffer 객체를 사용하는\n'buffer'
이다. crypto 모듈을 기본 인코딩으로 'binary'
를 사용하는 레거시 프로그램과\n쉽게 호환성을 맞출 수 있다.\n\n
새로운 프로그램은 버퍼를 기대할 것이므로 임시적으로만 이 값을 사용해라.\n\n
\n" } ], "modules": [ { "textRaw": "Recent API Changes", "name": "recent_api_changes", "desc": "Crypto 모듈은 통일된 Stream API의 개념과 바이너리 데이터를 다루는 Buffer 객체가\n존재하기 전에 Node에 추가되었다.\n\n
\n그래서 다른 Node 클래스들에는 있는 일반적인 메서드가 스트리밍 클래스에는 없고 많은 메서드들이\nBuffers 대신 기본적으로 바이너리로 인코딩된 문자열을 받아들이고 반환한다.\n이는 기본적으로 Buffer를 대신 사용하도록 바뀌었다.\n\n
\n이 변경사항은 전부는 아니지만 일부에서는 호환성을 깨뜨릴 것이다.\n\n
\n예를 들어 현재 Sign 클래스에 기본 인자를 사용하고 그 결과를 Verify 클래스에 전달하고\n데이터를 검사하지 않는다면 이전과 마차가지로 계속 동작할 것이다.\n바이너리 문자열을 얻고 Verify 객체에 바이너리 문자열을 제공하는 곳에서\nBuffer를 얻을 것이고 Verify 객체에 Buffer를 제공할 것이다.\n\n
\n하지만 Buffers에서 제대로 동작하지 않을 문자열 데이터로 어떤 작업을 한거나(문자열을\n이어붙힌다거나 데이터베이스에 저장하는 등) 인코딩 인자없이 암호화함수에 바이너리 문자열을\n전달한다면 사용하고자 하는 인코딩을 지정하는 인코딩 인자를 제공해야 할 것이다.\n기본적으로 바이너리 문자열을 사용하는 이전 방식으로 변경하려면\ncrypto.DEFAULT_ENCODING
필드를 'binary'로 설정해라.\n새로운 프로그램은 버퍼를 기대할 것이므로 이는 임시적으로만 사용해라.\n\n\n
이 모듈에 접근하려면 require('tls')
를 사용해라.\n\n
tls
모듈은 TLS(Transport Layer Security)나 SSL(Secure Socket Layer)을\n제공하는데 OpenSSL을 사용한다: 암호화된 스트림 통신\n\n
TLS/SSL는 공개키/개인키 기반이다. 각 클라이언트와 서버는 개인키를 반드시 가지고\n있어야 한다. 개인키는 다음과 같이 생성한다.\n\n
\nopenssl genrsa -out ryans-key.pem 1024
\n모든 서버와 몇몇 클라이언트는 인증서를 가질 필요가 있다. 인증서는 인증기관(Certificate\nAuthority)이나 자체서명으로 서명된 공개키이다. "인증서 서명 요청(Certificate Signing\nRequest)" (CSR) 파일을 생성하는 것이 인증서를 얻는 첫 단계이다. 다음과 같이 실행한다.\n\n
\nopenssl req -new -key ryans-key.pem -out ryans-csr.pem
\nCSR로 자체서명 인증서를 생성하려면 다음과 같이 한다.\n\n
\nopenssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem
\n아니면 서명을 위해서 인증기관(Certificate Authority)에 CSR을 보낼 수 있다.\n\n
\n(TODO: CA를 생성하는 문서에 관심이 있느 사용자들은 Node 소스크도의\ntest/fixtures/keys/Makefile
를 봐야한다.)\n\n
다음과 같이 실행해서 .pfx나 .p12를 생성한다.\n\n
\nopenssl pkcs12 -export -in agent5-cert.pem -inkey agent5-key.pem \\\n -certfile ca-cert.pem -out agent5.pfx
\nin
: 인증서inkey
: 개인키certfile
: cat ca1-cert.pem ca2-cert.pem > ca-cert.pem
와 같이 모든\nCA 인증서를 하나의 파일로 연결한다.TLS 프로토콜는 클라이언트가 TLS 세션의 어떤 관점을 재협상하게 한다. 불행히도 세션 재협상은\nDoS(denial-of-service) 공격의 잠재적인 요소인 서버측 리소스의 양의 불균형을 야기시킨다.\n\n
\n이를 완화시키려면 재현상을 10분내에 3번으로 제한해야 한다. 이 한계를 넘어서면\n[CleartextStream][] 인스턴스에서 오류가 발생한다. 이 제한은\n설정할 수 있다.\n\n
\ntls.CLIENT_RENEG_LIMIT
: 재협상 제한, 기본값은 3이다.
tls.CLIENT_RENEG_WINDOW
: 초단위의 재협상 시간, 기본값은
10 분이다.
\n무엇을 하는지 알지 못하면 기본값을 바꾸지 마라.\n\n
\n서버를 테스트하려면 openssl s_client -connect address:port
로 서버에 연결한 뒤\nR<CR>
(R
문자 뒤에 캐리지리턴)을 몇번 입력한다.\n\n\n
NPN (Next Protocol Negotiation)와 SNI (Server Name Indication)는 TLS\n핸드쉐이크 확장이다.\n\n
\n지원하는 SSL 암호 이름의 배열을 반환한다.\n\n
\n예제:\n\n
\nvar ciphers = tls.getCiphers();\nconsole.log(ciphers); // ['AES128-SHA', 'AES256-SHA', ...]
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "tls.createServer(options, [secureConnectionListener])",
"type": "method",
"name": "createServer",
"desc": "새로운 [tls.Server][]를 생성한다.\nconnectionListener
아규먼트는 자동적으로 [secureConnection][]\n이벤트의 리스너로 설정된다.\noptions
객체는 다음과 같은 선택사항이 있다.\n\n
pfx
: PFX나 PKCS12 형식으로 개인키, 인증서, 서버의 CA 인증서를 담고 있는\n문자열이나 Buffer
다. (key
, cert
, ca
옵셩은 상호배타적이다.)
key
: PEM 형식의 서버 개인키를 담고 있는 문자열이나 Buffer
다. (필수사항)
passphrase
: 개인키나 pfx에 대한 암호문의 문자열이다.
cert
: PEM 형식의 서버 인증키를 담고 있는 문자열이나 Buffer
다. (필수사항)
ca
: 신뢰할 수 있는 인증서의 문자열이나 Buffer
배열이다. 이 옵션을 생락하면\n각각 VeriSign처럼 잘 알려진 "루트" CA를 사용할 것이다. 연결에 권한을 부여하는 데\n이것들을 사용한다.
crl
: PEM으로 인코딩된 CRL(Certificate Revocation List)의 문자열이나 문자열의\n리스트
ciphers
: 사용하거나 제외할 암호(cipher)를 설명하는 문자열이다.
[BEAST attacks]을 완화시키려면 CBC가 아닌 암호문을 우선시하도록 아래에서 설명할\nhonorCipherOrder
을 이 옵션과 함께 사용하기를 권장한다.
기본값은\nAES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH
이다.\n형식에 대해 자세히 알고 싶으면 [OpenSSL cipher list format documentation]를 참고해라.\nECDH (Elliptic Curve Diffie-Hellman) 암호화는 아직 지원하지 않는다.
node.js가 OpenSSL 1.0.1이나 그 상위 버전과 연결되었을 때 AES128-GCM-SHA256
를\n사용하고 클라이언트는 TLS 1.2, RC4을 안전한 폴백(fallback)으로 사용한다.
NOTE: 이 섹션의 이전 버전에서는 AES256-SHA
를 괜찮은 암호문으로 제안했었다. 하지만\nAES256-SHA
는 CBC 암호문이므로 BEAST attacks을 받기 쉽다. AES256-SHA
를\n사용하지 말아라.
handshakeTimeout
: SSL/TLS 핸드쉐이크가 이 밀리초내에 끝나지 않으면 연결을 겨부한다.\n기본값은 120초이다.
핸드쉐이크가 타임아웃될 때마다 tls.Server
객체에서 'clientError'
가 발생한다.
honorCipherOrder
: 암호문을 선택할 때 클라이언트의 설정대신에 서버의 설정을 사용해라.
SSLv2을 사용한다면 서버는 클라이언트로 설정리스트를 보낼 것이고 클라이언트가 암호문을\n선택한다.
\n이 옵션은 기본적으로는 사용안함으로 되어 있지만 BEAST attacks을 완화하려면 ciphers
\n옵션과 함께 이 옵션을 사용하기를 권장한다.
requestCert
: true
로 지정하면 연결할 때 서버가 클라이언트한테 인증서를 요청하고\n인증서를 검증하는 데 사용할 것이다. 기본값: false
.
rejectUnauthorized
: true
로 지정하면 제공된 CA 목록에서 인가되지 않은\n모든 연결을 서버가 거절할 것이다. 이 옵션은 requestCert
가 true
일때만 유효하다.\n기본값: false
.
NPNProtocols
: 사용가능한 NPN 프로토콜의 배열이나 Buffer
다. (프로토콜은\n우선순위에 따라 정렬되어야 한다.)
SNICallback
: 클라이언트가 SNI TLS 확장을 지원하는 경우 호출될 함수다. 이 함수는\n단 하나의 아규먼트인 servername
만 받는다. 그리고 SNICallback
는 SecureContext\n인스턴스를 반환해야 한다.\n(적합한 SecureContext를 얻으려면 crypto.createCredentials(...).context
를\n사용할 수 있다.) SNICallback
를 제공하지 않으면 고수준 API와 함께 기본 콜백을\n사용할 것이다.(아래를 참고해라.)
sessionIdContext
: 세션 회수를 위한 불투명한 식별자를 담고 있는 문자열이다.\nrequestCert
가 true
이면 기본값은 커맨드라인에서 생성한 MD5 해시값이다.\nrequestCert
가 true
가 아니면 기본값은 제공하지 않는다.
secureProtocol
: 사용할 SSL 방식. 예를 들어 SSL 버전 3을 사용하려면\nSSLv3_method
이다. 사용가능한 값은 설치한 OpenSSL에 따라 다르고\n상수 [SSL_METHODS][]에 정의되어 있다.
간단한 에코(echo) 서버의 예제다.\n\n
\nvar tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n key: fs.readFileSync('server-key.pem'),\n cert: fs.readFileSync('server-cert.pem'),\n\n // This is necessary only if using the client certificate authentication.\n requestCert: true,\n\n // This is necessary only if the client uses the self-signed certificate.\n ca: [ fs.readFileSync('client-cert.pem') ]\n};\n\nvar server = tls.createServer(options, function(cleartextStream) {\n console.log('server connected',\n cleartextStream.authorized ? 'authorized' : 'unauthorized');\n cleartextStream.write("welcome!\\n");\n cleartextStream.setEncoding('utf8');\n cleartextStream.pipe(cleartextStream);\n});\nserver.listen(8000, function() {\n console.log('server bound');\n});
\n또는\n\n
\nvar tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n pfx: fs.readFileSync('server.pfx'),\n\n // This is necessary only if using the client certificate authentication.\n requestCert: true,\n\n};\n\nvar server = tls.createServer(options, function(cleartextStream) {\n console.log('server connected',\n cleartextStream.authorized ? 'authorized' : 'unauthorized');\n cleartextStream.write("welcome!\\n");\n cleartextStream.setEncoding('utf8');\n cleartextStream.pipe(cleartextStream);\n});\nserver.listen(8000, function() {\n console.log('server bound');\n});
\nopenssl s_client
로 서버에 접속해서 테스트할 수 있다.\n\n\n
openssl s_client -connect 127.0.0.1:8000
\n",
"signatures": [
{
"params": [
{
"name": "options"
},
{
"name": "secureConnectionListener",
"optional": true
}
]
}
]
},
{
"textRaw": "tls.connect(options, [callback])",
"type": "method",
"name": "connect",
"desc": "전달한 port
와 host
로(과거 API) 혹은 options.port
와 options.host
로\n새로운 클라이언트 연결을 생성한다. (host
를 지정하지 않으면\n기본값은 localhost
이다.) options
는 지정된 객체여야 한다.\n\n
host
: 클라이언트가 접속할 호스트
port
: 클라이언트가 접속할 포트
socket
: 새로운 소켓을 생성하는 대신 전달한 소켓으로 안전한 연결을 만든다.\n이 옵션을 지정하면 host
와 port
은 무시한다.
pfx
: PFX나 PKCS12 형식으로 개인키, 인증서 서버의 CA 인증서를 담고 있는 문자열이나\nBuffer
다.
key
: PEM 형식으로 클라이언트의 개인키를 담고 있는 문자열이나 Buffer
다.
passphrase
: 개인키나 pfx에 대한 암호문 문자열이다.
cert
: PEM 형식으로 클라이언트의 인증서 키를 담고 있는 문자열이나 Buffer
다.
ca
: 신뢰할 수 있는 인증서의 문자열이나 Buffer
배열이다. 이 옵션을 생락하면\n각각 VeriSign처럼 잘 알려진 "루트" CA를 사용할 것이다. 연결에 권한을 부여하는 데\n이것들을 사용한다.
rejectUnauthorized
: 이 값이 true
이면 서버 인증서를 제공한 CA 리스트로 검증한다.\n검증에 실패하면 'error'
이벤트가 발생한다. 기본값: true
.
NPNProtocols
: 지원하는 NPN 프로토콜의 배열이나 Buffer
다. Buffer
는 다음의\n형식이어야 한다. 0x05hello0x05world
, 첫 바이트는 next protocol name의\n길이이다.(배열을 전달하는 것이 보통 훨씬 간단할 것이다: ['hello', 'world']
)
servername
: SNI (Server Name Indication) TLS 확장에 대한 Servername이다.
secureProtocol
: 사용할 SSL 방식. 예를 들어 SSL 버전 3을 사용하려면\nSSLv3_method
이다. 사용가능한 값은 설치한 OpenSSL에 따라 다르고\n상수 [SSL_METHODS][]에 정의되어 있다.
callback
파라미터는 ['secureConnect'][]\n이벤트의 리스너로 추가할 것이다.\n\n
tls.connect()
는 [CleartextStream][] 객체를 반환한다.\n\n
앞에서 설명한 에코 서버의 클라이언트 예제다.\n\n
\nvar tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n // These are necessary only if using the client certificate authentication\n key: fs.readFileSync('client-key.pem'),\n cert: fs.readFileSync('client-cert.pem'),\n\n // This is necessary only if the server uses the self-signed certificate\n ca: [ fs.readFileSync('server-cert.pem') ]\n};\n\nvar cleartextStream = tls.connect(8000, options, function() {\n console.log('client connected',\n cleartextStream.authorized ? 'authorized' : 'unauthorized');\n process.stdin.pipe(cleartextStream);\n process.stdin.resume();\n});\ncleartextStream.setEncoding('utf8');\ncleartextStream.on('data', function(data) {\n console.log(data);\n});\ncleartextStream.on('end', function() {\n server.close();\n});
\n또는\n\n
\nvar tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n pfx: fs.readFileSync('client.pfx')\n};\n\nvar cleartextStream = tls.connect(8000, options, function() {\n console.log('client connected',\n cleartextStream.authorized ? 'authorized' : 'unauthorized');\n process.stdin.pipe(cleartextStream);\n process.stdin.resume();\n});\ncleartextStream.setEncoding('utf8');\ncleartextStream.on('data', function(data) {\n console.log(data);\n});\ncleartextStream.on('end', function() {\n server.close();\n});
\n",
"signatures": [
{
"params": [
{
"name": "port"
},
{
"name": "host",
"optional": true
},
{
"name": "options",
"optional": true
},
{
"name": "callback",
"optional": true
}
]
},
{
"params": [
{
"name": "options"
},
{
"name": "callback",
"optional": true
}
]
}
]
},
{
"textRaw": "tls.connect(port, [host], [options], [callback])",
"type": "method",
"name": "connect",
"desc": "전달한 port
와 host
로(과거 API) 혹은 options.port
와 options.host
로\n새로운 클라이언트 연결을 생성한다. (host
를 지정하지 않으면\n기본값은 localhost
이다.) options
는 지정된 객체여야 한다.\n\n
host
: 클라이언트가 접속할 호스트
port
: 클라이언트가 접속할 포트
socket
: 새로운 소켓을 생성하는 대신 전달한 소켓으로 안전한 연결을 만든다.\n이 옵션을 지정하면 host
와 port
은 무시한다.
pfx
: PFX나 PKCS12 형식으로 개인키, 인증서 서버의 CA 인증서를 담고 있는 문자열이나\nBuffer
다.
key
: PEM 형식으로 클라이언트의 개인키를 담고 있는 문자열이나 Buffer
다.
passphrase
: 개인키나 pfx에 대한 암호문 문자열이다.
cert
: PEM 형식으로 클라이언트의 인증서 키를 담고 있는 문자열이나 Buffer
다.
ca
: 신뢰할 수 있는 인증서의 문자열이나 Buffer
배열이다. 이 옵션을 생락하면\n각각 VeriSign처럼 잘 알려진 "루트" CA를 사용할 것이다. 연결에 권한을 부여하는 데\n이것들을 사용한다.
rejectUnauthorized
: 이 값이 true
이면 서버 인증서를 제공한 CA 리스트로 검증한다.\n검증에 실패하면 'error'
이벤트가 발생한다. 기본값: true
.
NPNProtocols
: 지원하는 NPN 프로토콜의 배열이나 Buffer
다. Buffer
는 다음의\n형식이어야 한다. 0x05hello0x05world
, 첫 바이트는 next protocol name의\n길이이다.(배열을 전달하는 것이 보통 훨씬 간단할 것이다: ['hello', 'world']
)
servername
: SNI (Server Name Indication) TLS 확장에 대한 Servername이다.
secureProtocol
: 사용할 SSL 방식. 예를 들어 SSL 버전 3을 사용하려면\nSSLv3_method
이다. 사용가능한 값은 설치한 OpenSSL에 따라 다르고\n상수 [SSL_METHODS][]에 정의되어 있다.
callback
파라미터는 ['secureConnect'][]\n이벤트의 리스너로 추가할 것이다.\n\n
tls.connect()
는 [CleartextStream][] 객체를 반환한다.\n\n
앞에서 설명한 에코 서버의 클라이언트 예제다.\n\n
\nvar tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n // These are necessary only if using the client certificate authentication\n key: fs.readFileSync('client-key.pem'),\n cert: fs.readFileSync('client-cert.pem'),\n\n // This is necessary only if the server uses the self-signed certificate\n ca: [ fs.readFileSync('server-cert.pem') ]\n};\n\nvar cleartextStream = tls.connect(8000, options, function() {\n console.log('client connected',\n cleartextStream.authorized ? 'authorized' : 'unauthorized');\n process.stdin.pipe(cleartextStream);\n process.stdin.resume();\n});\ncleartextStream.setEncoding('utf8');\ncleartextStream.on('data', function(data) {\n console.log(data);\n});\ncleartextStream.on('end', function() {\n server.close();\n});
\n또는\n\n
\nvar tls = require('tls');\nvar fs = require('fs');\n\nvar options = {\n pfx: fs.readFileSync('client.pfx')\n};\n\nvar cleartextStream = tls.connect(8000, options, function() {\n console.log('client connected',\n cleartextStream.authorized ? 'authorized' : 'unauthorized');\n process.stdin.pipe(cleartextStream);\n process.stdin.resume();\n});\ncleartextStream.setEncoding('utf8');\ncleartextStream.on('data', function(data) {\n console.log(data);\n});\ncleartextStream.on('end', function() {\n server.close();\n});
\n",
"signatures": [
{
"params": [
{
"name": "port"
},
{
"name": "host",
"optional": true
},
{
"name": "options",
"optional": true
},
{
"name": "callback",
"optional": true
}
]
}
]
},
{
"textRaw": "tls.createSecurePair([credentials], [isServer], [requestCert], [rejectUnauthorized])",
"type": "method",
"name": "createSecurePair",
"desc": "두 스트림으로 새 안전한 쌍(pair) 객체를 생성한다. 두 스트림 중 하나는 암호화된 데이터를\n읽고 쓰고 다른 하나는 평문 데이터를 읽고 쓴다.\n보통 암호화된 쪽은 들어오는 암호화된 데이터 스트림에 파이프로 연결되고 평문 쪽은 초기\n암호화 스트림에 대한 대체용으로 사용된다.\n\n
\ncredentials
: crypto.createCredentials( ... )의 증명서 객체
isServer
: 이 tls 연결이 서버나 클라이언트로써 열려야 하는지를 나타내는 불리언값이다.
requestCert
: 서버가 연결하는 클라이언트에서 인증서를 요구해야 하는지 나타내는 불리언\n값이다. 서버 연결에만 적용된다.
rejectUnauthorized
: 서버가 유효하지 않은 인증서를 가진 클라이언트를 자동으로 거절할\n것인지 나타내는 불리언 값이다. requestCert
를 사용하는 서버에만 적용된다.
tls.createSecurePair()
는 [cleartext][]와 encrypted
스트림 프로퍼티로\nSecurePair 객체를 반환한다.\n\n
모든 tls 서버와 클라이언트가 사용하는 슬랩(slab) 버퍼의 크기\n기본값: 10 * 1024 * 1024
.\n\n\n
무슨 작업을 하는지 알지 못한다면 기본값을 바꾸지 말아라.\n\n\n
\n" } ], "classes": [ { "textRaw": "Class: SecurePair", "type": "class", "name": "SecurePair", "desc": "tls.createSecurePair가 반환하는 클래스다.\n\n
\n", "events": [ { "textRaw": "Event: 'secure'", "type": "event", "name": "secure", "desc": "쌍이 성공적으로 안전한 연결을 수립했을 때 SecurePair가 발생시키는 이벤트이다.\n\n
\n서버의 'secureConnection' 이벤트를 확인하는 것과 비슷하게 pair.cleartext.authorized는\n사용된 인증서가 제대로 권한을 부여받았는지 승인하기 위해 확인되어야 한다.\n\n
\n", "params": [] } ] }, { "textRaw": "Class: tls.Server", "type": "class", "name": "tls.Server", "desc": "net.Server
의 하위클래스이고 net.Server
와 같은 메서드를 가진다.\n그냥 로우(raw) TCP 연결을 받아들이는 대신 TLS나 SSL을 사용해서 암호화된 연결을\n받아들인다.\n\n
function (cleartextStream) {}
\n\n
새로운 연결이 성공적으로 핸드쉐이크를 했을 때 발생하는 이벤트이다. 아규먼트는\nCleartextStream 인스턴스다. 이 인스턴스는 공통 스트림 메서드와\n이벤트를 모두 갖고 있다.\n\n
\ncleartextStream.authorized
는 서버에 대해 제공된 인증서 권한 중 하나로 클라이언트가\n검증되었는지 나타내는 불리언 값이다. cleartextStream.authorized
가 false이면\ncleartextStream.authorizationError
는 어떻게 권한부여가 실패했는 지를 알려주기 위해\n설정된다. TLS 서버의 설정에 따라 권한이 부여되지 않은 연결을 받아들일 수 있다는 점을 알아두어야\n한다. cleartextStream.npnProtocol
는 선택된 NPN 프로토콜을 담고 있는 문자열이다.\ncleartextStream.servername
은 SNI로 요청된 servername을 담고 있는 문자열이다.\n\n\n
function (exception, securePair) { }
\n\n
안전한 연결이 이뤄지기 전에 클라이언트 연결이 'error' 이벤트를 발생시켰을 때 발생하는\n이벤트다.\n\n
\nsecurePair
는 오류가 발생한 tls.SecurePair
이다.\n\n\n
function (sessionId, sessionData) { }
\n\n
TLS 세션을 생성했을 때 발생한다. 외부 스토리지에 세션을 저장할 때 사용할 것이다.\n\n\n
\n", "params": [] }, { "textRaw": "Event: 'resumeSession'", "type": "event", "name": "resumeSession", "desc": "function (sessionId, callback) { }
\n\n
클라이언트가 이전의 TLS 세션을 되찾고자 할 때 발생한다. 이벤트 리스너는 주어진 sessionId
를\n사용해서 외부 스토리지에서 검색하고 검색이 완료되면 callback(null, sessionData)
를 호출할\n것이다. 세션을 되찾을 수 없다면(예: 스토리지에 존재하지 않는 경우) callback(null, null)
를\n호출할 것이다. callback(err)
를 호출하면 들어오는 요청을 종료시키고 소켓을 제거할 것이다.\n\n\n
지정한 port
와 host
로 연결을 받아들이기 시작한다. host
를 생략하면 서버는 모든\nIPv4 주소(INADDR_ANY
)에서 직접 연결을 받아들일 것이다.\n\n
이 함수는 비동기함수이다. 마지막 파라미터인 callback
는 서버의 바인딩이 완료되었을 때\n호출될 것이다.\n\n
더 자세한 내용은 net.Server
를 봐라.\n\n\n
서버가 새로운 연결을 받아들이는 것을 멈춤다. 이 함수는 비동기 함수이고 서버가 'close'
\n이벤트를 발생시켰을 때 결국 닫힌다.\n\n
운영체제에서 보고된 서버가 바인딩된 주소와 주소 패밀리이름과 포트를 반환한다.\n더 자세한 내용은 [net.Server.address()][]를 봐라.\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "server.addContext(hostname, credentials)", "type": "method", "name": "addContext", "desc": "클라이언트 요청의 SNI 호스트이름이 전달한 hostname
(와일드카드도 사용할 수 있다.)와\n일치하는 경우 사용할 안전한 컨텍스트를 추가한다. credentials
은 key
, cert
, ca
를\n포함할 수 있다.\n\n
서버의 연결수가 많아졌을 때 연결을 거절하려면 이 프로퍼티를 설정해라.\n\n
\n" }, { "textRaw": "server.connections", "name": "connections", "desc": "서버의 현재 연결 수\n\n\n
\n" } ] }, { "textRaw": "Class: CryptoStream", "type": "class", "name": "CryptoStream", "desc": "이는 암호화된 스트림이다.\n\n
\n", "properties": [ { "textRaw": "cryptoStream.bytesWritten", "name": "bytesWritten", "desc": "의존하는 소켓의 bytesWritten 접근자로의 프록시로 이는 소켓에 쓰여진 전체\n바이트(TLS 오버헤드를 포함해서)를 반환할 것이다.\n\n
\n" } ] }, { "textRaw": "Class: tls.CleartextStream", "type": "class", "name": "tls.CleartextStream", "desc": "평문 데이터와 같이 암호화된 데이터도 읽고 쓸 수 있도록 암호화된 스트림에 기반을 둔\n스트림이다.\n\n
\n이 인스턴스는 이중 Stream 인터페이스를 구현한다.\n이 인스턴스는 공통 스트림 메서드와 이벤트를 모두 가지고 있다.\n\n
\nClearTextStream는 SecurePair 객체의 clear
멤버이다.\n\n
새로운 연결이 성공적으로 핸드쉐이크를 했을 때 발생하는 이벤트이다.\n리스너는 서버의 인증서가 권한 부여를 받았는 지에 상관없이 호출될 것이다. 이는 서버 인증서가\n지정한 CA중의 하나로 서명되었는지를 보려고 cleartextStream.authorized
를 검사하는\n사용자에게 달려있다. cleartextStream.authorized === false
인 경우 오류는\ncleartextStream.authorizationError
에 있을 것이다. 또한 NPN이 사용되었다면 협상\n프로토콜을 위해 cleartextStream.npnProtocol
를 확인할 수 있다.\n\n
피어(peer) 인증서가 지정한 CA중에 하나로 서명되었으면 true
그렇지 않으면 false
인\n불리언이다.\n\n
왜 피어(peer)의 인증서가 검증되지 못했는지에 대한 내용이다. 이 프로퍼티는\ncleartextStream.authorized === false
인 경우에만 사용할 수 있다.\n\n
원격 IP 주소를 나타내는 문자열이다. 예를 들면 '74.125.127.100'
나\n'2001:4860:a005::68'
이다.\n\n
원격 포트르르 나태내는 숫자다. 예를 들면 443
.\n\n
피어(peer)의 인증서를 나타내는 객체를 반환한다. 반환된 객체는 인증서의 필드와 대응되는\n몇몇 프로퍼티를 가지고 있다.\n\n
\n예제:\n\n
\n{ subject:\n { C: 'UK',\n ST: 'Acknack Ltd',\n L: 'Rhys Jones',\n O: 'node.js',\n OU: 'Test TLS Certificate',\n CN: 'localhost' },\n issuer:\n { C: 'UK',\n ST: 'Acknack Ltd',\n L: 'Rhys Jones',\n O: 'node.js',\n OU: 'Test TLS Certificate',\n CN: 'localhost' },\n valid_from: 'Nov 11 09:52:22 2009 GMT',\n valid_to: 'Nov 6 09:52:22 2029 GMT',\n fingerprint: '2A:7A:C2:DD:E5:F9:CC:53:72:35:99:7A:02:5A:71:38:52:EC:8A:DF' }
\n피어(peer)가 인증서를 제공하지 않는다면 null
이나 비어있는 객체를 반환한다.\n\n
현재 연결의 암호문 이름과 SSL/TLS 프로토콜 버전을 나타내는 객체를\n반환한다.\n\n
\n예제:\n{ name: 'AES256-SHA', version: 'TLSv1/SSLv3' }\n\n
\n자세한 내용은\nhttp://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_CIPHERS 에서\nSSL_CIPHER_get_name()와 SSL_CIPHER_get_version()를 봐라.\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "cleartextStream.address()", "type": "method", "name": "address", "desc": "운영체제가 보고했듯이 기반하는 소켓의 바인딩된 주소와 주소 패밀리 이름과 포트를 반환한다.\n다음과 같이 세 가지 프로퍼티를 가진 객체를 반환한다.\n{ port: 12346, family: 'IPv4', address: '127.0.0.1' }
\n\n
이 모듈은 require('string_decoder')
로 사용한다. StringDecoder는 버퍼를\n문자열로 디코딩한다. buffer.toString()
의 간단한 인터페이스이지만 utf8에 대한\n추가적인 지원을 한다.\n\n
var StringDecoder = require('string_decoder').StringDecoder;\nvar decoder = new StringDecoder('utf8');\n\nvar cent = new Buffer([0xC2, 0xA2]);\nconsole.log(decoder.write(cent));\n\nvar euro = new Buffer([0xE2, 0x82, 0xAC]);\nconsole.log(decoder.write(euro));
\n",
"classes": [
{
"textRaw": "Class: StringDecoder",
"type": "class",
"name": "StringDecoder",
"desc": "기본값이 utf8
인 encoding
아규먼트를 받는다.\n\n
디코딩한 문자열을 반환한다.\n\n
\n", "signatures": [ { "params": [ { "name": "buffer" } ] } ] }, { "textRaw": "decoder.end()", "type": "method", "name": "end", "desc": "버퍼에 남아있는 바이트를 반환한다.\n\n
\n", "signatures": [ { "params": [] } ] } ] } ], "type": "module", "displayName": "StringDecoder" }, { "textRaw": "File System", "name": "fs", "stability": 3, "stabilityText": "Stable", "desc": "파일 I/O는 표준 POSIX 함수의 랩퍼(wrapper)로 제공된다. 이 모듈을 사용하려면\nrequire('fs')
를 사용해라. 모든 함수는 비동기 방식과 동기방식이 있다.\n\n
비동기 방식은 항상 마지막 파라미터로 완료 콜백함수를 받는다. 완료 콜백에 전달되는 함수는\n메서드에 따라 다르지만 첫 아규먼트는 항상 예외로 사용한다. 작업이 성공적으로 완료되면\n첫 아규먼트는 null
이나 undefined
가 될 것이다.\n\n
동기형식을 사용할 때는 모든 예외가 즉시 던져진다. try/catch를 사용해서 예외를\n다루거나 위로 버블링할 수 있다.\n\n
\n다음은 비동기 버전의 예제다.\n\n
\nvar fs = require('fs');\n\nfs.unlink('/tmp/hello', function (err) {\n if (err) throw err;\n console.log('successfully deleted /tmp/hello');\n});
\n다음은 동기버전이다.\n\n
\nvar fs = require('fs');\n\nfs.unlinkSync('/tmp/hello')\nconsole.log('successfully deleted /tmp/hello');
\n비동기 메서드를 사용할 때는 순서대로 실행된다는 보장을 하지 않는다. 그래서 다음\n예제는 오류가 날 수 있다.\n\n
\nfs.rename('/tmp/hello', '/tmp/world', function (err) {\n if (err) throw err;\n console.log('renamed complete');\n});\nfs.stat('/tmp/world', function (err, stats) {\n if (err) throw err;\n console.log('stats: ' + JSON.stringify(stats));\n});
\nfs.stat가
fs.rename`보다 먼저 실행될 수 있다.\n이에 대한 올바른 방법은 콜백 체인으로 연결하는 것이다.\n\n
fs.rename('/tmp/hello', '/tmp/world', function (err) {\n if (err) throw err;\n fs.stat('/tmp/world', function (err, stats) {\n if (err) throw err;\n console.log('stats: ' + JSON.stringify(stats));\n });\n});
\n프로세스가 바쁜 경우 프로그래머는 이러한 호출을 비동기 방식으로 사용하기를\n강력히 추천한다. 동기방식은 모든 연결을 멈추고 작업이 완료될 때까지\n전체 프로세스를 블락킹할 것이다.\n\n
\n파일명에 상대경로를 사용할 수 있지만 이 상대 경로는 process.cwd()
이 대한\n상대경로가 될 것이다.\n\n
대부분의 fs함수는 callback인자를 생략할 수 있게 한다. callback인자를 생략하면\n오류는 무시하지만 폐기(deprecation) 경고는 출력하는 기본 콜백을 사용한다.\n\n
\nIMPORTANT: 콜백 생략은 폐기되었다. v0.12는 기대하는대로 오류를 던질 것이다.\n\n\n
\n", "methods": [ { "textRaw": "fs.rename(oldPath, newPath, callback)", "type": "method", "name": "rename", "desc": "비동기 rename(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "oldPath" }, { "name": "newPath" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.renameSync(oldPath, newPath)", "type": "method", "name": "renameSync", "desc": "동기 rename(2).\n\n
\n", "signatures": [ { "params": [ { "name": "oldPath" }, { "name": "newPath" } ] } ] }, { "textRaw": "fs.ftruncate(fd, len, callback)", "type": "method", "name": "ftruncate", "desc": "동기 ftruncate(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "fd" }, { "name": "len" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.ftruncateSync(fd, len)", "type": "method", "name": "ftruncateSync", "desc": "동기 ftruncate(2).\n\n
\n", "signatures": [ { "params": [ { "name": "fd" }, { "name": "len" } ] } ] }, { "textRaw": "fs.truncate(path, len, callback)", "type": "method", "name": "truncate", "desc": "비동기 truncate(2). 발생할 수 있는 오류인자 외에 완료 콜백에 전달되는 인자는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "len" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.truncateSync(path, len)", "type": "method", "name": "truncateSync", "desc": "동기 truncate(2).\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "len" } ] } ] }, { "textRaw": "fs.chown(path, uid, gid, callback)", "type": "method", "name": "chown", "desc": "비동기 chown(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "uid" }, { "name": "gid" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.chownSync(path, uid, gid)", "type": "method", "name": "chownSync", "desc": "동기 chown(2).\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "uid" }, { "name": "gid" } ] } ] }, { "textRaw": "fs.fchown(fd, uid, gid, callback)", "type": "method", "name": "fchown", "desc": "비동기 fchown(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "fd" }, { "name": "uid" }, { "name": "gid" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.fchownSync(fd, uid, gid)", "type": "method", "name": "fchownSync", "desc": "동기 fchown(2).\n\n
\n", "signatures": [ { "params": [ { "name": "fd" }, { "name": "uid" }, { "name": "gid" } ] } ] }, { "textRaw": "fs.lchown(path, uid, gid, callback)", "type": "method", "name": "lchown", "desc": "비동기 lchown(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "uid" }, { "name": "gid" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.lchownSync(path, uid, gid)", "type": "method", "name": "lchownSync", "desc": "동기 lchown(2).\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "uid" }, { "name": "gid" } ] } ] }, { "textRaw": "fs.chmod(path, mode, callback)", "type": "method", "name": "chmod", "desc": "비동기 chmod(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "mode" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.chmodSync(path, mode)", "type": "method", "name": "chmodSync", "desc": "동기 chmod(2).\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "mode" } ] } ] }, { "textRaw": "fs.fchmod(fd, mode, callback)", "type": "method", "name": "fchmod", "desc": "비동기 fchmod(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "fd" }, { "name": "mode" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.fchmodSync(fd, mode)", "type": "method", "name": "fchmodSync", "desc": "동기 fchmod(2).\n\n
\n", "signatures": [ { "params": [ { "name": "fd" }, { "name": "mode" } ] } ] }, { "textRaw": "fs.lchmod(path, mode, callback)", "type": "method", "name": "lchmod", "desc": "비동기 lchmod(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\nMac OS X에서만 사용할 수 있다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "mode" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.lchmodSync(path, mode)", "type": "method", "name": "lchmodSync", "desc": "동기 lchmod(2).\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "mode" } ] } ] }, { "textRaw": "fs.stat(path, callback)", "type": "method", "name": "stat", "desc": "비동기 stat(2). 콜백은 두 아규먼트 (err, stats)
를 받고 stats
은\nfs.Stats 객체이다. 더 자세한 내용은 아래의\nfs.Stats부분을 봐라.\n\n
동기 lstat(2). 콜백은 두 아규먼트 (err, stats)
를 받고 stats
은 fs.Stats
객체다.\nlstat()
은 path
가 심볼릭 링크일 경우 참조하는 파일이 아닌 심볼릭 링크 자체의 상태라는\n점만 빼면 stat()
와 같다.\n\n
비동기 fstat(2). 콜백은 두 아규먼트 (err, stats)
를 받고 stats
은 fs.Stats
객체다.\nfstat()
은 상태를 확인하는 파일이 파일 디스크립터 fd
가 지정한 파일이라는 점만 빼면\nstat()
와 같다.\n\n
동기 stat(2). fs.Stats
인스턴스를 반환한다.\n\n
동기 lstat(2). fs.Stats
인스턴스를 반환한다.\n\n
동기 fstat(2). fs.Stats
인스턴스를 반환한다.\n\n
비동기 link(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "srcpath" }, { "name": "dstpath" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.linkSync(srcpath, dstpath)", "type": "method", "name": "linkSync", "desc": "동기 link(2).\n\n
\n", "signatures": [ { "params": [ { "name": "srcpath" }, { "name": "dstpath" } ] } ] }, { "textRaw": "fs.symlink(srcpath, dstpath, [type], callback)", "type": "method", "name": "symlink", "desc": "비동기 symlink(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\ntype
아규먼트는 'dir'
이나 'file'
, 'junction'
이 가능하다.(기본값은 'file'
이다) 이 옵션은\n윈도우에서만 사용된다.(다른 플랫폼에서는 무시한다.)\nWindows의 junction에서는 목적지경로가 절대경로여야 한다. 'junction'
을 사용하면 destination
\n아규먼트를 절대경로로 자동으로 정규화한다.\n\n
동기 symlink(2).\n\n
\n", "signatures": [ { "params": [ { "name": "srcpath" }, { "name": "dstpath" }, { "name": "type", "optional": true } ] } ] }, { "textRaw": "fs.readlink(path, callback)", "type": "method", "name": "readlink", "desc": "비동기 readlink(2). 콜백은 두 아규먼트 (err, linkString)
를 받는다.\n\n
동기 readlink(2). 심볼릭 링크의 문자열 값을 반환한다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" } ] } ] }, { "textRaw": "fs.realpath(path, [cache], callback)", "type": "method", "name": "realpath", "desc": "비동기 realpath(2). callback
은 두 개의 아규먼트 (err, resolvedPath)
를 받는다.\n상대경로를 처리하려면 process.cwd
를 사용해야 할 것이다. cache
는 실제 경로를 알기\n위해 지정한 경로 처리를 강제하거나 추가적인 fs.stat
호출을 피하기 위해 사용할 수 있는\n매핑된 경로의 객체리터럴이다.\n\n
예제:\n\n
\nvar cache = {'/etc':'/private/etc'};\nfs.realpath('/etc/passwd', cache, function (err, resolvedPath) {\n if (err) throw err;\n console.log(resolvedPath);\n});
\n",
"signatures": [
{
"params": [
{
"name": "path"
},
{
"name": "cache",
"optional": true
},
{
"name": "callback"
}
]
}
]
},
{
"textRaw": "fs.realpathSync(path, [cache])",
"type": "method",
"name": "realpathSync",
"desc": "동기 realpath(2). 처리된 경로를 반환한다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "cache", "optional": true } ] } ] }, { "textRaw": "fs.unlink(path, callback)", "type": "method", "name": "unlink", "desc": "비동기 unlink(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.unlinkSync(path)", "type": "method", "name": "unlinkSync", "desc": "동기 unlink(2).\n\n
\n", "signatures": [ { "params": [ { "name": "path" } ] } ] }, { "textRaw": "fs.rmdir(path, callback)", "type": "method", "name": "rmdir", "desc": "비동기 rmdir(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.rmdirSync(path)", "type": "method", "name": "rmdirSync", "desc": "동기 rmdir(2).\n\n
\n", "signatures": [ { "params": [ { "name": "path" } ] } ] }, { "textRaw": "fs.mkdir(path, [mode], callback)", "type": "method", "name": "mkdir", "desc": "비동기 mkdir(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\nmode
의 기본값은 0777
이다.\n\n
동기 mkdir(2).\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "mode", "optional": true } ] } ] }, { "textRaw": "fs.readdir(path, callback)", "type": "method", "name": "readdir", "desc": "비동기 readdir(3). 디렉토리의 내용을 읽는다.\n콜백은 두 아규먼트 (err, files)
를 받고 files
는 디렉토리에서 '.'
와 '..'
를\n제외한 파일명들의 배열이다.\n\n
동기 readdir(3). '.'
와 '..'
를 제외한 파일명들의 배열을 반환한다.\n\n
비동기 close(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "fd" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.closeSync(fd)", "type": "method", "name": "closeSync", "desc": "동기 close(2).\n\n
\n", "signatures": [ { "params": [ { "name": "fd" } ] } ] }, { "textRaw": "fs.open(path, flags, [mode], callback)", "type": "method", "name": "open", "desc": "비동기 파일 열기. open(2).를 봐라. flags
는 다음의 값이 될 수 있다.\n\n
'r'
- 읽기모드로 파일을 연다.\n파일이 존재하지 않으면 예외가 발생한다.
'r+'
- 읽기와 쓰기모드로 파일을 연다.\n(파일이 존재하지 않으면) 파일을 생성하거나 (파일이 존재하면) 새로 쓴다.
'rs'
- 동기방식으로 읽는 파일을 연다. 운영체제가 로컬 파일시스템 캐시를 우회하도록\n한다.
오래됐을 수도 있는 로컬 캐시를 무시하고 NFS 마운트에서 파일을 열 때 주고 유용하다.\n이 플래그는 I/O 성능에 실제로 큰 영향을 주기 때문에 필요한 경우가 아니면 사용하지\n말아야 한다.
\n이 모드는 fs.open()
를 동기적인 블락킹 호출로 바꾸지 않는다.\n동기적인 블락킹 호출이 필요하다면 fs.openSync()
를 사용해야 한다.
'rs+'
- 운영체제가 동기방식으로 일기와 쓰기모드로 파일을 열도록 한다. 이 모드를\n사용할 때의 주의점은 'rs'
를 봐라.
'w'
- 쓰기모드로 파일을 연다.\n(파일이 존재하지 않으면) 파일을 생성하거나 (파일이 존재하면) 새로 쓴다.
'wx'
- 'w'
와 비슷하지만 path
가 존재하면 실패한다.
'w+'
- 읽기와 쓰기모드로 파일을 연다.\n(파일이 존재하지 않으면) 파일을 생성하거나 (파일이 존재하면) 새로 쓴다.
'wx+'
- 'w+'
와 비슷하지만 path
가 존재하면 실패한다.
'a'
- 추가모드로 파일을 연다.\n파일이 존재하지 않으면 예외가 발생한다.
'ax'
- 'a'
와 비슷하지만 path
가 존재하면 실패한다.
'a+'
- 읽기와 추가모드로 파일을 연다.\n파일이 존재하지 않으면 예외가 발생한다.
'ax+'
- 'a+'
와 비슷하지만 path
가 존재하면 실패한다.
mode
는 파일을 생성할 때만 파일모드(권한과 스티키비트(sticky bits))를 설정한다.\n기본값은 0666
이며 읽고 쓸 수 있다.\n\n
콜백은 두 아규먼트 (err, fd)
를 받는다.\n\n
독점 모드 'x'
(open(2)의 O_EXCL
플래그)는 새로 path
를 생성한다는 것을 보장한다.\nPOSIX 시스템에서 존재하지 않는 파일에 대한 심볼릭 링크도 path
가 존재하는 것으로 간주한다.\n네트워크 파일 시스템에서 독점 모드는 동작할 수도 있고 동작하지 않을 수도 있다.\n\n
리눅스에서는 추가(append) 모드로 파일을 열었을 경우 위치 쓰기(positional write)가 동작하지\n않는다. 커널이 위치 인자를 무시하고 항상 파일 끝에 데이터를 추가한다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "flags" }, { "name": "mode", "optional": true }, { "name": "callback" } ] } ] }, { "textRaw": "fs.openSync(path, flags, [mode])", "type": "method", "name": "openSync", "desc": "fs.open()
의 동기버전\n\n
전달한 경로가 참조하는 파일의 타임스탬프를 변경한다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "atime" }, { "name": "mtime" } ] }, { "params": [ { "name": "path" }, { "name": "atime" }, { "name": "mtime" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.utimesSync(path, atime, mtime)", "type": "method", "name": "utimesSync", "desc": "전달한 경로가 참조하는 파일의 타임스탬프를 변경한다.\n\n
\n", "signatures": [ { "params": [ { "name": "path" }, { "name": "atime" }, { "name": "mtime" } ] } ] }, { "textRaw": "fs.futimes(fd, atime, mtime, callback)", "type": "method", "name": "futimes", "desc": "전달한 파일 디스크립터가 참조하는 파일의 타임스탬프를 변경한다.\n\n
\n", "signatures": [ { "params": [ { "name": "fd" }, { "name": "atime" }, { "name": "mtime" } ] }, { "params": [ { "name": "fd" }, { "name": "atime" }, { "name": "mtime" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.futimesSync(fd, atime, mtime)", "type": "method", "name": "futimesSync", "desc": "전달한 파일 디스크립터가 참조하는 파일의 타임스탬프를 변경한다.\n\n
\n", "signatures": [ { "params": [ { "name": "fd" }, { "name": "atime" }, { "name": "mtime" } ] } ] }, { "textRaw": "fs.fsync(fd, callback)", "type": "method", "name": "fsync", "desc": "비동기 fsync(2). 전달한 완료콜백에는 예외 아규먼트 외에 다른 아규먼트는 없다.\n\n
\n", "signatures": [ { "params": [ { "name": "fd" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.fsyncSync(fd)", "type": "method", "name": "fsyncSync", "desc": "동기 fsync(2).\n\n
\n", "signatures": [ { "params": [ { "name": "fd" } ] } ] }, { "textRaw": "fs.write(fd, buffer, offset, length, position, callback)", "type": "method", "name": "write", "desc": "fd
가 지정한 파일에 buffer
를 작성한다.\n\n
offset
과 length
는 작성할 버퍼의 부분을 결정한다.\n\n
position
은 이 데이터를 작성해야할 파일의 시작 위치부터의 오프셋을 참조한다. position
이\nnull
이면 데이터는 현재 위치에 작성할 것이다.\npwrite(2)를 봐라.\n\n
콜백은 세 아규먼트 (err, written, buffer)
를 받고 written
는 buffer
에서\n얼마나 많은 바이트가 작성되었는 지를 가리킨다.\n\n
콜백을 기다리지 않고 같은 파일에 여러번 fs.write
를 사용하는 것은 안전하지 않다. 이 경우에\nfs.createWriteStream
를 사용하기를 강력하게 추천한다.\n\n
리눅스에서는 추가(append) 모드로 파일을 열었을 경우 위치 쓰기(positional write)가 동작하지\n않는다. 커널이 위치 인자를 무시하고 항상 파일 끝에 데이터를 추가한다.\n\n
\n", "signatures": [ { "params": [ { "name": "fd" }, { "name": "buffer" }, { "name": "offset" }, { "name": "length" }, { "name": "position" }, { "name": "callback" } ] } ] }, { "textRaw": "fs.writeSync(fd, buffer, offset, length, position)", "type": "method", "name": "writeSync", "desc": "fs.write()
의 동기 버전. 작성한 바이트 수를 반환한다.\n\n
fd
가 지정한 파일에서 데이터를 읽는다.\n\n
buffer
는 데이터가 작성될 버퍼이다.\n\n
offset
은 버퍼내에서 쓰기 시작할 오프셋이다.\n\n
length
는 읽어들일 바이트 수를 지정하는 정수이다.\n\n
position
은 파일에서 읽어들이기 시작하는 위치를 지정하는 정수이다.\nposition
가 null
이면 데이터는 파일의 현재 위치에서 읽을 것이다.\n\n
콜백은 세 아규먼트 (err, bytesRead, buffer)
를 받는다.\n\n
fs.read
의 동기 버전이다. bytesRead
의 수를 반환한다.\n\n
파일의 전체 내용을 비동기로 읽는다. 예제:\n\n
\nfs.readFile('/etc/passwd', function (err, data) {\n if (err) throw err;\n console.log(data);\n});
\n콜백에는 두 아규먼트 (err, data)
를 전달하고 data
는 파일의 내용이다.\n\n
인코딩을 지정하지 않으면 로우(raw) 버퍼를 반환한다.\n\n\n
\n" }, { "textRaw": "fs.readFileSync(filename, [options])", "type": "method", "name": "readFileSync", "desc": "fs.readFile
의 동기버전이다. filename
의 내용을 반환한다.\n\n
encoding
옵션을 지정하면 이 함수는 문자열을 반환하고 encoding
을 지정하지 않으면\n버퍼를 반환한다.\n\n\n
비동기로 파일에 데이터를 작성하고 파일이 이미 존재하는 경우에는 파일을 대체한다.\ndata
는 문자열이나 버퍼가 될 수 있다.\n\n
data
가 버퍼일 경우 encoding
옵션은 무시한다. encoding
의\n기본값은 'utf8'
이다.\n\n
예제:\n\n
\nfs.writeFile('message.txt', 'Hello Node', function (err) {\n if (err) throw err;\n console.log('It\\'s saved!');\n});
\n"
},
{
"textRaw": "fs.writeFileSync(filename, data, [options])",
"type": "method",
"name": "writeFileSync",
"desc": "fs.writeFile
의 동기버전이다.\n\n
비동기로 파일에 데이터를 추가하고 파일이 존재하지 않는 경우 파일을 생성한다.\ndata
는 문자열이거나 버퍼다.\n\n
예제:\n\n
\nfs.appendFile('message.txt', 'data to append', function (err) {\n if (err) throw err;\n console.log('The "data to append" was appended to file!');\n});
\n"
},
{
"textRaw": "fs.appendFileSync(filename, data, [options])",
"type": "method",
"name": "appendFileSync",
"desc": "fs.appendFile
의 동기버전이다.\n\n
filename
의 변경사항을 감시한다. 콜백 listener
는 파일이 접근될 때마다 호출될\n것이다.\n\n
두번째 아규먼트는 선택사항이다. options
을 전달하는 경우 options
은 두 불리언값의\n멤버변수 persistent
와 interval
을 담고 있는 객체가 될 것이다. persistent
는\n파일을 감사하는 동안 계속해서 프로세스가 실행되어야 하는지를 나타낸다. interval
은\n얼마나 자주 대상을 확인해야 하는지를 밀리초로 나타낸다.\n기본값은 { persistent: true, interval: 5007 }
이다.\n\n
listener
는 두 아규먼트 현재의 stat 객체와 이전의 stat 객체를 받는다.\n\n
fs.watchFile('message.text', function (curr, prev) {\n console.log('the current mtime is: ' + curr.mtime);\n console.log('the previous mtime was: ' + prev.mtime);\n});
\n이 stat 객체들은 fs.Stat
인스턴스다.\n\n
그냥 파일에 접근만 했을 때가 아니라 파일이 수정되었을 때 알림을 받고 싶다면\ncurr.mtime
와 prev.mtime
를 비교해야 한다.\n\n\n
filename
의 변경사항을 감시하는 것을 멈춘다. listener
를 지정하면 해당 리스너만 제거한다.\nlistener
를 지정하지 않으면 모든 리스너를 제거하고 filename
감시를 효율적으로 멈춘다.\n\n
감시받지 않는 파일명으로 fs.unwatchFile()
를 호출하면 오류는 발생하지 않고 아무 작업도\n일어나지 않는다.\n\n
filename
의 변경사항을 감시하고 filename
은 파일이나 디렉토리가 될 수 있다.\n반환객체는 fs.FSWatcher이다.\n\n
두번째 아규먼트는 선택사항이다. options
을 전달한다면 options
은 불리언값의 멤버변수\npersistent
를 담고 있는 객체여야 한다. persistent
는 파일을 감사하는 동안 계속해서\n프로세스가 실행되어야 하는지를 나타낸다. 기본값은 { persistent: true }
이다.\n\n
리스너 콜백은 두 아규먼트 (event, filename)
를 받는다. event
는 'rename'나 'change'이고\nfilename
은 이벤트를 발생시킨 파일의 이름이다.\n\n
fs.watch
API는 모든 플랫폼에서 100% 일치하지 않고 몇몇 상황에서는\n사용할 수 없다.\n\n
이 기능은 의존 운영체제가 제공하는 파일시스템의 변경사항을 알리는 방법에 따라 다르다.\n\n
\ninotify
를 사용한다.kqueue
를 사용한다.event ports
를 사용한다.ReadDirectoryChangesW
에 달려있다.몇가지 이유로 의존하는 기능을 사용할 수 없다면 fs.watch
를 사용할 수 없을 것이다.\n예를 들어 네트워크 파일시스템(NFS, SMB 등)에서 파일이나 디렉토리를 감시하면 종종 신뢰할 수\n있을만큼 동작하지 않거나 전혀 작동하지 않는다.\n\n
stat 폴링(polling)을 사용하지만 더 느리고 덜 신뢰적인 fs.watchFile
는 여전히\n사용할 수 있다.\n\n
모든 클랫폼에서 filename
아규먼트를 콜백에 전달하는 것은 아니다. (현재는 Linux와\nWindows에서만 지원한다.) 이를 지원하는 플랫폼에서 조차도 filename
을 항상 제공한다고\n보장하는 것은 아니다. 그러므로 콜백에 filename
아규먼트가 항상 전달된다고 가정하지 말고\nnull 일 경우를 위한 대체(fallback) 로직을 가지고 있어야 한다.\n\n
fs.watch('somedir', function (event, filename) {\n console.log('event is: ' + event);\n if (filename) {\n console.log('filename provided: ' + filename);\n } else {\n console.log('filename not provided');\n }\n});
\n"
}
]
}
],
"signatures": [
{
"params": [
{
"name": "filename"
},
{
"name": "options",
"optional": true
},
{
"name": "listener",
"optional": true
}
]
}
]
},
{
"textRaw": "fs.exists(path, callback)",
"type": "method",
"name": "exists",
"desc": "파일시스템을 확인해서 전달한 경로가 존재하는지 검사한다.\n존재여부fmf true나 false로 callback
을 호출한다. 예제:\n\n
fs.exists('/etc/passwd', function (exists) {\n util.debug(exists ? "it's there" : "no passwd!");\n});
\n",
"signatures": [
{
"params": [
{
"name": "path"
},
{
"name": "callback"
}
]
}
]
},
{
"textRaw": "fs.existsSync(path)",
"type": "method",
"name": "existsSync",
"desc": "fs.exists
의 동기버전이다.\n\n
새로운 ReadStream 객체를 반환한다. (Readable Stream
를 봐라)\n\n
options
는 다음의 기본값을 가진 객체다.\n\n
{ flags: 'r',\n encoding: null,\n fd: null,\n mode: 0666,\n autoClose: true\n}
\noptions
는 전체 파일대신 읽어드릴 파일의 범위인 start
와 end
를 포함할 수 있다.\nstart
와 end
둘 다 포함하고 0 부터 시작한다. encoding
은 'utf8'
,\n'ascii'
, 'base64'
가 될 수 있다.\n\n
autoClose
가 false이면 오류가 발생하더라도 파일 디스크립터를 닫지 않는다. 파일 디스크립터를\n닫고 파일 디스크립터가 새는 문제가 없도록 하는 것은 개발자의 책임이다. autoClose
를 true로\n설정하면(기본 동작) error
나 end
에서 파일 디스크립터를 자동으로 닫을 것이다.\n\n
100 바이트 길이인 파일의 마지막 10 바이트를 읽는 예제.\n\n
\nfs.createReadStream('sample.txt', {start: 90, end: 99});
\n",
"signatures": [
{
"params": [
{
"name": "path"
},
{
"name": "options",
"optional": true
}
]
}
]
},
{
"textRaw": "fs.createWriteStream(path, [options])",
"type": "method",
"name": "createWriteStream",
"desc": "새로운 WriteStream 객체를 반환한다. (Writable Stream
를 봐라.)\n\n
options
는 다음의 기본값을 갖는 객체다.\n\n
{ flags: 'w',\n encoding: null,\n mode: 0666 }
\noptions
도 파일의 시작위치가 아닌 다른 위치에 데이터를 작성하도록 start
옵션을\n포함할 수도 있다. 파일을 교체하는 대신에 파일을 수정하려면 flags
모드를 기본값인\nw
대신에 r+
를 사용해야 한다.\n\n
fs.stat()
, fs.lstat()
, fs.fstat()
가 리턴하는 객체고 이 함수들의 동기함수들도\n이 타입을 리턴한다.\n\n
stats.isFile()
stats.isDirectory()
stats.isBlockDevice()
stats.isCharacterDevice()
stats.isSymbolicLink()
(only valid with fs.lstat()
)stats.isFIFO()
stats.isSocket()
정규 파일에 대한 util.inspect(stats)
는 다음과 유사한 문자열을 리턴할\n것이다.\n\n
{ dev: 2114,\n ino: 48064969,\n mode: 33188,\n nlink: 1,\n uid: 85,\n gid: 100,\n rdev: 0,\n size: 527,\n blksize: 4096,\n blocks: 8,\n atime: Mon, 10 Oct 2011 23:24:11 GMT,\n mtime: Mon, 10 Oct 2011 23:24:11 GMT,\n ctime: Mon, 10 Oct 2011 23:24:11 GMT }
\natime
, mtime
, ctime
는 [Date][MDN-Date] 객체의 인스턴스이고\n이 객체의 값들을 비교하려면 적절한 메서드를 사용해야한다. 대부분의 경우\n[getTime()][MDN-Date-getTime]는 1980년 1월 _1일부터 경과된\n밀리초를 반환할 것이고 이 정수값은 비교하기에 충분하다. 하지만 명확하지\n않은 정보를 보여주는데 사용할 수 있는 추가적인 메서드들이 있다. 더 자세한\n내용은 [MDN JavaScript Reference][MDN-Date] 페이지에 있다.\n\n
ReadStream
는 Readable Stream이다.\n\n
ReadStream의 파일이 열렸을 때 발생한다.\n\n\n
\n" } ] }, { "textRaw": "Class: fs.WriteStream", "type": "class", "name": "fs.WriteStream", "desc": "WriteStream
는 Writable Stream이다.\n\n
WriteStream의 파일이 열렸을 때 발생한다.\n\n
\n" } ], "properties": [ { "textRaw": "file.bytesWritten", "name": "bytesWritten", "desc": "지금까지 작성된 바이트의 수. 작성하기 위해 아직 큐에 있는 데이터는 포함하지 않는다.\n\n
\n" } ] }, { "textRaw": "Class: fs.FSWatcher", "type": "class", "name": "fs.FSWatcher", "desc": "fs.watch()
가 반환하는 객체가 이 타입이다.\n\n
주어진 fs.FSWatcher
에서 변경사항을 감시하는 것을 멈춘다.\n\n
감시하는 디렉토리나 파일명에서 어떤 변경이 생겼을 때 발생한다.\n더 자세한 내용은 fs.watch를 봐라.\n\n
\n" }, { "textRaw": "Event: 'error'", "type": "event", "name": "error", "params": [], "desc": "오류가 생겼을 때 발생한다.\n\n
\n" } ] } ], "type": "module", "displayName": "fs" }, { "textRaw": "Path", "name": "path", "stability": 3, "stabilityText": "Stable", "desc": "이 모듈에는 파일 경로를 다루고 변경하는 유틸리티가 포함되어 있다. 이 모듈 대부분의\n메서드들은 문자열 변경만 수행한다. 경로가 유효한지 확인하는데 파일 시스템이 관여하지 않는다.\n\n
\n이 모듈을 사용하려면 require('path')
를 사용해라. 다음의 메서드들이 제공된다.\n\n
'..'
와 '.'
부분을 처리해서 문자열 경로를 정규화한다.\n\n
슬래시가 여러 개 있는 경우 슬래시 하나로 교체하고 경로의 마지막에 슬래시가\n있는 경우에는 유지한다.\nwindows에서는 역슬래시를 사용한다.\n\n
\n예제:\n\n
\npath.normalize('/foo/bar//baz/asdf/quux/..')\n// returns\n'/foo/bar/baz/asdf'
\n",
"signatures": [
{
"params": [
{
"name": "p"
}
]
}
]
},
{
"textRaw": "path.join([path1], [path2], [...])",
"type": "method",
"name": "join",
"desc": "모든 아규먼트를 합쳐서 최종 경로로 정규화한다.\n\n
\n아규먼트는 문자열이어야 한다. v0.8에서 문자열이 아닌 아규먼트는 경고없이 무시한다.\nv0.10이상에서는 예외를 던진다.\n\n
\n예제:\n\n
\npath.join('/foo', 'bar', 'baz/asdf', 'quux', '..')\n// returns\n'/foo/bar/baz/asdf'\n\npath.join('foo', {}, 'bar')\n// throws exception\nTypeError: Arguments to path.join must be strings
\n",
"signatures": [
{
"params": [
{
"name": "path1",
"optional": true
},
{
"name": "path2",
"optional": true
},
{
"name": "...",
"optional": true
}
]
}
]
},
{
"textRaw": "path.resolve([from ...], to)",
"type": "method",
"name": "resolve",
"desc": "to
를 절대경로로 변환한다.\n\n
to
가 절대경로가 아니면 절대경로를 찾을 때까지 from
아규먼트들을 우측에서 좌측의 순서로\n앞에 이어붙힌다.모든 from
경로를 사용한 후에도 절대경로를 찾지 못하면 현재 워킹 디렉토리를\n사용한다. 최종 경로는 정규화되고 경로가 루트 디렉토리로 처리되지 않는한 마지막 슬래시는 제거한다.\n문자열이 아닌 아규먼트는 무시한다.\n\n
이는 쉘에서 cd
명령어를 순서대로 실행한 것과 같다.\n\n
path.resolve('foo/bar', '/tmp/file/', '..', 'a/../subfile')
\n이는 다음과 비슷하다.:\n\n
\ncd foo/bar\ncd /tmp/file/\ncd ..\ncd a/../subfile\npwd
\n다른 경로라 존재할 필요가 없거나 파일일 수도 있다는 점만이 다르다.\n\n
\n예제:\n\n
\npath.resolve('/foo/bar', './baz')\n// returns\n'/foo/bar/baz'\n\npath.resolve('/foo/bar', '/tmp/file/')\n// returns\n'/tmp/file'\n\npath.resolve('wwwroot', 'static_files/png/', '../gif/image.gif')\n// if currently in /home/myself/node, it returns\n'/home/myself/node/wwwroot/static_files/gif/image.gif'
\n",
"signatures": [
{
"params": [
{
"name": "from ...",
"optional": true
},
{
"name": "to"
}
]
}
]
},
{
"textRaw": "path.relative(from, to)",
"type": "method",
"name": "relative",
"desc": "from
에서 to
까지의 상대경로를 처리한다.\n\n
때로는 두 개의 절대경로를 가지고 있고 하나에서 다른 하나로의 상대경로를 얻어야 한다.\n사실 이는 path.resolve
의 반대 변환이다. 이 의미를 다음 예제에서 보자.\n\n
path.resolve(from, path.relative(from, to)) == path.resolve(to)
\n예제:\n\n
\npath.relative('C:\\\\orandea\\\\test\\\\aaa', 'C:\\\\orandea\\\\impl\\\\bbb')\n// returns\n'..\\\\..\\\\impl\\\\bbb'\n\npath.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb')\n// returns\n'../../impl/bbb'
\n",
"signatures": [
{
"params": [
{
"name": "from"
},
{
"name": "to"
}
]
}
]
},
{
"textRaw": "path.dirname(p)",
"type": "method",
"name": "dirname",
"desc": "경로의 디렉토리이름을 반환한다. Unix의 dirname
명령어와 비슷하다.\n\n
예제:\n\n
\npath.dirname('/foo/bar/baz/asdf/quux')\n// returns\n'/foo/bar/baz/asdf'
\n",
"signatures": [
{
"params": [
{
"name": "p"
}
]
}
]
},
{
"textRaw": "path.basename(p, [ext])",
"type": "method",
"name": "basename",
"desc": "경로의 마지막 부분을 반환한다. Unix의 basename
명령어와 비슷하다.\n\n
예제:\n\n
\npath.basename('/foo/bar/baz/asdf/quux.html')\n// returns\n'quux.html'\n\npath.basename('/foo/bar/baz/asdf/quux.html', '.html')\n// returns\n'quux'
\n",
"signatures": [
{
"params": [
{
"name": "p"
},
{
"name": "ext",
"optional": true
}
]
}
]
},
{
"textRaw": "path.extname(p)",
"type": "method",
"name": "extname",
"desc": "경로의 마지막 부분의 문자열에서 마지막 '.'에서부터 경로의 확장자를 반환한다.\n경로의 마지막 부분에 '.'가 없거나 첫 글자가 '.'이라면 빈 문자열을 반환한다.\n예제:\n\n
\npath.extname('index.html')\n// returns\n'.html'\n\npath.extname('index.')\n// returns\n'.'\n\npath.extname('index')\n// returns\n''
\n",
"signatures": [
{
"params": [
{
"name": "p"
}
]
}
]
}
],
"properties": [
{
"textRaw": "path.sep",
"name": "sep",
"desc": "플랫폼의 파일 구분자. '\\\\'
나 '/'
이다.\n\n
*nix의 예제:\n\n
\n'foo/bar/baz'.split(path.sep)\n// returns\n['foo', 'bar', 'baz']
\n윈도우즈의 예제:\n\n
\n'foo\\\\bar\\\\baz'.split(path.sep)\n// returns\n['foo', 'bar', 'baz']
\n"
},
{
"textRaw": "path.delimiter",
"name": "delimiter",
"desc": "플랫폼에 특화된 경로 구분자인 ;
나 ':'
이다.\n\n
*nix의 예제:\n\n
\nconsole.log(process.env.PATH)\n// '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin'\n\nprocess.env.PATH.split(path.delimiter)\n// returns\n['/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/bin']
\n윈도우즈의 예제:\n\n
\nconsole.log(process.env.PATH)\n// 'C:\\Windows\\system32;C:\\Windows;C:\\Program Files\\nodejs\\'\n\nprocess.env.PATH.split(path.delimiter)\n// returns\n['C:\\Windows\\system32', 'C:\\Windows', 'C:\\Program Files\\nodejs\\']
\n"
}
],
"type": "module",
"displayName": "Path"
},
{
"textRaw": "net",
"name": "net",
"stability": 3,
"stabilityText": "Stable",
"desc": "net
모듈은 비동기적인 네트워크 레퍼다. 서버와 클라이언트(스트림이라고 부른다.)를 모두\n생성하는 메서드들이 포함되어 있다. require('net');
로 이 모듈을 사용할 수 있다.\n\n
새로운 TCP 서버를 생성한다. connectionListener
아규먼트는 자동적으로\n['connection'][] 이벤트의 리스너로 설정한다.\n\n
options
은 다음 객체가 기본값이다.\n\n
{ allowHalfOpen: false\n}
\nallowHalfOpen
가 true
이면 소켓은 반대쪽 소켓이 FIN 패킷을 보냈을 때 자동으로\nFIN 패킷을 보내지 않는다. 소켓은 읽을 수 없는 상태가 되지만 여전히 쓰기는 가능하다.\n명시적으로 end()
메서드를 호출해야 한다. 더 자세한 내용은 ['end'][]\n이벤트를 봐라.\n\n
다음은 8124 포트에 대한 연결을 받는 에코 서버의 예제다.\n\n
\nvar net = require('net');\nvar server = net.createServer(function(c) { //'connection' listener\n console.log('server connected');\n c.on('end', function() {\n console.log('server disconnected');\n });\n c.write('hello\\r\\n');\n c.pipe(c);\n});\nserver.listen(8124, function() { //'listening' listener\n console.log('server bound');\n});
\n이 예제는 telnet
를 사용해서 테스트한다.\n\n
telnet localhost 8124
\n/tmp/echo.sock
소켓에서 응답을 받으려면 마지막에서 세번째 줄을 다음과 같이\n바꾼다.\n\n
server.listen('/tmp/echo.sock', function() { //'listening' listener
\nUNIX 도메인 소켓서버에 접속하려면 nc
를 사용해라.\n\n
nc -U /tmp/echo.sock
\n",
"signatures": [
{
"params": [
{
"name": "options",
"optional": true
},
{
"name": "connectionListener",
"optional": true
}
]
}
]
},
{
"textRaw": "net.connect(options, [connectionListener])",
"type": "method",
"name": "connect",
"desc": "새로운 소켓 객체를 생성하고 전달한 위치로 소켓을 연다. 소켓 구성이 완료되었을 때\n['connect'][] 이벤트가 발생할 것이다.\n\n
\nTCP 소켓에서 options
아규먼트는 다음을 지정하는 객체여야 한다.\n\n
port
: 클라이언트가 접속할 포트 (필수).
host
: 클라이언트가 접속할 호스트. 기본값은 'localhost'
다.
localAddress
: 네트워크 연결에 바인딩할 로컬 인터페이스.
For UNIX domain sockets, options
argument should be an object which specifies:\nUNIX계열 소켓에서는 options
아규먼트는 다음을 지정하는 객체여야 한다.\n\n
path
: 클라이언트가 접속할 경로. (필수)공통 옵션은 다음과 같다.\n\n
\nallowHalfOpen
: 이 값이 true
이면 소켓의 반대쪽에서 FIN 패킷을\n보냈을 때 자동으로 FIN 패킷을 보내지 않는다. 더 자세한 내용은 ['end'][]를\n봐라.connectListener
파라미터를 ['connect'][] 이벤트의\n리스터로 추가할 것이다.\n\n
다음은 이전에 설명한 에코서버의 클리이언트 예제다.\n\n
\nvar net = require('net');\nvar client = net.connect({port: 8124},\n function() { //'connect' listener\n console.log('client connected');\n client.write('world!\\r\\n');\n});\nclient.on('data', function(data) {\n console.log(data.toString());\n client.end();\n});\nclient.on('end', function() {\n console.log('client disconnected');\n});
\n/tmp/echo.sock
소켓에 연결하려면 두번째 줄을 다음과 같이 변경한다.\n\n
var client = net.connect({path: '/tmp/echo.sock'},
\n",
"signatures": [
{
"params": [
{
"name": "options"
},
{
"name": "connectionListener",
"optional": true
}
]
},
{
"params": [
{
"name": "options"
},
{
"name": "connectionListener",
"optional": true
}
]
}
]
},
{
"textRaw": "net.createConnection(options, [connectionListener])",
"type": "method",
"name": "createConnection",
"desc": "새로운 소켓 객체를 생성하고 전달한 위치로 소켓을 연다. 소켓 구성이 완료되었을 때\n['connect'][] 이벤트가 발생할 것이다.\n\n
\nTCP 소켓에서 options
아규먼트는 다음을 지정하는 객체여야 한다.\n\n
port
: 클라이언트가 접속할 포트 (필수).
host
: 클라이언트가 접속할 호스트. 기본값은 'localhost'
다.
localAddress
: 네트워크 연결에 바인딩할 로컬 인터페이스.
For UNIX domain sockets, options
argument should be an object which specifies:\nUNIX계열 소켓에서는 options
아규먼트는 다음을 지정하는 객체여야 한다.\n\n
path
: 클라이언트가 접속할 경로. (필수)공통 옵션은 다음과 같다.\n\n
\nallowHalfOpen
: 이 값이 true
이면 소켓의 반대쪽에서 FIN 패킷을\n보냈을 때 자동으로 FIN 패킷을 보내지 않는다. 더 자세한 내용은 ['end'][]를\n봐라.connectListener
파라미터를 ['connect'][] 이벤트의\n리스터로 추가할 것이다.\n\n
다음은 이전에 설명한 에코서버의 클리이언트 예제다.\n\n
\nvar net = require('net');\nvar client = net.connect({port: 8124},\n function() { //'connect' listener\n console.log('client connected');\n client.write('world!\\r\\n');\n});\nclient.on('data', function(data) {\n console.log(data.toString());\n client.end();\n});\nclient.on('end', function() {\n console.log('client disconnected');\n});
\n/tmp/echo.sock
소켓에 연결하려면 두번째 줄을 다음과 같이 변경한다.\n\n
var client = net.connect({path: '/tmp/echo.sock'},
\n",
"signatures": [
{
"params": [
{
"name": "options"
},
{
"name": "connectionListener",
"optional": true
}
]
}
]
},
{
"textRaw": "net.connect(port, [host], [connectListener])",
"type": "method",
"name": "connect",
"desc": "host
의 port
로 TCP 연결을 생성한다. host
를 생략하면 'localhost'
라고\n가정한다.\nconnectListener
파라미터는 ['connect'][] 이벤트의 리스너로 추가될 것이다.\n\n
host
의 port
로 TCP 연결을 생성한다. host
를 생략하면 'localhost'
라고\n가정한다.\nconnectListener
파라미터는 ['connect'][] 이벤트의 리스너로 추가될 것이다.\n\n
path
로 유닉스 소켓 연결을 생성한다.\nconnectListener
파라미터는 ['connect'][] 이벤트의 리스너로 추가될 것이다.\n\n
path
로 유닉스 소켓 연결을 생성한다.\nconnectListener
파라미터는 ['connect'][] 이벤트의 리스너로 추가될 것이다.\n\n
input이 IP 주소인지 검사한다. 유효하지 않은 문자열이면 0을 반환하고 IP 버전 4 주소이면 4를\n반환하고 IP 버전 6 주소이면 6을 반환한다.\n\n\n
\n", "signatures": [ { "params": [ { "name": "input" } ] } ] }, { "textRaw": "net.isIPv4(input)", "type": "method", "name": "isIPv4", "desc": "input이 IP 버전 4 주소이면 true를 반환하고 IP 버전 4 주소가 아니면 false를 반환한다.\n\n\n
\n", "signatures": [ { "params": [ { "name": "input" } ] } ] }, { "textRaw": "net.isIPv6(input)", "type": "method", "name": "isIPv6", "desc": "input이 IP 버전 6 주소이면 true를 반환하고 IP 버전 6 주소가 아니면 false를 반환한다.\n\n
\n", "signatures": [ { "params": [ { "name": "input" } ] } ] } ], "classes": [ { "textRaw": "Class: net.Server", "type": "class", "name": "net.Server", "desc": "이 클래스는 TCP나 UNIX 서버를 생성하는데 사용한다.\n서버는 새로 들어오는 연결을 받을 수 있는 net.Socket
이다.\n\n
지정한 port
와 host
에서 연결을 받아들이기 시작한다. host
를 생략하면\n모든 IPv4 주소(INADDR_ANY
)에서 직접 들어오는 연결을 받아들일 것이다.\n포트를 0으로 지정하면 임의의 포트를 사용할 것이다.\n\n
백로그는 대기하는 연결의 큐의 최대 길이이다.\n실제 길이는 리눅스의 tcp_max_syn_backlog
와 somaxconn
같은 sysctl 설정으로\nOS가 결정한다. 백로그의 기본값은 511이다.(512가 아니다)\n\n
이 함수는 비동기함수이다. 서버가 바인딩되었을 때\n['listening'][] 이벤트가 발생할 것이다.\n마지막 파라미터 callback
는 ['listening'][] 이벤트의\n리스터로 추가할 것이다.\n\n
몇몇 유저는 실행했을 때 EADDRINUSE
오류가 발생하는 이슈가 있다. 이는 다른 서버가\n이미 요청한 포트에서 동작하고 있다는 것을 의미한다. 이 오류를 다루는 한가지 방법은\n약간 기다린 후에 다시 시도하는 것이다. 다음과 같은 코드로 처리할 수 있다.\n\n
server.on('error', function (e) {\n if (e.code == 'EADDRINUSE') {\n console.log('Address in use, retrying...');\n setTimeout(function () {\n server.close();\n server.listen(PORT, HOST);\n }, 1000);\n }\n});
\n(주의: Node의 모든 소켓은 이미 SO_REUSEADDR
를 설정한다.)\n\n\n
전달한 path
에서 연결을 받아들이는 UNIX 소켓서버를 시작한다.\n\n
이 함수는 비동기 함수이다. 서버가 바인딩되었을 때\n['listening'][] 이벤트가 발생할 것이다.\n마지막 파라미터 callback
는 ['listening'][] 이벤트의\n리스터로 추가될 것이다.\n\n
handle
객체는 서버나 소켓으로 설정되거나(의존하는 _handle
멤버를 가진\n어떤 것이든) {fd: <n>}
객체가 될 수 있다.\n\n
이 함수는 서버가 지정한 핸들에서 연결받아들이도록 하지만 파일 디스크립터나\n핸들이 이미 포트나 도메인 소켓에 바인딩되었다고 가정한다.\n\n
\nWindows에서는 파일스크립터에서 연결을 받아들이는 것을 지원하지 않는다.\n\n
\n이 함수는 비동기 함수이다. 서버가 바인딩되었을 때\n'listening' 이벤트가 발생할 것이다.\n마지막 파라미터 callback
는 'listening' 이벤트의\n리스터로 추가될 것이다.\n\n
서버가 새로운 연결을 받아들이는 것과 현재 존재하는 연결을 유지하는 것을 멈춘다.\n이 함수는 비동기 함수이고 모든 연결이 종료되고 서버에서 'close'
이벤트가\n발생했을 때 완전히 닫힌다. 선택적으로 'close'
이벤트를 받는 콜백을\n전달할 수 있다.\n\n
운영체제가 보고한대로 서버에 바인딩된 주소와 주소 패밀리 이름과 포트를 반환한다.\n운영체제에 할당된 주소를 사용했을 때 할당된 포트를 찾는데 유용하다.\n세 개의 프로퍼티를 가진 객체를 리턴한다. 예시:\n{ port: 12346, family: 'IPv4', address: '127.0.0.1' }
\n\n
예제:\n\n
\nvar server = net.createServer(function (socket) {\n socket.end("goodbye\\n");\n});\n\n// grab a random port.\nserver.listen(function() {\n address = server.address();\n console.log("opened server on %j", address);\n});
\n'listening'
이벤트가 발생할 때까지 server.address()
를 호출하지 마라.\n\n
서버에 unref
를 호출하는 것은 해당 서버가 이벤트 시스템에서 유일하게 활성화된 서버인 경우\n프로그램이 종료되도록 할 것이다. 서버에 이미 unref
를 호출했다면 다시 unref
를 호출해도\n아무런 영향이 없다.\n\n
unref
와는 반대로 이미 unref
된 서버에 ref
를 호출하는 것은 해당 서버가 유일하게 남은\n서버인 경우 프로그램이 종료되지 않도록 할 것이다.(기본 동작이다) 서버에 이미 ref
를 호출했다면\n다시 ref
를 호출해도 아무런 영향이 없을 것이다.\n\n
비동기적으로 서버의 현재 연결 수를 가져온다. 포크(fork)하려보 소켓을 보냈을 때 동작한다.\n\n
\n콜백은 두개의 인자 err
와 count
를 받아야 한다.\n\n
서버의 연결수가 많아졌을 때 연결을 거절하려면 이 프로퍼티를 설정해라.\n\n
\nchild_process.fork()
로 자식에 소켓을 보냈을 때 이 옵션을 사용하는 것은\n권하지 않는다.\n\n
이 함수는 폐기되었다. 대신 [server.getConnections()][]를 사용해라.\n서버의 동시접속 수.\n\n
\nchild_process.fork()
로 자식 프로세스에 소켓을 보냈을 때 이 값은 null
이 된다.\n현재 활성화된 연결의 수를 얻거나 포크하려면 대신 비동기 server.getConnections
를 사용해라.\n\n
net.Server
는 다음 이벤트를 가진 [EventEmitter][]이다.\n\n
server.listen
가 호출된 후 서버가 바인딩되었을 때 발생한다.\n\n
새로운 연결이 생성되었을 때 발생한다. socket
은 net.Socket
의\n인스턴스다.\n\n
서버를 닫을 때 발생한다. 연결이 존재하는 경우\n모든 연결이 종료될 때까지 이 이벤트틑 발생하지 않는다.\n\n
\n", "params": [] }, { "textRaw": "Event: 'error'", "type": "event", "name": "error", "params": [], "desc": "오류가 생겼을 때 발생한다. 이 이벤트 후에 곧바로 'close'
이벤트가 호출될 것이다.\nserver.listen
설명에서의 예제를 봐라.\n\n
이 객체는 TCP나 UNIX 소켓의 추상화 객체다. net.Socket
인스턴스는 이중 Stream\n인스턴스를 구현한다. net.Socket
인스턴스는 사용자가 생성해서 클라이언트처럼\n(connect()
를 사용해서) 사용하거나 Node가 생성해서 서버의 'connection'
이벤트로\n사용자에게 전달할 수도 있다.\n\n
새로운 소켓 객체를 생성한다.\n\n
\noptions
은 다음의 기본값을 가진 객체다.\n\n
{ fd: null\n type: null\n allowHalfOpen: false\n}
\nfd
로 이미 존재하는 소켓의 파일 디스크립터를 지정할 수 있다. type
은 의존하는\n프로토콜들 지정한다. type
은 'tcp4'
, 'tcp6'
, 'unix'
가 될 수 있다.\nallowHalfOpen
에 대해서는 createServer()
와 'end'
이벤트를 참고해라.\n\n
주어진 소켓에 대한 연결을 오픈한다. port
와 host
를 절달하면 소켓은 TCP 소켓으로 열릴\n것이고 host
를 생략하면 localhost
를 사용할 것이다. path
를 전달하면 소켓은\n해당 경로로의 유닉스 소켓으로 열릴 것이다.\n\n
net.createConnection
이 소켓을 여는 한 이 메서드는 보통 필요하지 않다. 커스텀 Sokcet을\n구현헀을 때만 이 메서드를 사용해라.\n\n
이 함수는 비동기 함수이다. ['connect'][] 이벤트가 발생하면 소켓이 구성된\n것이다. 연결하는데 문제가 있다면 'connect'
이벤트는 발생하지 않고 'error'
이벤트가\n예외와 함께 발생할 것이다.\n\n
connectListener
파라미터는 ['connect'][] 이벤트의 리스터로 추가된다.\n\n\n
주어진 소켓에 대한 연결을 오픈한다. port
와 host
를 절달하면 소켓은 TCP 소켓으로 열릴\n것이고 host
를 생략하면 localhost
를 사용할 것이다. path
를 전달하면 소켓은\n해당 경로로의 유닉스 소켓으로 열릴 것이다.\n\n
net.createConnection
이 소켓을 여는 한 이 메서드는 보통 필요하지 않다. 커스텀 Sokcet을\n구현헀을 때만 이 메서드를 사용해라.\n\n
이 함수는 비동기 함수이다. ['connect'][] 이벤트가 발생하면 소켓이 구성된\n것이다. 연결하는데 문제가 있다면 'connect'
이벤트는 발생하지 않고 'error'
이벤트가\n예외와 함께 발생할 것이다.\n\n
connectListener
파라미터는 ['connect'][] 이벤트의 리스터로 추가된다.\n\n\n
읽을 수 있는 스트림인 소켓의 인코딩을 설정한다. 더 자세한 내용은\n[stream.setEncoding()][]를 봐라.\n\n
\n", "signatures": [ { "params": [ { "name": "encoding", "optional": true } ] } ] }, { "textRaw": "socket.write(data, [encoding], [callback])", "type": "method", "name": "write", "desc": "소켓에 데이터를 보낸다. 두 번째 파라미터는 문자열인 경우에 인코딩을 지정한다.\n기본 인코딩은 UTF8 인코딩이다.\n\n
\n전체 데이터를 커널 버퍼에 성공적으로 플러시(flush)했다면 true
를 반환한다.\n데이터의 일부나 전체가 사용자 메모리에 큐되었다면 false
를 반환한다.\n버퍼가 다시 비워졌을 때 'drain'
이 발생할 것이다.\n\n
선택사항인 callback
파라미터는 데이터가 최종적으로 작성되었을 때 실행될 것이다.\n이는 즉시 실행되는 것은 아니다.\n\n
소켓을 절반만 닫는다. 예를 들어 이 메서드는 FIN 패킷을 보낸다. 서버는 여전히 약간의\n데이터를 보낼 수 있을 것이다.\n\n
\ndata
를 지정하면 socket.end()
에 이어서 socket.write(data, encoding)
를\n호출한 것과 같다.\n\n
이 소켓에는 더이상 I/O 작업이 없다는 것은 보증한다. 오류가 발생한 경우에만 필요하다.\n(오류를 파싱하는 등)\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "socket.pause()", "type": "method", "name": "pause", "desc": "데이터를 읽는 것을 멈춘다. 즉, 'data'
이벤트가 발생하지 않는다.\n업로드를 차단하는데 유용하다.\n\n
pause()
를 호출한 후에 다시 읽기 시작한다.\n\n
소켓에서 활동이 없는 timeout
밀리초 후의 타임아웃에 소켓을 설정한다.\n기본적으로 net.Socket
에는 타임아웃이 없다.\n\n
유휴시간(idle timeout)이 실행되었을 때 소켓은 'timeout'
이벤트를 받지만\n연결은 끝기지 않는다. 사용자는 소켓을 수동으로 end()
하거나 destroy()
해야 한다.\n\n
timeout
이 0이면 존재하는 유휴시간이 사용할 수 없게 된다.\n\n
선택사항인 callback
파라미터는 'timeout'
이벤트의 일회성 리스터로 추가될 것이다.\n\n
Nagle 알고리즘을 사용하지 않는다. 기본적으로 TCP 연결은 Nagle 알고리즘을 사용해서\n데이터를 보내기전에 데이터를 버퍼에 넣는다. noDelay
를 true
로 설정하면\nsocket.write()
를 호출할 때마다 데이터를 즉시 보낼 것이다.\nnoDelay
의 기본값은 true
이다.\n\n
keep-alive 기능을 사용하거나 사용하지 않고 비어있는 소켓에 첫 keepalive 조사를\n하기 전에 초기화 지연을 선택적으로 설정한다.\nenable
의 기본값은 false
다.\n\n
받은 마지막 데이터 패킷과 첫 keepalive 검사사이에 지연시간을 설정하는데\ninitialDelay
를(밀리초로) 설정한다. initialDelay에 0을 설정하면 기본(혹은 이전의)\n설정 값을 변경하지 않고 놔둘 것이다. 기본값은 0
이다.\n\n\n
운영체제가 보고한대로 소켓에 바인딩된 주소와 주소 패밀리 이름과 포트를 반환한다.\n세 개의 프로퍼티를 가진 객체를 리턴한다.\n예시: { port: 12346, family: 'IPv4', address: '127.0.0.1' }
\n\n
소켓에 unref
를 호출하는 것은 해당 소켓이 이벤트 시스템에서 유일하게 활성화된 소켓일 때 프로그램이\n종료되도록 할 것이다. 소켓에 이미 unref
를 호출했다면 다시 unref
를 호출해도 아무런 영향이\n없을 것이다.\n\n
unref
와는 반대로 이전에 unref
된 소켓에 ref
를 호출하는 것은 해당 소켓이 유일하게 남은\n소켓일 때 프로그램이 종료되지 않도록 할 것이다.(기본 동작이다) 소켓에 이미 ref
를 호출했다면\n다시 ref
를 호출해도 아무런 영향이 없을 것이다.\n\n
net.Socket
는 socket.write()
가 항상 동작하는 프로퍼티를 가지고 있다. 이 프로퍼티는\n사용자가 빠르게 준비해서 실행하도록 도와준다. 컴퓨터는 소켓에 잘성된 데이터의 양을 항상\n유지할 수는 없다. - 네트워크 연결은 쉽게 엄청 느려질 수도 있다. Node는 매부적으로 소켓에\n작성된 데이터를 큐에 넣고 가능해 졌을 때 데이터를 보낼 것이다. (내부적으로 쓰기 가능한\n상태를 유지하기 위해 소켓의 파일 디스크립트에서 폴링한다.)\n\n
이러한 내부적 버퍼링으로 인해서 메모리가 커질 수 있다. 이 프로퍼티는 쓰여지기 위해서 현재\n버퍼된 글자의 수를 보여준다. (글자의 수는 대략적으로 쓰여질 바이트의 수와 같지만 버퍼는\n문자열을 담고 있을 것이고 문자열은 지연 인코딩된다. 그래서 바이트의 정확한 수는 알지\n못한다.)\n\n
\n엄청 크거나 커지는 bufferSize
를 경험한 사용자들은 프로그램에서 pause()
와\nresume()
로 데이터의 흐름을 "조절하는(throttle)" 시도를 해야한다.\n\n\n
원격 IP 주소의 문자열 표현이다. 예를 들면 '74.125.127.100'
나\n'2001:4860:a005::68'
와 같은 식이다.\n\n
원격 포트의 숫자 표현이다. 예를 들면 80
이나 21
이다.\n\n
원격 클라이언트가 접속한 로컬 IP 주소의 문자열 표현이다. 예를 들어 '0.0.0.0'
를 리스닝하고 있고\n클라이언트가 '192.168.1.1'
에 접속했다면 이 값은 '192.168.1.1'
가 될 것이다.\n\n
로컬 포트의 숫자 표현이다. 예를 들면 80
이나 21
이다.\n\n
받은 바이트의 양.\n\n
\n" }, { "textRaw": "socket.bytesWritten", "name": "bytesWritten", "desc": "보낸 바이트의 양.\n\n\n
\nnet.Socket
인스턴스는 다음의 이벤트를 가진 [EventEmitter][]이다.\n\n
소켓 연결이 성공적으로 이뤄졌을 때 발생한다.\nconnect()
를 봐라.\n\n
데이터를 받았을 때 발생한다. data
아규먼트는 Buffer
나 String
이 될 것이다.\n데이터의 인코딩은 socket.setEncoding()
로 설정한다.\n(더 자세한 내용은 [Readable Stream][]를 봐라.)\n\n
Socket
이 'data'
이벤트를 발생시켰을 때 리스너가 없으면 데이터를 잃어버릴 것이다.\n\n
소켓의 반대쪽 끝에서 FIN 패킷을 보냈을 때 발생한다.\n\n
\n기본적으로 (allowHalfOpen == false
) 소켓은 미뤄두었던 작성 큐를 다 소비하면\n자신의 파일 디스크립터를 파괴할 것이다.\n하지만 allowHalfOpen == true
로 설정하면 소켓은 이제 반대쪽에 end()
할 필요가\n있다는 경고와 함께 사용자가 임의의 양의 데이터를 작성할 수 있도록 반대쪽에 end()
를\n자동으로 호출하지 않을 것이다.\n\n\n
유휴상태에서 소켓의 시간이 만료되었을 때 발생한다. 이는 소켓이 아무일도 하지 않을 때만\n알려준다. 사용자는 수동으로 연결을 닫아야 한다.\n\n
\nsocket.setTimeout()
도 봐라.\n\n\n
작성 버퍼가 비워졌을 때 발생한다. 업로드를 조절하는데 사용할 수 있다.\n\n
\nsocket.write()
의 반환값도 참고해라.\n\n
오류가 생겼을 때 발생한다. 이 이벤트에 이어서 곧바로 'close'
이벤트가 호출될 것이다.\n\n
소켓이 완전히 닫혔을 때 발생한다. had_error
아규먼트는 소켓이 전송 오류때문에 닫혔는 지를\n알려주는 불리언 값이다.\n\n
데이터그램 소켓은 require('dgram')
로 사용할 수 있다.\n\n
중요사항: dgram.Socket#bind()
의 동작은 v0.10에서 변경되어서 이제는 항상 비동기로 동작한다.\n다음과 같이 작성했다면:\n\n
var s = dgram.createSocket('udp4');\ns.bind(1234);\ns.addMembership('224.0.0.114');
\n다음과 같이 변경해야 한다.\n\n
\nvar s = dgram.createSocket('udp4');\ns.bind(1234, function() {\n s.addMembership('224.0.0.114');\n});
\n",
"methods": [
{
"textRaw": "dgram.createSocket(type, [callback])",
"type": "method",
"name": "createSocket",
"signatures": [
{
"params": [
{
"textRaw": "`type` 문자열. 'udp4'나 'udp6' ",
"name": "type",
"desc": "문자열. 'udp4'나 'udp6'"
},
{
"textRaw": "`callback` 함수. `message` 이벤트에 리스너로 추가된다. 선택사항 ",
"name": "callback",
"desc": "함수. `message` 이벤트에 리스너로 추가된다. 선택사항",
"optional": true
},
{
"textRaw": "반환값: Socket 객체 ",
"name": "반환값",
"desc": "Socket 객체"
}
]
},
{
"params": [
{
"name": "type"
},
{
"name": "callback",
"optional": true
}
]
}
],
"desc": "지정한 타입의 데이터그램 소켓을 생성한다. 유효한 타입은 udp4
와 udp6
이다.\n\n
message
이벤트의 리스터로 추가되는 선택사항인 콜백을 받는다.\n\n
데이터그램을 받으려면 socket.bind
를 호출해라. socket.bind()
는 임의의 포트에서\n"모든 인터페이스" 주소에 바인딩한다. (udp4
와 udp6
소켓 둘다에 대해 맞는 것이다.)\n그 다음 socket.address().address
와 socket.address().port
로 주소와 포트를\n획득할 수 있다.\n\n
dgram Socket 클래스는 데이터그램 기능을 은닉화한다. 이 클래스는\ndgram.createSocket(type, [callback])
를 통해서 생성되어야 한다.\n\n
소켓에서 새로운 데이터그램을 사용할 수 있게 되었을 때 발생한다. msg
는 Buffer
이고 rinfo
는\n보내는 쪽의 주소정보와 데이터그램의 바이트 수를 담고 있는 객체다.\n\n
소켓이 데이트그램을 받기 시작했을 때 발생한다. 이는 UDP 소켓이 생성되자마자 발생한다.\n\n
\n", "params": [] }, { "textRaw": "Event: 'close'", "type": "event", "name": "close", "desc": "소켓이 close()
로 닫혔을 때 발생한다. 소켓에서 더이상 새로운 message
이벤트가 발생하지 않는다.\n\n
오류가 생겼을 때 발생한다.\n\n
\n" } ], "methods": [ { "textRaw": "socket.send(buf, offset, length, port, address, [callback])", "type": "method", "name": "send", "signatures": [ { "params": [ { "textRaw": "`buf` Buffer 객체. 보내는 메시지다 ", "name": "buf", "desc": "Buffer 객체. 보내는 메시지다" }, { "textRaw": "`offset` 정수. 버퍼에서 메시지가 시작되는 오프셋. ", "name": "offset", "desc": "정수. 버퍼에서 메시지가 시작되는 오프셋." }, { "textRaw": "`length` 정수. 메시지의 바이트 수 ", "name": "length", "desc": "정수. 메시지의 바이트 수" }, { "textRaw": "`port` 정수. 목적지 포트 ", "name": "port", "desc": "정수. 목적지 포트" }, { "textRaw": "`address` 문자열. 목적지 IP ", "name": "address", "desc": "문자열. 목적지 IP" }, { "textRaw": "`callback` 함수. 메시지가 배달완료되었을 때 호출될 콜백. 선택사항. ", "name": "callback", "desc": "함수. 메시지가 배달완료되었을 때 호출될 콜백. 선택사항.", "optional": true } ] }, { "params": [ { "name": "buf" }, { "name": "offset" }, { "name": "length" }, { "name": "port" }, { "name": "address" }, { "name": "callback", "optional": true } ] } ], "desc": "UDP 소켓에서 목적지 포트와 IP 주소는 반드시 지정해야 한다. address
파라미터에 문자열을\n전달하고 이는 DNS로 처리될 것이다. 선택사항인 콜백은 DNS 오류와 buf
가 다시 사용될 때를\n탐지하기 위해 지정할 것이다. DNS 검색은 최소한 다음 tick까지 통신이 이뤄지는 시간동안 연기될\n것이다. 통신이 콜백을 사용한다는 것을 확실하게 아는 유일한 방법이다.\n\n
소켓이 bind
호출로 이전에 바인딩되지 않았다면 임의의 포트번호를 할당받고\n"모든 인터페이스" 주소에 바인딩 될 것이다.\n(udp4
에는 0.0.0.0, udp6
소켓에는 ::0)\n\n
localhost
의 임의의 포트로 UDP 패킷을 보내는 예제;\n\n
var dgram = require('dgram');\nvar message = new Buffer("Some bytes");\nvar client = dgram.createSocket("udp4");\nclient.send(message, 0, message.length, 41234, "localhost", function(err, bytes) {\n client.close();\n});
\nUDP 데이터그램 크기에 대한 내용\n\n
\nIPv4/v6
데이터그램의 최대 크기는 MTU
(Maximum Transmission Unit)와 Payload Length
필드\n사이즈에 달려 있다.\n\n
Payload Length
필드는 16 bits
크기이다. 이는 일반적인 탑재량(payload)은 인터넷\n헤더와 데이터를 포함해서 64K 옥텟보다 클 수가 없다는 의미이다\n(65,507 bytes = 65,535 − 8 bytes UDP header − 20 bytes IP header);\n이는 loopback 인터페이스에서 보통 true이지만 긴 데이터그램같은 것은 대부분의 호스트와\n네트워크에서 비현실적이다.
MTU
는 주어진 링크 계층 기술(link layer technology)이 데이터그램에 지원할 수 있는\n최대 사이즈이다. 전체를 받든지 부분만 받든지 IPv4에 대해 추천되는 MTU
이 576
인 한\n어떤 링크에서도 IPv4
는 68
옥텟의 최소 MTU
를 지정한다. (보통 다이얼업(dial-up)\n타입의 어플리케이션에 대해 MTU
로 추천된다.)
IPv6
에서는 최소 MTU
가 1280
옥텟이지만 강제적인 최소 단편 재조합 버퍼의 크기는\n1500
옥텟이다.\n가장 현대적인 링크계층 기술은 1500
의 최소 MTU
를 가지기 때문에(이더넷처럼)\n68
옥텟의 값은 아주 작다.
패킷이 이동하는 각 링크의 MTU를 미리 아는 것은 불가능하고 보통 (수신자) MTU
보다 큰\n데이터그램을 전송하는 것은 동작하지 않는다. (데이터가 의도된 수신자에게 도달하지 않았다는\n것을 소스에 알리지 않고 패킷을 경고없이 버린다.)\n\n
UDP 소켓에서 port
와 선택사항인 address
에서 데이터그랩을 받는다. address
를 지정하지\n않으면 운영체제는 모든 주소에서 받을 것이다. 바인딩이 완료되면 "listening" 이벤트가 발생하고\ncallback
(지정한 경우)을 실행한다. "listening" 이벤트 리스너와 callback
을 모두\n지정해도 문제는 없지만 별로 유용하지도 않다.\n\n
바인딩된 데이터그램 소켓은 데이터그램을 받기 위해서 노드 프로세스가 계속 동작하도록 유지한다.\n\n
\n바인딩이 실패하면 "error" 이벤트가 발생한다. 드문 경우이지만(예를 들면 닫힌 소켓을 바인딩하는\n경우) 이 메서드가 Error
를 던질 수도 있다.\n\n
UDP 서버가 41234 포트에서 받는 예제:\n\n
\nvar dgram = require("dgram");\n\nvar server = dgram.createSocket("udp4");\n\nserver.on("error", function (err) {\n console.log("server error:\\n" + err.stack);\n server.close();\n});\n\nserver.on("message", function (msg, rinfo) {\n console.log("server got: " + msg + " from " +\n rinfo.address + ":" + rinfo.port);\n});\n\nserver.on("listening", function () {\n var address = server.address();\n console.log("server listening " +\n address.address + ":" + address.port);\n});\n\nserver.bind(41234);\n// server listening 0.0.0.0:41234
\n"
},
{
"textRaw": "socket.close()",
"type": "method",
"name": "close",
"desc": "의존하는 소켓을 닫고 소켓에서 데이터를 받는 것을 멈춘다.\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "socket.address()", "type": "method", "name": "address", "desc": "소켓에 대한 주소 정보를 담고 있는 객체를 반환한다. UDP 소켓에서 이 객체는\naddress
와 family
와 port
를 담고 있을 것이다.\n\n
SO_BROADCAST
소켓 옵션을 설정하거나 없앤다. 이 옵션을 설정하면 로컬 인터페이스의 브로드캐스트\n주소로 UDP 패킷을 보낼 것이다.\n\n
IP_TTL
소켓 옵션을 설정한다. TTL은 "Time to Live"를 의미하지만 이 상황에서 TTL은 패킷이\n거쳐가도 되는 IP 홉(hop)의 수를 지정한다. 패킷이 지나쳐가는 각 라우터나 게이트웨이는 TTL을\n감소시킨다. TTL이 라우터에 의해서 0까지 줄어들면 더이상 전송되지 않을 것이다. TTL 값을\n변경하는 것은 보통 네트워크 검사나 멀티캐스팅 될 때 이뤄진다.\n\n
setTTL()
의 아규먼트는 1부터 255사이의 홉 수이다. 대부분의 시스템에서 기본값은 64이다.\n\n
IP_MULTICAST_TTL
소켓 옵션을 설정한다. TTL은 "Time to Live"를 의미하지만 이 상황에서 TTL은\n특히 멀티캐스트 트래픽에 대해서 패킷이 거쳐가도 되는 IP 홉(hop)의 수를 지정한다. 패킷이 지나쳐가는\n각 라우터나 게이트웨이는 TTL을 감소시킨다. TTL이 라우터에 의해서 0까지 줄어들면 더이상 전송되지\n않을 것이다.\n\n
setMulticastTTL()
의 아규먼트는 0부터 255사이의 홉(hop) 수이다. 대부분의 시스템에서 기본값은 1이다.\n\n
IP_MULTICAST_LOOP
소켓 옵션을 설정하거나 제거한다. 이 옵셩을 설정하면 멀티캐스트 패킷도 로컬\n인터페이스에서 받을 것이다.\n\n
IP_ADD_MEMBERSHIP
소켓 옵션과 함께 멀티캐스트 그룹에 합류하도록 커널에 알려준다.\n\n
multicastInterface
를 지정하지 않으면 운영체제는 회원을 유효한 모든 인터페이스에 추가하려고\n할 것이다.\n\n
addMembership
와는 반대로 IP_DROP_MEMBERSHIP
소켓 옵션과 함께 멀티캐스트 그룹에서\n나오도록 커널에 명령한다. 이는 소캣이 닫히거나 진행이 종료되었을 때 커널이 자동적으로 호출할\n것이므로 대부분의 어플리케이션은 이 함수를 호출할 필요가 없을 것이다.\n\n
multicastInterface
를 지정하지 않으면 운영체제는 회원을 유효한 모든 인터페이스에서 버리려고\n할 것이다.\n\n
소켓에서 unref
를 호출하는 것은 해당 소켓이 이벤트 시스템에서 유일하게 활성화된 소켓인 경우\n프로그램이 종료될 수 있게 할 것이다. 소켓에 이미 unref
가 호출됐다면 다시 unref
를 호출해도\n아무런 영향이 없을 것이다.\n\n
unref
과는 반대로 이전에 unref
된 소켓에 ref
를 호출하면 해당 소켓이 유일하게 남아있는\n소켓인 경우 프로그램이 종료되지 않도록 할 것이다.(기본 동작) 소켓에 이미 ref
를 호출했다면\nref
를 다시 호출하는 것은 아무런 영향이 없을 것이다.\n\n
이 모듈을 접근하려면 require('dns')
를 사용해라. 쓰레드 풀에서 getaddrinfo(3)
를 \n사용하는 dns.lookup
를 제외한 dns 모듈의 모든 메서드들은 C-Ares를 사용한다.\nC-Ares가 getaddrinfo
보다 훨신 더 빠르지만 시스템 리졸버는 다른 프로그램이 어떻게 \n동작하는 지에 더 관려이 있다. 사용자가 net.connect(80, 'google.com')
나 \nhttp.get({ host: 'google.com' })
를 사용하면 dns.lookup
메서드가 사용된다. \n빠르게 다량의 검색을 해야하는 사용자들은 C-Ares를 쓰는 메서드를 사용해야한다. \n\n
다음은 'www.google.com'
를 처리하고 반대로 반환된 IP 주소를 도메인으로 처리하는 \n예제다.\n\n
var dns = require('dns');\n\ndns.resolve4('www.google.com', function (err, addresses) {\n if (err) throw err;\n\n console.log('addresses: ' + JSON.stringify(addresses));\n\n addresses.forEach(function (a) {\n dns.reverse(a, function (err, domains) {\n if (err) {\n throw err;\n }\n\n console.log('reverse for ' + a + ': ' + JSON.stringify(domains));\n });\n });\n});
\n",
"methods": [
{
"textRaw": "dns.lookup(domain, [family], callback)",
"type": "method",
"name": "lookup",
"desc": "도메인(예시: 'google.com'
)을 처음으로 찾은 A (IPv4)나 AAAA (IPv6) 레코드로 \n처리한다.\nfamily
는 정수 4
나 6
이 될 수 있다. 기본값은 Ip v4와 v6 주소 패밀리 둘 다를 \n의미하는 null
이다.\n\n
콜백은 (err, address, family)
아규먼트를 받는다. address
아규먼트는 IP v4나\nIP v6 주소의 문자열 표현이다. family
아규먼트는 정수 4나 6이고 address
의 \n패밀리를 나타낸다. (이 값은 필수적으로 lookup
에 전달해야 하는 값은 아니다.)\n\n\n
도메인(예시: 'google.com'
)을 rrtype에 지정한 레코드 종류의 배열로 처리한다. \n유효한 rrtype은 'A'
(기본값인 IPV4 주소), 'AAAA'
(IPV6 주소), \n'MX'
(메일 교환 레코드), 'TXT'
(텍스트 레코드), 'SRV'
(SRV 레코드), \n'PTR'
(반대로 IP 검색에 사용된다.), 'NS'
(네임서버 레코드), \n'CNAME'
(공인된 이름(canonical name) 레코드)다.\n\n
콜백은 (err, addresses)
아규먼트다. addresses
에서 각 아이템의 타입은 \n레코드 타입으로 결정되고 아래 대응하는 검색 메서드의 문서에서 설명한다.\n\n
오류가 있을 때 err
는 아래 목록에 있는 오류코드 중 하나인\nerr.code
가 있는 Error
객체다.\n\n\n
dns.resolve()
와 같지만 IPv4 조회(A
레코드)에만 사용한다.\naddresses
는 IPv4 주소의 배열이다. (예시: \n['74.125.79.104', '74.125.79.105', '74.125.79.106']
)\n\n
dns.resolve4()
와 같지만 IPv6 조회(AAAA
레코드)에만 사용한다.\n\n\n
dns.resolve()
와 같지만 메일 교환 조회(MX
레코드)에만 사용한다.\n\n
addresses
는 MX 레코드의 배열이다. 각 레코드는 우선순위와 교환속성을 가진다.\n(예시: [{'priority': 10, 'exchange': 'mx.example.com'},...]
)\n\n
dns.resolve()
와 같지만 텍스트 조회(TXT
레코드)에만 사용한다.\naddresses
는 domain
에서 사용가능한 텍스트 레코드의 배열이다. \n(예시: ['v=spf1 ip4:0.0.0.0 ~all']
)\n\n
dns.resolve()
와 같지만 서비스 레코드(SRV
레코드)에만 사용한다. \naddresses
는 domain
에서 사용가능한 SRV 레코드의 배열이다. SRV 레코드의 프로퍼티들은 \n우선순위, 중요도, 포트, 이름이다. (예시: \n[{'priority': 10, {'weight': 5, 'port': 21223, 'name': 'service.example.com'}, ...]
)\n\n
dns.resolve()
와 같지만 네임서버 레코드(NS
레코드)에만 사용한다.\naddresses
는 domain
에서 사용가능한 네임서버 레코드의 배열이다. \n(예시: ['ns1.example.com', 'ns2.example.com']
)\n\n
dns.resolve()
와 같지만 공인된 이름(canonical name) 레코드(CNAME
레코드)에만 \n사용한다. addresses
는 domain
에서 사용가능한 공인된 이름 레코드의 배열이다. \n(예시: ['bar.example.com']
)\n\n
반대로 ip 주소를 도메인명의 배열로 처리한다.\n\n
\n콜백은 (err, domains)
아규먼트를 받는다.\n\n
오류가 있을 때 err
는 아래 목록에 있는 오류코드 중 하나인\nerr.code
가 있는 Error
객체다.\n\n
각 DNS 조회는 다음 오류코드 중 하나를 반환할 수 있다.\n\n
\ndns.NODATA
: DNS 서버가 데이터가 없다는 응답함.dns.FORMERR
: DNS 서버가 쿼리의 형식이 잘못되었다고 응답함.dns.SERVFAIL
: DNS 서버가 일반적인 실패를 반환함.dns.NOTFOUND
: 도메인 명을 못 찾음.dns.NOTIMP
: DNS 서버가 요청된 작업을 구현하지 않음.dns.REFUSED
: DNS 서버가 조회를 거절함.dns.BADQUERY
: 형식이 잘못된 DNS 조회.dns.BADNAME
: 형식이 잘못된 도메인명.dns.BADFAMILY
: 지원되지 않는 주소 패밀리.dns.BADRESP
: 형식이 잘못된 DNS 응답.dns.CONNREFUSED
: DNS 서버에 접속할 수 없음.dns.TIMEOUT
: DNS 서버에 접속하는 동안 타임아웃 발생.dns.EOF
: 파일의 끝.dns.FILE
: 파일을 읽는 중 오류발생.dns.NOMEM
: Out of memory.dns.DESTRUCTION
: 채널이 파괴됨.dns.BADSTR
: 형식이 잘못된 문자열.dns.BADFLAGS
: 허용되지 않는 플래그가 지정됨.dns.NONAME
: 주어진 호스트명이 숫자가 아님.dns.BADHINTS
: 허용되지 않는 힌트 플래그가 지정됨.dns.NOTINITIALIZED
: c-ares 라이브러리 초기화가 아직 수행되지 않음.dns.LOADIPHLPAPI
: iphlpapi.dll을 로딩하는 데 오류발생.dns.ADDRGETNETWORKPARAMS
: GetNetworkParams 함수를 찾을 수 없음.dns.CANCELLED
: DNS 조회가 취소됨.HTTP 서버와 클라이언트를 사용하려면 require('http')
를 사용해라.\n\n
Node의 HTTP 인터페이스는 전통적으로 다루기 어려웠던 프로토콜의 많은 기능들을\n지원하려고 디자인되었다. 특히 크고 청크로 인코딩 될수 있는 메시지들이다.\n인터페이스는 전체 요청이나 응답을 버퍼에 넣지 않는다. 사용자는 스트림 데이터를\n버퍼에 넣을 수 있다.\n\n
\nHTTP 메시지 헤더는 다음과 같은 객체로 표현된다.\n\n
\n{ 'content-length': '123',\n 'content-type': 'text/plain',\n 'connection': 'keep-alive',\n 'accept': '*/*' }
\n키는 소문자로 쓰고 값은 수정되지 않는다.\n\n
\nHTTP 어플리케이션이 가능한 전체 범위를 다 지원하기 위해서 Node의 HTTP API는 상당히\n저수준의 API이다. API는 스트림 핸들링과 메시지 파싱만을 다룬다. 메시지를 헤더와 바디로\n파싱하지만 실제 헤더와 바디는 파싱하지 않는다.\n\n\n
\n", "properties": [ { "textRaw": "`STATUS_CODES` {Object} ", "name": "STATUS_CODES", "desc": "모든 표준 HTTP 응답 상태코드와 짧은 설명의 모음이다.\n예를 들어 http.STATUS_CODES[404] === 'Not Found'
와 같이 할 수 있다.\n\n
모든 HTTP 클라이언트 요청에 기본적으로 사용되는 Agent의 전역 인스턴스다.\n\n\n
\n" }, { "textRaw": "http.IncomingMessage", "name": "IncomingMessage", "desc": "IncomingMessage
객체는 http.Server
나 http.ClientRequest
가 생성하고\n'request'
와 'response'
이벤트에 각각 첫 번째 인자로 전달된다. 응답 상태,\n헤더, 데이터에 접근할 때 사용한다.\n\n
이는 [Readable Stream][] 인터페이스를 구현했고 다음의 추가적인 이벤트, 메서드,\n프로퍼티를 구현했다.\n\n
\n", "events": [ { "textRaw": "Event: 'close'", "type": "event", "name": "close", "desc": "function () { }
\n\n
response.end()
가 호출되거나 플러시할 수 있기 전에 의존하는 연결이 종료되었다는\n것을 나타낸다.\n\n
'end'
처럼 이 이벤트는 응답마다 딱 한번만 발생한다.\n자세한 내용은 [http.ServerResponse][]의 'close'
이벤트를 봐라.\n\n
서버 요청의 경우 HTTP 버전을 클라이언트가 보낸다. 클라이언트 응답의 경우 서버에 연결된\nHTTP 버전이다. 아마 '1.1'
나 '1.0'
둘 중 하나일 것이다.\n\n
response.httpVersionMajor
는 첫번째 정수이고\nresponse.httpVersionMinor
는 두번째 정수이다.\n\n
요청/응답 헤더 객체.\n\n
\n읽기 전용인 헤더 이름과 값의 맵이다. 헤더 이름은 소문자이다.\n예제:\n\n
\n// Prints something like:\n//\n// { 'user-agent': 'curl/7.22.0',\n// host: '127.0.0.1:8000',\n// accept: '*/*' }\nconsole.log(request.headers);
\n"
},
{
"textRaw": "message.trailers",
"name": "trailers",
"desc": "요청/응답의 trailers 객체다. 'end' 이벤트 후에만 존재한다.\n\n
\n" }, { "textRaw": "message.method", "name": "method", "desc": "http.Server
에서 얻은 요청에만 유효하다.\n\n
요청 메서드의 문자열 표현. 읽기 전용이다.\n예제: 'GET'
, 'DELETE'
.\n\n
http.Server
에서 얻은 요청에만 유효하다..\n\n
요청 URL 문자열. 이 값은 실제 HTTP 요청에 있는 URL만 답고 있다.\n요청이 다음과 같다면\n\n
\nGET /status?name=ryan HTTP/1.1\\r\\n\nAccept: text/plain\\r\\n\n\\r\\n
\nrequest.url
는 다음과 같을 것이다.\n\n
'/status?name=ryan'
\nURL을 각 부분으로 파싱하고 싶다면 require('url').parse(request.url)
를\n사용할 수 있다. 예제:\n\n
node> require('url').parse('/status?name=ryan')\n{ href: '/status?name=ryan',\n search: '?name=ryan',\n query: 'name=ryan',\n pathname: '/status' }
\n쿼리스트링에서 파라미터를 추출하고 싶다면 require('querystring').parse
함수를\n사용하거나 require('url').parse
에 두번째 인자로 true
를 전달할 수 있다.\n예제:\n\n
node> require('url').parse('/status?name=ryan', true)\n{ href: '/status?name=ryan',\n search: '?name=ryan',\n query: { name: 'ryan' },\n pathname: '/status' }
\n"
},
{
"textRaw": "message.statusCode",
"name": "statusCode",
"desc": "http.ClientRequest
에서 얻은 응답에만 유효하다.\n\n
3자리 숫자의 HTTP 응답 상태코드. 예를 들면 404
등이다.\n\n
연결과 관련된 net.Socket
객체이다.\n\n
HTTPS를 지원한다면 클라이언트의 자세한 인증을 얻을 때\nrequest.connection.verifyPeer()와 request.connection.getPeerCertificate()를\n사용해라.\n\n\n
\n" } ], "methods": [ { "textRaw": "message.setTimeout(msecs, callback)", "type": "method", "name": "setTimeout", "signatures": [ { "params": [ { "textRaw": "`msecs` {Number} ", "name": "msecs", "type": "Number" }, { "textRaw": "`callback` {Function} ", "name": "callback", "type": "Function" } ] }, { "params": [ { "name": "msecs" }, { "name": "callback" } ] } ], "desc": "message.connection.setTimeout(msecs, callback)
를 호출한다.\n\n
새로운 웹서버 객체를 반환한다.\n\n
\nrequestListener
는 자동으로 'request'
이벤트에 추가되는\n함수다.\n\n
이 함수는 폐기되었다. 대신에 [http.request()][]를 사용해라.\n새로운 HTTP 클라이언트를 구성한다. port
와 host
는 연결할 서버를 가리킨다.\n\n
Node는 HTTP 요청에 대한 연결을 서버당 여러 개 유지하고 있다. 이 함수는 투명하게\n요청을 진행한다.\n\n
\noptions
은 객체나 문자열이 될 수 있다. options
이 문자열이면 자동으로\n[url.parse()][]를 사용해서 파싱한다.\n\n
옵션:\n\n
\nhost
: 요청을 보낼 서버의 도메인 명이나 IP 주소. 기본값은 'localhost'
이다.hostname
: url.parse()
를 지원하려면 host
보다 hostname
가 낫다.port
: 원격서버의 포트. 기본포트는 80포트이다.localAddress
: 에트워크 연결에 바인딩할 로컬 인터페이스.socketPath
: Unix 도메인 소켓 (host:port난 socketPath 중 하나를 사용한다)method
: HTTP 요청 메서드를 지정하는 문자열. 기본값은 'GET'
이다.path
: 요청 경로. 기본값은 '/'
이다. 필요하다면 쿼리스트링도 포함시킨다.\n예시. '/index.html?page=12'
headers
: 요청 헤더를 담고 있는 객체.auth
: 기본 인증으롤 예를 들면 인증헤더를 계산하는 'user:password'
이다.agent
: [Agent][] 동작을 제어한다. 에이전트를 사용했을 때 요청은\n기본적으로 Connection: keep-alive
가 될 것이다. 가능한 값은 다음과 같다.undefined
(default): 이 호스트와 포트에 대한 [global Agent][]를 사용한다.Agent
object: 명시적으로 Agent
에 전달된 객체를 사용한다.false
: Agent와 함께 연결 풀을 사용하지 않는다. 기본값은\nConnection: close
에 요청한다.http.request()
는 http.ClientRequest
클래스의 인스턴스를 리턴한다.\nClientRequest
인스턴스는 쓰기가 가능한 스트림이다. POST 요청으로 파일을\n업로드해야 한다면 ClientRequest
객체에 작성한다.\n\n
예제:\n\n
\nvar options = {\n hostname: 'www.google.com',\n port: 80,\n path: '/upload',\n method: 'POST'\n};\n\nvar req = http.request(options, function(res) {\n console.log('STATUS: ' + res.statusCode);\n console.log('HEADERS: ' + JSON.stringify(res.headers));\n res.setEncoding('utf8');\n res.on('data', function (chunk) {\n console.log('BODY: ' + chunk);\n });\n});\n\nreq.on('error', function(e) {\n console.log('problem with request: ' + e.message);\n});\n\n// write data to request body\nreq.write('data\\n');\nreq.write('data\\n');\nreq.end();
\n예제에서 req.end()
를 호출했다. 요청 바디에 쓰여진 데이터가 없다고 하더라도 요청이\n완료되었다는 의미로 http.request()
에서 항상 req.end()
를 반드시 호출해야 한다.\n\n
요청중에 어떤 오류가 있다면(DNS 처리나 TCP 레벨의 오류, 실제 HTTP 파싱 오류 등등)\n반환된 요청 객체에서 'error'
이벤트가 발생한다.\n\n
알아야 할 몇가지 특별한 헤더가 있다.\n\n
\n'Connection: keep-alive'를 전송하면 서버와의 연결을 다음 요청까지 유지해야 한다는\n것을 Node에 알려줄 것이다.
\n'Content-length' 헤더를 전송하면 기본 chunked 인코딩을 사용하지 않을 것이다.
\n'Expect'헤더를 전송하면 즉시 요청헤더를 보낼 것이다. 'Expect: 100-continue'를 보낼\n때는 보통 타임아웃과 continue
이벤트에 대한 linten을 둘 다 설정해야 한다. 더\n자세한 내용은 RFC2616의 섹션 8.2.3을 봐라.
인증헤더를 전송하면 기본 인증을 계산하는 auth
옵션을 덮어쓸 것이다.
대부분의 요청은 바디가 없는 GET 요청이기 때문에 Node는 이 편리한 메서드를 제공한다.\n이 메서드와 http.request()
간의 유일한 차이점은 자동적으로 메서드를 GET으로 설정하고\nreq.end()
를 호출한다는 점이다.\n\n
예제:\n\n
\nhttp.get("http://www.google.com/index.html", function(res) {\n console.log("Got response: " + res.statusCode);\n}).on('error', function(e) {\n console.log("Got error: " + e.message);\n});
\n",
"signatures": [
{
"params": [
{
"name": "options"
},
{
"name": "callback"
}
]
}
]
}
],
"classes": [
{
"textRaw": "Class: http.Server",
"type": "class",
"name": "http.Server",
"desc": "이 클래스는 다음의 이벤트를 가진 [EventEmitter][]다.\n\n
\n", "events": [ { "textRaw": "Event: 'request'", "type": "event", "name": "request", "desc": "function (request, response) { }
\n\n
요청이 있을 때마다 발생한다. 연결마다 여러번의 요청이 있을 수 있다.(keep-alive\n연결인 경우)\n request
는 http.IncomingMessage
의 인스턴스이고 response
는\n http.ServerResponse
의 인스턴스다.\n\n
function (socket) { }
\n\n
새로운 TCP 스트림이 생성되었을 때 발생한다. socket
은 net.Socket
타입의\n 객체다. 보통 사용자들은 이 이벤트에 접근하지 않을 것이다. 특히 프로토콜 파서가 소켓에 연결되는\n 방법 때문에 소켓이 readable
이벤트를 발생시키지 않을 것이다. socket
도\n request.connection
에서 접근할 수 있다.\n\n
function () { }
\n\n
서버가 닫혔을 때 발생한다.\n\n
\n", "params": [] }, { "textRaw": "Event: 'checkContinue'", "type": "event", "name": "checkContinue", "desc": "function (request, response) { }
\n\n
http Expect: 100-continue 헤더를 가진 요청을 받을 때마다 발생한다.\n이 이벤트가 바인딩되지 않았다면 서버는 자동적으로 적절한 100 Continue로 응답할\n것이다.\n\n
\n이 이벤트를 다루면 클라이언트가 계속해서 요청바디를 보내야 한다면\nresponse.writeContinue
호출하고 클라이언트가 요청 바디를 계속 보내지 않는다면\n적절한 HTTP 응답(예시: 400 Bad Request)을 생성한다.\n\n
function (request, socket, head) { }
\n\n
클라이언트가 http CONNECT 메서드를 요청할 때마다 발생한다. 이 이벤트에 등록된\n리스너가 없으면 CONNECT 메서드를 요청한 클라이언트의 연결이 닫힐 것이다.\n\n
\nrequest
는 request 이벤트와 같이 http 요청의 아규먼트다.socket
는 서버와 클라이언트 간의 네트워크 소켓이다.head
는 터널링 스트림의 첫 패킷인 Buffer의 인스턴스다. 이 값은 비어있을 것이다.이 이벤트가 발생한 후 요청의 소켓은 data
이벤트 리스너를 가지지 않을 것이다.\n즉, 해당 소켓으로 서버에 보낸 데이터를 다루려면 리스너에 바인딩해야 한다.\n\n
function (request, socket, head) { }
\n\n
클라이언트가 http 업그래이드를 요청할 때마다 발생한다. 이 이벤트가 바인딩되지 않았다면\n업그래이드를 요청하는 클라이언트는 닫힌 연결을 가질 것이다.\n\n
\nrequest
은 요청이벤트에 있는 것처럼 http 요청의 아규먼트다.socket
은 서버와 클라이언트 사이의 네트워크 소켓이다.head
는 Buffer의 인스턴스다. 업그래이드된 스트림의 첫 패킷이고 비어있을 수도 있다.이 이벤트가 발생한 후에 요청의 소켓은 data
이벤트 리스너를 갖지 않을 것이다. 이는\n해당 소켓으로 서버에 보내는 메시지를 다루기 위해서는 소켓에 바인딩할 필요가 있다는 의미이다.\n\n
function (request, socket, head) { }
\n\n
function (exception, socket) { }
\n\n
클라이언트 연결에서 'error' 이벤트가 발생하면 이 이벤트가 진행된다.\n\n
\nsocket
은 오류가 발생한 net.Socket
객체이다.\n\n
지정한 hostname과 port에서 열결을 받아들이기 시작한다. hostname을 생락하면 서버는\nIPv4 주소(INADDR_ANY
)에서 들어오는 연결을 모두 받아들일 것이다.\n\n
유닉스 소켓에 바인딩하려면 port와 hostname 대신에 파일명을 전달한다.\n\n
\n백로그는 지연된는 연결 큐의 최대길이이다.\n실제 길이는 리눅스의 tcp_max_syn_backlog
와 somaxconn
같은 sysctl 설정을 통해\nOS가 결정한다. backlog의 기본값은 511이다.(512가 아니다)\n\n
이 함수는 비동기 함수다. 마지막 파라미터 callback
은\n['listening'][] 이벤트의 리스터로 추가될 것이다.\n[net.Server.listen(port)][]도 참고해 봐라.\n\n\n
전달한 path
에서 연결을 받아들이는 UNIX 소켓 서버를 시작한다.\n\n
이 함수는 비동기 함수다. 마지막 파라미터 callback
은\n['listening'][] 이벤트의 리스너로 추가될 것이다.\n[net.Server.listen(path)][]도 참고해라.\n\n\n
handle
객체는 서버나 소켓(의존하는 _handle
멤버를 가진 어떤 것이든)으로\n설정하거나 {fd: <n>}
객체로 설정할 수 있다.\n\n
이 함수는 서버가 지정한 핸들에서 연결을 받아들이도록 하지만 파일 디스크립터나\n핸들이 이미 포트나 도메인 소켓에 바인딩되어 있다고 가정한다.\n\n
\n윈도우는 파일 디스크립터에서 요청을 받아들이는 것을 지원하지 않는다.\n\n
\n이 함수는 비동기 함수다. 마지막 파라미터 callback
은\n'listening' 이벤트의 리스너로 추가될 것이다.\nnet.Server.listen()도 참고해라.\n\n
Stops the server from accepting new connections. See [net.Server.close()][].\n서버가 새로운 연결을 받아들이는 것을 멈춘다. [net.Server.close()][]를 참고해라.\n\n\n
\n", "signatures": [ { "params": [ { "name": "callback", "optional": true } ] } ] }, { "textRaw": "server.setTimeout(msecs, callback)", "type": "method", "name": "setTimeout", "signatures": [ { "params": [ { "textRaw": "`msecs` {Number} ", "name": "msecs", "type": "Number" }, { "textRaw": "`callback` {Function} ", "name": "callback", "type": "Function" } ] }, { "params": [ { "name": "msecs" }, { "name": "callback" } ] } ], "desc": "소켓의 타임아웃 값을 설정하고 타임아웃이 발생하면 인자로 소켓을 넘기면서 Server 객체에\n'timeout'
이벤트를 발생시킨다.\n\n
Server 객체에 'timeout'
이벤트 리스너가 있으면 타임아웃이 발생한 소켓을 인자로 전달하면서\n이벤트 리스너를 호출할 것이다.\n\n
기본적으로 Server의 타임아웃 값은 2분이고 타임아웃이 발생했을 때 소켓을 자동적으로 없앤다.\n하지만 Server의 'timeout'
이벤트에 콜백을 할당하면 소켓 타임아웃을 처리하는 책임은\n개발자에게 있다.\n\n
들어오는 헤더의 최대 수를 제한하고 기본값은 1000이다. 이 값을 0으로 설정하면\n제한을 두지 않는다.\n\n
\n" }, { "textRaw": "`timeout` {Number} Default = 120000 (2 minutes) ", "name": "timeout", "desc": "소켓이 타임아웃되었다고 판단하기 전에 활동하지 않는 밀리초 시간.\n\n
\n소켓 타임아웃 로직이 연결에 설정되므로 이 값을 변경해도 서버에 이미 존재하는 연결이 아닌\n새로운 연결에만 영향을 끼칠 것이다.\n\n
\n들어오는 요청에 자동 타임아웃 동작을 모두 비활성화하려면 0으로 설정해라.\n\n
\n", "shortDesc": "Default = 120000 (2 minutes)" } ] }, { "textRaw": "Class: http.ServerResponse", "type": "class", "name": "http.ServerResponse", "desc": "사용자가 아니라 HTTP 서버가 내부적으로 생성하는 객체다. 'request'
이벤트의\n두번째 파라미터로 전달된다.\n\n
응답은 [Writable Stream][] 인터페이스를 구현했다.\n이 클래스는 다음의 이벤트를 가지고 있는 [EventEmitter][]이다.\n\n
\n", "events": [ { "textRaw": "Event: 'close'", "type": "event", "name": "close", "desc": "function () { }
\n\n
response.end()
가 호출되기 전이나 플러시할 수 있을 때 의존하는 연결을\n종료했다는 것을 나타낸다.\n\n
클라이언트에 요청 바디가 보내질 것이라는 것을 나타내는 HTTP/1.1 100 Continue\n메시지를 보낸다. Server
의 ['checkContinue'][] 이벤트를 봐라.\n\n
요청에 응답 헤더를 보낸다. 상태코드는 404
같은 3자리 수의 HTTP 상태코드이다.\n마지막 파리미터인 headers
는 응답 헤더다. 선택적으로 두번째 파라미터에 사람이 읽을 수\n있는 reasonPhrase
를 전달할 수 있다.\n\n
예제:\n\n
\nvar body = 'hello world';\nresponse.writeHead(200, {\n 'Content-Length': body.length,\n 'Content-Type': 'text/plain' });
\n이 메서드는 한 메시지에서 딱 한번만 호출되어야 하고 response.end()
가 호출되기 전에\n호출되어야 한다.\n\n
이 메서드가 호출되기 전에 response.write()
나 response.end()
를 호출한다면\n암묵적이고 변할 가능성이 있는 헤더가 계산해서 이 함수를 호출할 것이다.\n\n
Note: 해당 Content-Length는 문자가 아니라 바이트로 주어진다. 문자열 'hello world'
는\n단일 바이트의 문자만 가지고 있기 때문에 위의 예제는 동작한다. 바디에 더 높은 코드의 문자가\n있다면 주어진 인코딩으로 바이트의 수를 결정하는데 Buffer.byteLength()
를 사용할 것이다.\n그리고 Node는 전송된 바디의 길이와 Content-Length가 같은지 같지 않은지 확인하지 않는다.\n\n
Socket의 타임아웃값을 msecs
로 설정한다. 콜백을 지정하면 응답 객체의\n'timeout'
이벤트 리스너로 추가한다.\n\n
요청, 응답, 서버에 'timeout'
리스너를 추가하지 않으면 타임아웃되었을 때 소켓을 제거한다.\n요청, 응답, 서버의 'timeout'
이벤트에 핸들러를 할당하면 타임아웃된 소켓을 처리하는 것은\n개발자의 몫이다.\n\n
암묵적인 헤더에 단일 헤더값을 설정한다. 전송할 헤더에 이미 이 헤더가 존재한다면 해당 값은\n덮어써질 것이다. 같은 이름을 가진 여러 헤더를 전송해야 한다면 여기에 문자열 배열을\n사용해라.\n\n
\n예제:\n\n
\nresponse.setHeader("Content-Type", "text/html");
\n또는\n\n
\nresponse.setHeader("Set-Cookie", ["type=ninja", "language=javascript"]);
\n",
"signatures": [
{
"params": [
{
"name": "name"
},
{
"name": "value"
}
]
}
]
},
{
"textRaw": "response.getHeader(name)",
"type": "method",
"name": "getHeader",
"desc": "이미 큐에 들어갔지만 아직 클라이언트에는 보내지 않은 헤더를 읽는다. 이름이 대소문자를\n구분한다는 점에 주의해라. 이 함수는 헤더가 암묵적으로 플러시 되기 전에만 호출할 수 있다.\n\n
\n예제:\n\n
\nvar contentType = response.getHeader('content-type');
\n",
"signatures": [
{
"params": [
{
"name": "name"
}
]
}
]
},
{
"textRaw": "response.removeHeader(name)",
"type": "method",
"name": "removeHeader",
"desc": "암묵적으로 보내려고 큐에 있는 헤더를 제거한다.\n\n
\n예제:\n\n
\nvar contentType = response.getHeader('content-type');
\n",
"signatures": [
{
"params": [
{
"name": "name"
}
]
}
]
},
{
"textRaw": "response.write(chunk, [encoding])",
"type": "method",
"name": "write",
"desc": "이 메서드는 호출하고 response.writeHead()
는 호출하지 않았다면 암묵적인 헤더 모드로\n바꾸고 암묵적인 헤더를 플러시할 것이다.\n\n
이 메서드는 응답 바디의 청크를 전송한다. 바디의 연속적인 부분을 제공하기 위해 이 함수를\n여러번 호출할 수 있다.\n\n
\nchunk
는 문자열이나 버퍼가 될 수 있다. chunk
는 문자열이면 두번째 파라미터로 chunk
를\n어떻게 바이트 스트림으로 인코딩할 것인지 지정한다. encoding
의 기본값은 'utf8'
이다.\n\n
Note: 이 메서드는 로우(raw) HTTP 바디이고 사용될 수도 있는 고수준의 multi-part 바디\n인코딩에서는 아무것도 하지 않는다.\n\n
\n처음 response.write()
를 호출하면 버퍼되어 있는 헤더 정보와 첫 바디를 클라이언트에 보낼\n것이다. 두번째로 response.write()
를 호출하면 Node는 데이터를 스트리밍 할 것이라고\n가정하고 나눠서 전송한다. 즉, 응답은 바디의 첫번째 청크에 버퍼된다.\n\n
전체 데이터가 성공적으로 커널버퍼에 플러시되면 true
를 반환한다. 전체 혹은 일부의 데이터가\n사용자 메모리에 큐로 들어가면 false
를 반환한다.\n버퍼가 다시 여유가 생기면 'drain'
가 발생할 것이다.\n\n
이 메서드는 HTTP trailing headers(헤더이지만 메시지 끝에 오는 헤더)를 응답에\n추가한다.\n\n
\n응답에 chunked 인코딩을 사용한 경우에만 Trailers가 발생할 것이다. chunked 인코딩이\n아니라면(요청이 HTTP/1.0인 등등) 이 헤더는 경고없이 버려질 것이다.\n\n
\n헤더의 값에 헤더 필드들의 리스트로 trailers를 발생시키려면 HTTP는 Trailer
를 필요로 한다.\n\n
response.writeHead(200, { 'Content-Type': 'text/plain',\n 'Trailer': 'Content-MD5' });\nresponse.write(fileData);\nresponse.addTrailers({'Content-MD5': "7895bf4b8828b55ceaf47747b4bca667"});\nresponse.end();
\n",
"signatures": [
{
"params": [
{
"name": "headers"
}
]
}
]
},
{
"textRaw": "response.end([data], [encoding])",
"type": "method",
"name": "end",
"desc": "이 메서드는 모든 응답 헤더와 바디를 보냈다고 서버에 신호를 보낸다. 해당 서버는 이 메시지를\n완료된 것으로 간주해야 한다. response.end()
메서드는 반드시 각 응답마다 호출되어야\n한다.\n\n
data
를 지정하면 response.write(data, encoding)
를 호출한 다음에 response.end()
를\n호출한 것과 같다.\n\n\n
(명시적으로 response.writeHead()
를 호출하지 않고) 암묵적인 헤더를 사용하는 경우 헤더가 플러시됐을\n때 클라이언트에 보낼 상태코드를 이 프로퍼티가 제어한다.\n\n
예제:\n\n
\nresponse.statusCode = 404;
\n응답해더가 클라이언트에 보내진 후 이 프로퍼티는 보낸 상태코드를 나타낸다.\n\n
\n" }, { "textRaw": "response.headersSent", "name": "headersSent", "desc": "불리언 값(읽기 전용). 헤더를 보냈으면 true이고 보내지 않았으면 false이다.\n\n
\n" }, { "textRaw": "response.sendDate", "name": "sendDate", "desc": "이 값이 ture이면 이미 헤더에 Date 헤더가 존재하지 않으며 자동으로 Date 헤더를\n생성해서 응답에 보낼 것이다. 기본값은 true이다.\n\n
\n이 값은 테스트할 때만 사용하지 않도록 해야 한다. HTTP는 응답에 Date 헤더를 필요로\n한다.\n\n
\n" } ] }, { "textRaw": "Class: http.Agent", "type": "class", "name": "http.Agent", "desc": "node 0.5.3이상부터는 HTTP 클라이언트 요청의 풀링 소켓에 사용하는 HTTP 에이전트의\n새로운 구현체가 있다.\n\n
\n그 이전에 단일 에이전트 인스턴스는 하나의 host+port에 대한 풀을 도왔다. 지금의 구현체는\n많은 수의 호스트에 대한 소켓을 가지고 있다.\n\n
\n현재 HTTP 에이전트도 기본 클라이언트 요청은 Connection:keep-alive 를 사용한다. 소켓에서\n대기하고 있는 지연된 HTTP 요청이 없다면 해당 소켓을 닫는다. 즉 node의 풀은 부하가 있을 때\nkeep-alive 이점을 가지지만 여전히 keep-alive를 사용하는 HTTP 클라이언트를 개발자가\n수동으로 닫을 필요가 없다.\n\n
\n소켓이 "close" 이벤트나 특수한 "agentRemove" 이벤트를 발생시켰을 때 이에전트의 풀에서\n소켓을 제거한다. 다시 말하면 HTTP 요청을 오랫동안 열어놓고 유지하고 HTTP 요청이 풀에\n유지되기를 원하지 않는다면 다음과 같이 할 수 있다.\n\n
\nhttp.get(options, function(res) {\n // Do stuff\n}).on("socket", function (socket) {\n socket.emit("agentRemove");\n});
\n대신 agent:false
를 사용해서 완전히 풀링을 사용하지 않을 수도 있다.\n\n
http.get({hostname:'localhost', port:80, path:'/', agent:false}, function (res) {\n // Do stuff\n})
\n",
"properties": [
{
"textRaw": "agent.maxSockets",
"name": "maxSockets",
"desc": "기본적으로 5로 설정되어 있다. 에이전트가 얼마나 많은 동시 소켓을 호스트당 열 수 있는지를\n결정한다.\n\n
\n" }, { "textRaw": "agent.sockets", "name": "sockets", "desc": "Agent가 현재 사용하고 있는 소켓의 배열을 담고 있는 객체다. 수정하면 안된다.\n\n
\n" }, { "textRaw": "agent.requests", "name": "requests", "desc": "소켓에 아직 할당되지 않은 요청의 큐를 담고 있는 객체다. 수정하면 안된다.\n\n
\n" } ] }, { "textRaw": "Class: http.ClientRequest", "type": "class", "name": "http.ClientRequest", "desc": "내부적으로 생성하고 http.request()
가 반환하는 객체다. 헤더는 이미 큐에 들어간\n처리중인 요청을 나타낸다. setHeader(name, value)
, getHeader(name)
,\nremoveHeader(name)
API를 사용해서 헤더를 여전히 변경할 수 있다. 실제 헤더는\n첫 데이터 청크와 함게 보내거나 연결이 닫힐 때 보낼 것이다.\n\n
응답을 받으려면 응답 객체에 'response'
에 대한 리스너를 추가해라. 'response'
는\n응답 헤더를 받았을 때 요청 객체에서 발생할 것이다. 'response'
이벤트는\nhttp.IncomingMessage
인스턴스를 아규먼트로 받아서 실행된다.\n\n
'response'
이벤트 가운데 응답 객체에 리스너들을 추가할 수 있다. 특히 'data'
\n이벤트를 받기 위해 추가할 수 있다.\n\n
'response'
핸들러를 추가하지 않았다면 응답을 완전히 버릴 것이다. 하지만 'response'
이벤트\n핸들러를 추가했다면 'readable'
이벤트가 발생할 때마다 response.read()
를 호출하거나\n'data'
핸들러를 추가하거나 .resume()
메서드를 호출해서 응답객체의 데이터를 반드시\n소비해야 한다. 데이터가 소비될 때까지 'end'
이벤트는 발생하지 않을 것이다. 또한, 데이터를 읽는\n동안 메모리를 소비하므로 'process out of memory' 오류가 발생할 수도 있다.\n\n
Note: Node는 Content-Length와 전송된 바디의 길이가 같은지 같지 않은지 확인하지\n않는다.\n\n
\n요청은 [Writable Stream][] 인터페이스를 구현했다.\n이는 다음 이벤트를 가진 [EventEmitter][]이다.\n\n
\n", "events": [ { "textRaw": "Event 'response'", "type": "event", "name": "response", "desc": "function (response) { }
\n\n
해당 요청에 대한 응답을 받았을 때 발생한다. 이 이벤트는 딱 한번만 발생한다. response
아규먼트는\nhttp.IncomingMessage
의 인스턴스가 될 것이다.\n\n
옵션:\n\n
\nhost
: 요청을 보낼 서버의 도메인명이나 IP 주소다.port
: 원격 서버의 포트.socketPath
: Unix 도메인 소켓 (host:port나 socketPath 중 하나를 사용한다)function (socket) { }
\n\n
해당 요청에 소켓이 할당된 후에 발생한다.\n\n
\n", "params": [] }, { "textRaw": "Event: 'connect'", "type": "event", "name": "connect", "desc": "function (response, socket, head) { }
\n\n
CONNECT 메서드의 요청에 서버가 응답할 때마다 발생한다. 이 이벤트에 등록된 리스너가 없으면\nCONNECT 메서드를 받는 클라이언트의 연결을 닫힐 것이다.\n\n
\n클라이언트와 서버가 어떻게 connect
이벤트를 받는지 보여준다.\n\n
var http = require('http');\nvar net = require('net');\nvar url = require('url');\n\n// HTTP 터널링 프록시를 생성한다\nvar proxy = http.createServer(function (req, res) {\n res.writeHead(200, {'Content-Type': 'text/plain'});\n res.end('okay');\n});\nproxy.on('connect', function(req, cltSocket, head) {\n // 원래의 서버로 연결한다\n var srvUrl = url.parse('http://' + req.url);\n var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, function() {\n cltSocket.write('HTTP/1.1 200 Connection Established\\r\\n' +\n 'Proxy-agent: Node-Proxy\\r\\n' +\n '\\r\\n');\n srvSocket.write(head);\n srvSocket.pipe(cltSocket);\n cltSocket.pipe(srvSocket);\n });\n});\n\n// 이제 프록시서버가 동작한다\nproxy.listen(1337, '127.0.0.1', function() {\n\n // 터널링 프록시에 요청을 만든다\n var options = {\n port: 1337,\n hostname: '127.0.0.1',\n method: 'CONNECT',\n path: 'www.google.com:80'\n };\n\n var req = http.request(options);\n req.end();\n\n req.on('connect', function(res, socket, head) {\n console.log('got connected!');\n\n // HTTP 터널을 통해 요청을 만든다\n socket.write('GET / HTTP/1.1\\r\\n' +\n 'Host: www.google.com:80\\r\\n' +\n 'Connection: close\\r\\n' +\n '\\r\\n');\n socket.on('data', function(chunk) {\n console.log(chunk.toString());\n });\n socket.on('end', function() {\n proxy.close();\n });\n });\n});
\n",
"params": []
},
{
"textRaw": "Event: 'upgrade'",
"type": "event",
"name": "upgrade",
"desc": "function (response, socket, head) { }
\n\n
업그레이드 요청에 서버가 응답할 때마다 발생한다. 이 이벤트가 바인딩되어 있지 않으면\n업그레이드 헤더를 받는 클라이언트는 연결이 닫힐 것이다.\n\n
\nupgrade
이벤트를 어떻게 바인딩하는 지 보여주는 클라이언트와 서버 쌍의 예제다:\n\n
var http = require('http');\n\n// HTTP 서버 생성\nvar srv = http.createServer(function (req, res) {\n res.writeHead(200, {'Content-Type': 'text/plain'});\n res.end('okay');\n});\nsrv.on('upgrade', function(req, socket, head) {\n socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\\r\\n' +\n 'Upgrade: WebSocket\\r\\n' +\n 'Connection: Upgrade\\r\\n' +\n '\\r\\n');\n\n socket.pipe(socket); // echo back\n});\n\n// 이제 서버가 동작한다\nsrv.listen(1337, '127.0.0.1', function() {\n\n // 요청 생성\n var options = {\n port: 1337,\n hostname: '127.0.0.1',\n headers: {\n 'Connection': 'Upgrade',\n 'Upgrade': 'websocket'\n }\n };\n\n var req = http.request(options);\n req.end();\n\n req.on('upgrade', function(res, socket, upgradeHead) {\n console.log('got upgraded!');\n socket.end();\n process.exit(0);\n });\n});
\n",
"params": []
},
{
"textRaw": "Event: 'continue'",
"type": "event",
"name": "continue",
"desc": "function () { }
\n\n
보통 요청이 'Expect: 100-continue'를 답고 있기 때문에서버가 '100 Continue' HTTP\n응답을 보냈을 때 발생한다. 이는 클라이언트가 요청 바디를 보내야 한다는 것을 알려준다.\n\n
\n", "params": [] } ], "methods": [ { "textRaw": "request.write(chunk, [encoding])", "type": "method", "name": "write", "desc": "바디의 청크를 전송한다. 이 메서드를 여러번 호출해서\n사용자는 요청 바디를 서버에 스트리밍할 수 있다. -\n이 경우 요청을 생성할 때\n['Transfer-Encoding', 'chunked']
헤더를\n사용하기를 제안한다.\n\n
chunk
아규먼트는 [Buffer][]나 문자열이 되어야 한다.\n\n
encoding
아규먼트는 선택사항이고 chunk
가 문자열인 경우에만 적용된다.\n기본값은 'utf8'
이다.\n\n\n
요청 전송을 종료한다. 바디의 일부를 보내지 않았다면 스트림으로 플러시할\n것이다. 요청이 청크라면 종료하는 '0\\r\\n\\r\\n'
를 보낼 것이다.\n\n
data
를 지정하면 request.end()
다음에\nrequest.write(data, encoding)
를 호출한 것과 같다.\n\n
요청을 중단한다. (v0.3.8부터 추가되었다.)\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "request.setTimeout(timeout, [callback])", "type": "method", "name": "setTimeout", "desc": "해당 요청에 소켓이 바인딩되고 소켓이 연결되면\n[socket.setTimeout()][]이 호출될 것이다.\n\n
\n", "signatures": [ { "params": [ { "name": "timeout" }, { "name": "callback", "optional": true } ] } ] }, { "textRaw": "request.setNoDelay([noDelay])", "type": "method", "name": "setNoDelay", "desc": "해당 요청에 소켓이 바인딩되고 소켓이 연결되면\n[socket.setNoDelay()][]이 호출될 것이다.\n\n
\n", "signatures": [ { "params": [ { "name": "noDelay", "optional": true } ] } ] }, { "textRaw": "request.setSocketKeepAlive([enable], [initialDelay])", "type": "method", "name": "setSocketKeepAlive", "desc": "해당 요청에 소켓이 바인딩되고 소켓이 연결되면\n[socket.setKeepAlive()][]이 호출될 것이다.\n\n
\n", "signatures": [ { "params": [ { "name": "enable", "optional": true }, { "name": "initialDelay", "optional": true } ] } ] } ] } ], "type": "module", "displayName": "HTTP" }, { "textRaw": "HTTPS", "name": "https", "stability": 3, "stabilityText": "Stable", "desc": "HTTPS는 TLS/SSL를 사용하는 HTTP 프로토콜이다. Node에서 HTTPS는 별도의 모듈로\n구현되었다.\n\n
\n", "classes": [ { "textRaw": "Class: https.Server", "type": "class", "name": "https.Server", "desc": "이 클래스는 tls.Server
의 하위 클래스로 http.Server
와 같은 이벤트를\n발생시킨다. 자세한 내용은 http.Server
를 참고해라.\n\n
[http.Agent][]와 유사한 HTTPS의 Agent 객체.\n자세한 내용은 [https.request()][]를 참고해라.\n\n\n
\n" } ], "methods": [ { "textRaw": "https.createServer(options, [requestListener])", "type": "method", "name": "createServer", "desc": "새로운 HTTPS 웹서버 객체를 반환한다. options
은 [tls.createServer()][]와\n유사하다. requestListener
는 'request'
이벤트에 자동으로 추가되는\n함수이다.\n\n
예제:\n\n
\n// curl -k https://localhost:8000/\nvar https = require('https');\nvar fs = require('fs');\n\nvar options = {\n key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),\n cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')\n};\n\nhttps.createServer(options, function (req, res) {\n res.writeHead(200);\n res.end("hello world\\n");\n}).listen(8000);
\n또는\n\n
\nvar https = require('https');\nvar fs = require('fs');\n\nvar options = {\n pfx: fs.readFileSync('server.pfx')\n};\n\nhttps.createServer(options, function (req, res) {\n res.writeHead(200);\n res.end("hello world\\n");\n}).listen(8000);
\n",
"methods": [
{
"textRaw": "server.listen(path, [callback])",
"type": "method",
"name": "listen",
"desc": "자세한 내용은 [http.listen()][]를 참고해라.\n\n
\n", "signatures": [ { "params": [ { "name": "handle" }, { "name": "callback", "optional": true } ] }, { "params": [ { "name": "path" }, { "name": "callback", "optional": true } ] } ] }, { "textRaw": "server.listen(handle, [callback])", "type": "method", "name": "listen", "desc": "자세한 내용은 [http.listen()][]를 참고해라.\n\n
\n", "signatures": [ { "params": [ { "name": "handle" }, { "name": "callback", "optional": true } ] } ] }, { "textRaw": "server.close([callback])", "type": "method", "name": "close", "desc": "자세한 내용은 [http.close()][]를 참고해라.\n\n
\n", "signatures": [ { "params": [ { "name": "callback", "optional": true } ] } ] } ], "signatures": [ { "params": [ { "name": "options" }, { "name": "requestListener", "optional": true } ] } ] }, { "textRaw": "https.request(options, callback)", "type": "method", "name": "request", "desc": "안전한 웹서버로의 요청을 생성한다.\n\n
\noptions
은 객체거나 문자열이다. options
이 문자열인 경우 자동적으로\nurl.parse()로 파싱한다.\n\n
[http.request()][]의 모든 옵션이 유효하다.\n\n
\n예제:\n\n
\nvar https = require('https');\n\nvar options = {\n hostname: 'encrypted.google.com',\n port: 443,\n path: '/',\n method: 'GET'\n};\n\nvar req = https.request(options, function(res) {\n console.log("statusCode: ", res.statusCode);\n console.log("headers: ", res.headers);\n\n res.on('data', function(d) {\n process.stdout.write(d);\n });\n});\nreq.end();\n\nreq.on('error', function(e) {\n console.error(e);\n});
\noptions 아규먼트는 다음과 같다.\n\n
\nhost
: 요청을 보낼 서버의 도메인명이나 IP 주소다. 기본값은 'localhost'
이다.hostname
: url.parse()
를 지원하기 위해 host
보다 hostname
를 선호한다.port
: 원격서버의 포트. 기본값은 443이다.method
: HTTP 요청 메서드를 지정하는 문자열이다. 기본값은 'GET'
이다.path
: 요청 경로. 기본값은 '/'
이다. 필요하다면 쿼리스트링도 포함해야 한다.\n예시. '/index.html?page=12'
headers
: 요청 헤더를 담고 있는 객체다.auth
: 기본 인증. 예글 들면 인증헤더를 계산하는 'user:password'
agent
: [Agent][] 동작을 제어한다. Agent를 사용했을 때\n요청은 기본적으로 Connection: keep-alive
가 될 것이다. 다음의 값들이 가능하다.undefined
(기본값): 해당 호스트와 포트에 [globalAgent][]를 사용한다.Agent
객체: Agent
에 명시적으로 전달된 객체를 사용한다.false
: Agent를 연결 풀링에 참가시키지 않는다. 기본적으로 요청은\nConnection: close
가 된다.[tls.connect()][]의 다음 옵션들도 지정할 수 있다.\n하지만 [globalAgent][]는 경고없이 이러한 값들을 무시한다.\n\n
\npfx
: SSL에 사용할 인증서, 개인키, CA 인증서. 기본값은 null
이다.key
: SSL에 사용할 개인키. 기본값은 null
이다.passphrase
: 개인키나 pfx에 대한 암호문 문자열. 기본값은 null
이다.cert
: 사용할 공개 x509 인증서. 기본값은 null
이다.ca
: 원격 호스트에 대해 확인할 권한 인증이나 권한 인증의 배열이다.ciphers
: 사용하거나 배제할 암호문을 나타내는 문자열. 자세한 형식은\nhttp://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT 를\n참고해라.rejectUnauthorized
: 이 값이 true
이면 서버 인증서를 제공된 CA 리스트로\n검증한다. 검증이 실패했을 때 'error'
이벤트가 발생한다. 검증은 HTTP 요청을\n보내기 전 연결단계에서 이뤄진다. 기본값은 true
이다.secureProtocol
: 사용할 SSL 방식. 예를 들어 SSL 버전 3을 사용하려면\nSSLv3_method
이다. 사용가능한 값은 설치한 OpenSSL에 따라 다르고\n상수 [SSL_METHODS][]에 정의되어 있다.이러한 옵션들을 지정하려면 커스텀 Agent
를 사용해라.\n\n
예제:\n\n
\nvar options = {\n hostname: 'encrypted.google.com',\n port: 443,\n path: '/',\n method: 'GET',\n key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),\n cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')\n};\noptions.agent = new https.Agent(options);\n\nvar req = https.request(options, function(res) {\n ...\n}
\n또는 Agent
를 사용하지 마라.\n\n
예제:\n\n
\nvar options = {\n hostname: 'encrypted.google.com',\n port: 443,\n path: '/',\n method: 'GET',\n key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),\n cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem'),\n agent: false\n};\n\nvar req = https.request(options, function(res) {\n ...\n}
\n",
"signatures": [
{
"params": [
{
"name": "options"
},
{
"name": "callback"
}
]
}
]
},
{
"textRaw": "https.get(options, callback)",
"type": "method",
"name": "get",
"desc": "http.get()
와 같지만 HTTPS다.\n\n
options
은 객체거나 문자열이다. options
이 문자열인 경우 자동적으로\nurl.parse()로 파싱한다.\n\n
예제:\n\n
\nvar https = require('https');\n\nhttps.get('https://encrypted.google.com/', function(res) {\n console.log("statusCode: ", res.statusCode);\n console.log("headers: ", res.headers);\n\n res.on('data', function(d) {\n process.stdout.write(d);\n });\n\n}).on('error', function(e) {\n console.error(e);\n});
\n",
"signatures": [
{
"params": [
{
"name": "options"
},
{
"name": "callback"
}
]
}
]
}
],
"properties": [
{
"textRaw": "https.globalAgent",
"name": "globalAgent",
"desc": "모든 HTTPS 클라이언트 요청에 대한 [https.Agent][]의 전역 인스턴스다.\n\n
\n" } ], "type": "module", "displayName": "HTTPS" }, { "textRaw": "URL", "name": "url", "stability": 3, "stabilityText": "Stable", "desc": "이 모듈은 URL 처리와 파싱에 관한 유틸리티 모듈이다.\n사용하려면 require('url')
를 호출해라.\n\n
파싱된 URL 객체들은 다음의 필드들을 가지고 있다. 필드들은 URL 문자열에 존재여부에 따라\n있을 수도 있고 없을 수도 있다. URL 문자열에 없는 부분은 파싱된 객체에도 없다.\n다음은 URL에 대한 예제를 보여준다.\n\n
\n'http://user:pass@host.com:8080/p/a/t/h?query=string#hash'
\n\n
href
: 파싱되기 전 원래의 전체 URL. 프로톨콜과 호스트가 모두 소문자이다.
예제: 'http://user:pass@host.com:8080/p/a/t/h?query=string#hash'
protocol
: 요청 프로토콜로 소문자다.
예제: 'http:'
host
: 포트정보를 포함해서 소문자로된 호스트 부분.
예제: 'host.com:8080'
auth
: URL의 인증정보 부분.
예제: 'user:pass'
hostname
: 호스트에서 소문자로 된 호스트명 부분.
예제: 'host.com'
port
: 호스트의 포트번호 부분.
예제: '8080'
pathname
: 존재한다면 첫 슬래시를 포함해서 호스트 이후부터 쿼리 이전까지의\nURL의 경로부분.
예제: '/p/a/t/h'
search
: URL에서 물음표로 시작되는 'query string' 부분.
예제: '?query=string'
path
: pathname
와 search
의 연결.
예제: '/p/a/t/h?query=string'
query
: 쿼리스트링의 'params' 부분이거나 쿼리스트링이 파싱된 객체다.
예제: 'query=string'
or {'query':'string'}
hash
: 해시기호를 포함해서 URL의 'fragment' 부분.
예제: '#hash'
URL 모듈에서 다음 메서드들을 제공한다.\n\n
\n", "methods": [ { "textRaw": "url.parse(urlStr, [parseQueryString], [slashesDenoteHost])", "type": "method", "name": "parse", "desc": "URL 문자열을 받아서 객체를 반환한다.\n\n
\nquerystring
모듈을 사용해서 쿼리스트링을 파싱하려면\n두번째 아규먼트로 true
를 전달한다.\n기본값은 false
이다.\n\n
{ pathname: '//foo/bar' }
보다는\n{ host: 'foo', pathname: '/bar' }
와 같이 //foo/bar
를\n다루려면 세번째 아규먼트로 true
를 전달한다.\n기본값은 false
이다.\n\n
파싱된 URL 객체를 받아서 포매팅된 URL 문자열을 반환한다.\n\n
\nhref
는 무시된다.protocol
은 뒷 부분의 :
(콜론)을 포함하거나 포함하지 않고 다룬다.http
, https
, ftp
, gopher
, file
은\n://
(콜론-슬래시-슬래시)로 접미사가 붙는다.mailto
, xmpp
, aim
, sftp
, foo
등은 :
\n(콜론)로 접미사가 붙는다.auth
를 사용한다.host
가 없으면 hostname
만 사용한다.host
가 없으면 port
를 사용한다.host
를 hostname
, port
대신에 사용한다.pathname
는 /
(슬래시)로 시작되는 부분을 포함하거나 포함하지 않고 다룬다.search
를 query
대신에 사용한다.search
가 없으면 query
(객체; querystring
를 봐라)만 사용할 것이다.search
는 ?
(물음표)로 시작되는 부분을 포함하거나 포함하지 않고 다룬다.hash
는 #
(해시기호, 앵커)로 시작하는 부분을 포함하거나 포함하지 않고 다룬다.기준 URL과 href URL을 받아서 앵커태그를 위해서 브라우저처럼 처리한다.\n예제:\n\n
\nurl.resolve('/one/two/three', 'four') // '/one/two/four'\nurl.resolve('http://example.com/', '/one') // 'http://example.com/one'\nurl.resolve('http://example.com/one', '/two') // 'http://example.com/two'
\n",
"signatures": [
{
"params": [
{
"name": "from"
},
{
"name": "to"
}
]
}
]
}
],
"type": "module",
"displayName": "URL"
},
{
"textRaw": "Query String",
"name": "querystring",
"stability": 3,
"stabilityText": "Stable",
"desc": "이 모듈은 쿼리스트링을 다루는 유틸리티 모듈이다.\n다음의 메서드들을 제공한다.\n\n
\n", "methods": [ { "textRaw": "querystring.stringify(obj, [sep], [eq])", "type": "method", "name": "stringify", "desc": "객체를 쿼리스트링으로 직렬화한다.\n선택적으로 기본 구분기호('&'
)와 할당기호('='
)를 오버라이드 할 수 있다.\n\n
예제:\n\n
\nquerystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' })\n// returns\n'foo=bar&baz=qux&baz=quux&corge='\n\nquerystring.stringify({foo: 'bar', baz: 'qux'}, ';', ':')\n// returns\n'foo:bar;baz:qux'
\n",
"signatures": [
{
"params": [
{
"name": "obj"
},
{
"name": "sep",
"optional": true
},
{
"name": "eq",
"optional": true
}
]
}
]
},
{
"textRaw": "querystring.parse(str, [sep], [eq], [options])",
"type": "method",
"name": "parse",
"desc": "쿼리스트링을 객체로 역직렬화한다.\n선택적으로 기본 구분기호('&'
)와 할당기호('='
)를 오버라이드 할 수 있다.\n\n
options 객체는 maxKeys
프로퍼티를 가지고 있고(기본값은 1000이다) 이 프로퍼티는 처리되는\n키를 제한하는데 사용한다. 키의 갯수 제한을 없애려면 0으로 설정한다.\n\n
예제:\n\n
\nquerystring.parse('foo=bar&baz=qux&baz=quux&corge')\n// returns\n{ foo: 'bar', baz: ['qux', 'quux'], corge: '' }
\n",
"signatures": [
{
"params": [
{
"name": "str"
},
{
"name": "sep",
"optional": true
},
{
"name": "eq",
"optional": true
},
{
"name": "options",
"optional": true
}
]
}
]
}
],
"properties": [
{
"textRaw": "querystring.escape",
"name": "escape",
"desc": "querystring.stringify
에서 사용하는 이스케이스 함수로 \n필요하다면 오버라이드 할 수 있다.\n\n
querystring.parse
에서 사용하는 역이스케이스(unescape) 함수로 \n필요하다면 오버라이드 할 수 있다.\n\n
Punycode.js는 Node.js v0.6.2+부터 포함되었고\nrequire('punycode')
로 접근한다.(다른 Node.js 버전에서 이 모듈을 사용하려면\nnpm으로 punycode
모듈을 설치해야 한다.)\n\n
ASCII 코드의 퓨니코드(Punycode) 문자열을 유니코드 문자열로 변환한다.\n\n\n
\n// 도메인명 부분을 디코드한다\npunycode.decode('maana-pta'); // 'mañana'\npunycode.decode('--dqo34k'); // '☃-⌘'
\n",
"signatures": [
{
"params": [
{
"name": "string"
}
]
}
]
},
{
"textRaw": "punycode.encode(string)",
"type": "method",
"name": "encode",
"desc": "유니코드 문자열을 ASCII 코드의 퓨니코드(Punycode) 문자열로 변환한다.\n\n
\n// 도메인명 부분을 인코딩한다\npunycode.encode('mañana'); // 'maana-pta'\npunycode.encode('☃-⌘'); // '--dqo34k'
\n",
"signatures": [
{
"params": [
{
"name": "string"
}
]
}
]
},
{
"textRaw": "punycode.toUnicode(domain)",
"type": "method",
"name": "toUnicode",
"desc": "도메인명을 나타내는 퓨니코드 문자열을 유니코드로 변환한다. 도메인명에서 퓨니코드부분만\n변환된다. 예를 들어 이미 유니코드로 변환된 문자열에서 이 함수를 호출해도 아무 문제가 없다.\n\n
\n// 도메인명을 디코드한다\npunycode.toUnicode('xn--maana-pta.com'); // 'mañana.com'\npunycode.toUnicode('xn----dqo34k.com'); // '☃-⌘.com'
\n",
"signatures": [
{
"params": [
{
"name": "domain"
}
]
}
]
},
{
"textRaw": "punycode.toASCII(domain)",
"type": "method",
"name": "toASCII",
"desc": "도메인명을 나타내는 유니코드 문자열을 퓨니코드로 변환한다. 도메인명에서 ASCII가 아닌\n부분만 변환한다. 이미 ASCII인 도메인에서 호출해도 괜찮다.\n\n
\n// 도메인명을 인코딩한다\npunycode.toASCII('mañana.com'); // 'xn--maana-pta.com'\npunycode.toASCII('☃-⌘.com'); // 'xn----dqo34k.com'
\n",
"signatures": [
{
"params": [
{
"name": "domain"
}
]
}
]
}
],
"properties": [
{
"textRaw": "punycode.ucs2",
"name": "ucs2",
"modules": [
{
"textRaw": "punycode.ucs2.decode(string)",
"name": "punycode.ucs2.decode(string)",
"desc": "문자열의 각 유니코드 문자에 대한 십진수 코드를 담고 있는 배열을 생성한다. JavaScript \n가 내부적으로 UCS-2를 사용하기때문에\n이 함수는 서로게이트 반쪽(surrogate halves)의 쌍을(UCS-2의 각각은 분리된 코드로 나타난다)\nUTF-16에 맞는 단일 코드로 변환한다.\n\n
\npunycode.ucs2.decode('abc'); // [97, 98, 99]\n// surrogate pair for U+1D306 tetragram for centre:\npunycode.ucs2.decode('\\uD834\\uDF06'); // [0x1D306]
\n",
"type": "module",
"displayName": "punycode.ucs2.decode(string)"
},
{
"textRaw": "punycode.ucs2.encode(codePoints)",
"name": "punycode.ucs2.encode(codepoints)",
"desc": "십진수코드 배열에 기반한 문자열을 생성한다.\n\n
\npunycode.ucs2.encode([97, 98, 99]); // 'abc'\npunycode.ucs2.encode([0x1D306]); // '\\uD834\\uDF06'
\n",
"type": "module",
"displayName": "punycode.ucs2.encode(codePoints)"
}
]
},
{
"textRaw": "punycode.version",
"name": "version",
"desc": "현재 Punycode.js 버전번호를 나타내는 문자열.\n\n
\n" } ], "type": "module", "displayName": "punycode" }, { "textRaw": "Readline", "name": "readline", "stability": 2, "stabilityText": "Unstable", "desc": "이 모듈을 사용하려면 require('readline')
를 실행해라. Readline은 줄마다 \n스트림(process.stdin
같은)으로 읽을 수 있다.\n\n
이 모듈을 한번 호출하고 나면 인터페이스를 종료할 때까지 node 프로그램은 종료되지 \n않을 것이다. 어떻게 프로그램을 안전하게(gracefully) 종료할 수 있는 지 보여주는 \n예제가 있다.\n\n
\nvar readline = require('readline');\n\nvar rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n});\n\nrl.question("What do you think of node.js? ", function(answer) {\n // TODO: 데이터베이스에 답변을 로깅한다\n console.log("Thank you for your valuable feedback:", answer);\n\n rl.close();\n});
\n",
"methods": [
{
"textRaw": "readline.createInterface(options)",
"type": "method",
"name": "createInterface",
"desc": "readline의 Interface
인스턴스를 생성한다. 다음 값의 "options" 객체를 받는다.\n\n
input
- 리스닝할 읽을 수 있는 스트림 (필수).
output
- readline 데이터를 작성할 쓰기가 가능한 스트림 (필수).
completer
- 탭 자동완성에 사용한 선택적인 함수. 아래 이 값을 사용하는 예제를 봐라.
terminal
- input
스트림과 output
스트림을 TTY처럼 다뤄야 하고 작성된 코드가 \nANSI/VT100로 이스케이프되었다면 true
를 전달한다.\n기본값은 인스턴스의 output
스트림에서 isTTY
를 확인하는 것이다.
completer
함수는 사용자가 입력하는 현재 라인을 받고 2가지 배열을 리턴한다.\n\n
자동완성을 위해 일치하는 값들의 배열
\n매칭에 사용되는 부분문자열.
\n그래서 다음과 같은 결과가 나올 것이다.\n[[substr1, substr2, ...], originalsubstring]
\n\n
예제:\n\n
\nfunction completer(line) {\n var completions = '.help .error .exit .quit .q'.split(' ')\n var hits = completions.filter(function(c) { return c.indexOf(line) == 0 })\n // 아무것도 찾지 못하면 모든 자동완성을 보여준다\n return [hits.length ? hits : completions, line]\n}
\n두 개의 아규먼트를 받으면 completer
도 비동기로 실행할 수 있다.\n\n
function completer(linePartial, callback) {\n callback(null, [['123'], linePartial]);\n}
\ncreateInterface
는 보통 사용자 입력을 받기 위해\nprocess.stdin
와 process.stdout
와 함께 사용한다.\n\n
var readline = require('readline');\nvar rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout\n});
\nreadline 인스턴스를 가지면 보통 "line"
이벤트를 리스닝한다.\n\n
해당 인스턴스의 terminal
값이 true
이면 output
스트림은 output.columns
\n프로퍼티를 정의하는 최적의 호환성을 가질 것이고 output
은 컬럼이 변경될 때마다 \n"resize"
이벤트를 발생시킨다.\n(output
이 TTY이면 process.stdout
는 자동으로 이렇게 한다.)\n\n
클래스는 입력스트림과 출력 스트림을 가진 readline 인터페이스를 나타낸다.\n\n
\n", "methods": [ { "textRaw": "rl.setPrompt(prompt, length)", "type": "method", "name": "setPrompt", "desc": "프롬프트를 설정한다. 예를 들어 커맨드라인에서 node
를 실행하면 node의 프롬프트인 \n>
를 볼 수 있다.\n\n
사용자가 작성할 새로운 지점인 새로운 줄에서 현재의 setPrompt
옵션을 두어 \n사용자에게 입력을 받기 위해서 readline을 준비한다. 커서 위치를 0
으로 초기화하는\n것을 막으려면 preserveCursor
을 true
으로 설정해라.\n\n
createInterface
과 함께 사용한 input
스트림이 멈춰있다면 이 함수는 다시\n시작할 것이다.\n\n
query
앞에 프로프트를 붙히고 사용자의 응답으로 callback
을 호출한다. \n사용자에게 쿼리를 보여주고 사용자가 입력한 응답으로 callback
을 호출한다.\n\n
createInterface
과 함께 사용한 input
스트림이 멈춰있다면 이 함수는 다시\n시작할 것이다.\n\n
예제:\n\n
\ninterface.question('What is your favorite food?', function(answer) {\n console.log('Oh, so your favorite food is ' + answer);\n});
\n",
"signatures": [
{
"params": [
{
"name": "query"
},
{
"name": "callback"
}
]
}
]
},
{
"textRaw": "rl.pause()",
"type": "method",
"name": "pause",
"desc": "나중에 필요할 때 다시 시작할 수 있도록 readline input
스트림을 멈춘다.\n\n
readline input
스트림을 다시 시작한다.\n\n
input
과 output
스트림의 제어권을 포기하고 Interface
인스턴스를 닫는다.\n"close" 이벤트도 발생할 것이다.\n\n
output
스트림에 data
를 작성한다. key
는 키의 순서를 나타내는 객체 리터럴로 터미널이\nTTY일 때 사용할 수 있다.\n\n
input
스트림이 멈춰있다면 이 함수는 다시 시작할 것이다.\n\n
예제:\n\n
\nrl.write('Delete me!');\n// 이전에 작성한 라인을 삭제하는 ctrl+u를 시뮬레이트한다\nrl.write(null, {ctrl: true, name: 'u'});
\n",
"signatures": [
{
"params": [
{
"name": "data"
},
{
"name": "key",
"optional": true
}
]
}
]
}
]
}
],
"modules": [
{
"textRaw": "Events",
"name": "events",
"events": [
{
"textRaw": "Event: 'line'",
"type": "event",
"name": "line",
"desc": "function (line) {}
\n\n
in
스트림이 \\n
를 받을 때마다 발생한다. 보통 사용자가 엔터를 쳤을 때 받게 된다.\n이 이벤트는 사용자 입력을 받기 위한 좋은 후크(hook)이다.\n\n
line
이벤트를 받는 예제다.\n\n
rl.on('line', function (cmd) {\n console.log('You just typed: '+cmd);\n});
\n",
"params": []
},
{
"textRaw": "Event: 'pause'",
"type": "event",
"name": "pause",
"desc": "function () {}
\n\n
input
스트림이 멈출 때마다 발생한다.\n\n
input
스트림이 멈춰있지 않고 SIGCONT
이벤트를 받을 때도 발생한다.\n(SIGTSTP
이벤트와 SIGCONT
이벤트를 참고해라.)\n\n
pause
이벤트를 리스닝하는 예제:\n\n
rl.on('pause', function() {\n console.log('Readline paused.');\n});
\n",
"params": []
},
{
"textRaw": "Event: 'resume'",
"type": "event",
"name": "resume",
"desc": "function () {}
\n\n
input
스트림이 재시작 할때마다 발생한다.\n\n
resume
이벤트를 리스닝하는 예제:\n\n
rl.on('resume', function() {\n console.log('Readline resumed.');\n});
\n",
"params": []
},
{
"textRaw": "Event: 'close'",
"type": "event",
"name": "close",
"desc": "function () {}
\n\n
close()
를 호출할 때 발생한다.\n\n
input
스트림이 "end" 이벤트를 받을 때도 발생한다. Interface
인터페이스는 "finished"\n이벤트가 발생했다고 간주한다. 예를 들어 input
스트림이 EOT
인 ^D
를 받은 경우이다.\n\n
input
스트림이 SIGINT
의 의미인 ^C
를 받았을 때 SIGINT
이벤트에 등록된 리스너가\n없으면 이 이벤트가 호출된다.\n\n
function () {}
\n\n
input
스트림이 SIGINT
의 의미인 ^C
를 받을 때마다 발생한다. input
스트림이\nSIGINT
를 받을 때 SIGINT
이벤트에 등록된 리스너가 없으면 pause
이벤트가 발생한다.\n\n
SIGINT
를 리스닝하는 예제:\n\n
rl.on('SIGINT', function() {\n rl.question('Are you sure you want to exit?', function(answer) {\n if (answer.match(/^y(es)?$/i)) rl.pause();\n });\n});
\n",
"params": []
},
{
"textRaw": "Event: 'SIGTSTP'",
"type": "event",
"name": "SIGTSTP",
"desc": "function () {}
\n\n
이 이벤트는 Windows에서는 동작하지 않는다.\n\n
\ninput
스트림이 SIGTSTP
로 알려진 ^Z
를 받을 때마다 발생한다. input
스트림이\nSIGTSTP
을 받았을 때 SIGTSTP
이벤트에 등록된 리스너가 없으면 프로그램은 백그라운드로\n보내진다.\n\n
프로그램이 fg
로 복귀했을 때 pause
와 SIGCONT
이벤트가 실행될 것이다. 스트림으로\n복귀하는데 사용할 수도 있다.\n\n
프로그램이 백그라운드로 보내지기 전에 스트림이 멈춰있다면 pause
와 SIGCONT
이벤트는\n발생하지 않을 것이다.\n\n
SIGTSTP
이벤트를 리스닝하는 예제:\n\n
rl.on('SIGTSTP', function() {\n // 이는 SIGTSTP를 오버라이드 하고 프로그램이 백그라운드로 가는 것을 막는다.\n console.log('Caught SIGTSTP.');\n});
\n",
"params": []
},
{
"textRaw": "Event: 'SIGCONT'",
"type": "event",
"name": "SIGCONT",
"desc": "function () {}
\n\n
이 이벤트는 Windows에서는 동작하지 않는다.\n\n
\ninput
스트림이 SIGTSTP
로 알려진 ^Z
를 통해 백그라운드로 보내질 때마다 발생하고\n이는 fg(1)
로 다시 복귀할 수 있다. 이 이벤트는 프로그램을 백그라운드로 보내기 전에\n스트림이 멈춰있지 않은 경우에만 발생한다.\n\n
SIGCONT
이벤트를 리스닝하는 예제:\n\n
rl.on('SIGCONT', function() {\n // `prompt`는 자동으로 스트림을 복구시킬 것이다\n rl.prompt();\n});
\n이 모두를 사용해서 어떻게 작은 명령행 인터페이스를 만드는지 보여주는 예제가 있다.\n\n
\nvar readline = require('readline'),\n rl = readline.createInterface(process.stdin, process.stdout);\n\nrl.setPrompt('OHAI> ');\nrl.prompt();\n\nrl.on('line', function(line) {\n switch(line.trim()) {\n case 'hello':\n console.log('world!');\n break;\n default:\n console.log('Say what? I might have heard `' + line.trim() + '`');\n break;\n }\n rl.prompt();\n}).on('close', function() {\n console.log('Have a great day!');\n process.exit(0);\n});
\n",
"params": []
}
],
"type": "module",
"displayName": "Events"
}
],
"type": "module",
"displayName": "Readline"
},
{
"textRaw": "REPL",
"name": "repl",
"desc": "Read-Eval-Print-Loop (REPL)는 단독 프로그램과 다른 프로그램에 쉽게 포함해서 사용할 수 있다.\nREPL은 자바스크립트를 실행하고 결과를 보는 대화식 방법을 제공한다. 이는 디버깅, 테스팅이나\n그냥 간단한 것을 시도해 볼 때 사용할 수 있다.\n\n
\n명령행에서 아규먼트없이 node
를 실행하면 REPL에 들어간다.\nREPL은 극도로 단순한 emacs 라인수정을 가진다.\n\n
mjr:~$ node\nType '.help' for options.\n> a = [ 1, 2, 3];\n[ 1, 2, 3 ]\n> a.forEach(function (v) {\n... console.log(v);\n... });\n1\n2\n3
\n향상된 라인에디터를 위해서는 환경변수 NODE_NO_READLINE=1
로 node를 시작해라.\n이는 rlwrap
를 사용할 수 있도록 인정된 터미널 설정에서 메인 REPL과\n디버거 REPL을 시작한다.\n\n
예를 들어 bashrc 파일에 다음을 추가할 수 있다.\n\n
\nalias node="env NODE_NO_READLINE=1 rlwrap node"
\n",
"methods": [
{
"textRaw": "repl.start(options)",
"type": "method",
"name": "start",
"desc": "REPLServer
인스턴스를 시작하고 반환한다. 다음 값의 "options" 객체를 받는다.\n\n
prompt
- 모든 I/O에 대한 프롬프트와 stream
. 기본값은 >
이다.
input
- 리스닝할 읽을 수 있는 스트림. 기본값은 process.stdin
이다.
output
- readline 데이터를 작성할 쓰기가능한 스트림. 기본값은\nprocess.stdout
이다.
terminal
- stream
을 TTY처럼 다뤄야 하고 작성된 데이터가 ANSI/VT100로\n이스케이프되어 있다면 true
를 전달해라. 기본값은 인스턴스의 output
스트림에서\nisTTY
를 확인하는 것이다.
eval
- 각 주어진 라인을 평가(eval)하는데 사용할 함수. 기본값은 eval()
에 대한\n비동기 래퍼이다. 아래의 커스텀 eval
의 예제를 참조해라.
useColors
- writer
함수가 색상을 출력해야 하는지 아닌지를 지정하는 불리언값.\n다른 writer
함수를 설정하면 이 값은 아무것도 하지 않는다. 기본값은 repl의\nterminal
값이다.
useGlobal
- true
로 설정하면 repl이 분리된 컨텍스트에서 스크립트를 실행하는\n대신에 global
객체를 사용한다. 기본값은 false
이다.
ignoreUndefined
- true
로 설정하면 repl은 명령의 결과값이 undefined
인\n경우 출력하지 않는다. 기본값은 false
이다.
writer
- 화면에 표시하기 위해서 포매팅(컬러링 포함)된 값을 평가하려고\n명령마다 호출할 함수이다. 기본값은 util.inspect
이다.
다음과 같은 시그니처를 가진 자신만의 eval
함수를 사용할 수 있다.\n\n
function eval(cmd, context, filename, callback) {\n callback(null, result);\n}
\n다중 REPL은 node에서 실행되는 같은 인스턴스에서 시작될 것이다. 각 REPL은 같은 전역객체를\n공유하지만 각각 유일한 I/O를 가질 것인다.\n\n
\nstdin, Unix 소켓, TCP 소켓에서 REPL을 시작하는 예제는 다음과 같다.\n\n
\nvar net = require("net"),\n repl = require("repl");\n\nconnections = 0;\n\nrepl.start({\n prompt: "node via stdin> ",\n input: process.stdin,\n output: process.stdout\n});\n\nnet.createServer(function (socket) {\n connections += 1;\n repl.start({\n prompt: "node via Unix socket> ",\n input: socket,\n output: socket\n }).on('exit', function() {\n socket.end();\n })\n}).listen("/tmp/node-repl-sock");\n\nnet.createServer(function (socket) {\n connections += 1;\n repl.start({\n prompt: "node via TCP socket> ",\n input: socket,\n output: socket\n }).on('exit', function() {\n socket.end();\n });\n}).listen(5001);
\n명령행에서 이 프로그램을 실행하면 stdin에서 REPL을 시작할 것이다. 다른 REPL 클라이언트는\nUnix 소켓이나 TCP 소켓을 통해서 연결할 것이다. telnet
은 TCP 소켓에 연결하는 데 유용하고\nsocat
은 Unix와 TCP 소켓에 연결하는 데 사용할 수 있다.\n\n
stdin 대신 Unix 소켓에 기반한 서버에서 REPL을 시작하면 재시작 없이 오랫동안\n실행되는 node 프로세스에 연결할 수 있다.\n\n
\nnet.Server
와 net.Socket
인스턴스에서 실행되는 "완전한 기능의" (terminal
) REPL의\n예제는 https://gist.github.com/2209310 를 참고해라.\n\n
curl(1)
을 실행하는 REPL 인스턴스의 예제는\nhttps://gist.github.com/2053342 를 참고해라.\n\n
function () {}
\n\n
사용자가 어떤 방법으로든 REPL을 종료했을 때 발생한다. 즉 repl에서 .exit
를 입력하거나\nSIGINT 신호를 위해 Ctrl+C를 두번 입력하거나 input
스트림에서 "end" 신호를 위해\nCtrl+D를 입력하는 등이다.\n\n
exit
이벤트를 리스닝하는 예제:\n\n
r.on('exit', function () {\n console.log('Got "exit" event from repl!');\n process.exit();\n});
\n",
"params": []
}
],
"signatures": [
{
"params": [
{
"name": "options"
}
]
}
]
}
],
"miscs": [
{
"textRaw": "REPL Features",
"name": "REPL Features",
"type": "misc",
"desc": "REPL내에서 Control+D를 누르면 종료될 것이다. 다중라인 포현식은 입력이 될 수 있다.\n전역 변수와 지역 변수에 모두 탭 자동완성을 지원한다.\n\n
\n특수한 변수 _
(언더스코어)는 마지막 표현식의 결과를 담고 있다.\n\n
> [ "a", "b", "c" ]\n[ 'a', 'b', 'c' ]\n> _.length\n3\n> _ += 1\n4
\nREPL은 전역범위의 어떤 변수라도 접근할 수 있다.\n각 REPLServer
과 연결된 context
객체에 할당해서 명시적으로 REPL에 변수를\n노출할 수 있다. 예를 들어\n\n
// repl_test.js\nvar repl = require("repl"),\n msg = "message";\n\nrepl.start("> ").context.m = msg;
\nREPL내 context
객체에서 지역변수로 나타나는 변수들이 있다.\n\n
mjr:~$ node repl_test.js\n> m\n'message'
\n몇몇 REPL 명령어가 있다.\n\n
\n.break
- 다중 라인 표현식을 입력하는 동안 종종 멈추거나 표현식을 완성하기를 신경쓰지\n않을 때 사용한다. .break
은 다시 시작할 것이다..clear
- context
객체를 비어있는 객체로 리셋하고 모든 다중라인 표현식을\n정리한다..exit
- REPL이 종료되도록 I/O 스트림을 닫는다..help
- 이 특수한 명령어 리스트를 보여준다..save
- 현재 REPL 세션을 파일로 저장한다.\n\n.save ./file/to/save.js
\n
.load
- 파일에서 현재 REPL 세션으로 로드한다.\n\n.load ./file/to/load.js
\n
REPL에서 다음의 키 조합은 다음과 같은 특수한 효가가 있다.\n\n
\n<ctrl>C
- .break
키워드와 유사하다. 현재 명령어를 종료한다.\n비어있는 라인에서 두 번 입력하면 강제적으로 종료한다.<ctrl>D
- .exit
키워드와 유사하다.이 모듈은 다음과 같이 접근할 수 있다.\n\n
\nvar vm = require('vm');
\n자바스크립트 코드는 컴파일하고 바로 실행하거나 컴파일하고 저장한 후에 나중에 실행할 수 있다.\n\n
\n", "modules": [ { "textRaw": "Caveats", "name": "caveats", "desc": "vm
모듈은 많은 이슈와 엣지 케이스(edge cases)가 있다. 어떤 이슈나\n기대하지 않은 결과를 만난다면\nthe open issues on\nGitHub\n를 참고해라. 가장 큰 문제들은 아래에 설명했다.\n\n
vm.runInNewContext
와 vm.createContext
의 sandbox
아규먼트와\nvm.createContext
의 initSandbox
아규먼트는 Node의 다양한 버전에서\n보통 한가지 동작으로 기대할 수 없고 다양하게 동작한다.\n\n
알려진 핵심이슈는 컨텍스트내에서 사용한 전역객체를 직접 제어할 방법을 V8이 제공하지\n않는다는 것이다. 그 결과 sandbox
객체의 프로퍼티를 컨텍스트에서 이용할 수\n있더라도 sandbox
의 prototype
에서 어떤 프로퍼티도 이용할 수 없다. 게다가\n컨텍스트의 전역범위내에서 this
표현식은 sandbox 대신 빈 객체({}
)가 된다.\n\n
실행할 때 컨텍스트로 복사되고 실행후에 변경사항을 전파하기 위해 다시 복사된다.\n\n
\n", "type": "module", "displayName": "Sandboxes" }, { "textRaw": "Globals", "name": "globals", "desc": "Array
와 String
같은 전역객체의 프로퍼티들은 컨텍스트내에서 다른 값들을 가진다.\n이는 vm
모듈을 통해서 실행한 스트립트내에서는 [] instanceof Array
나\nObject.getPrototypeOf([]) === Array.prototype
같은 일반적인 표현식이\n기대한 결과가 되지 않는다는 의미이다.\n\n
이러한 문제들 중 일부는 Github의 vm
에 대한 이슈에 우회방법이 리스트되어 있다.\n예를 들어 Array.isArray
는 Array
문제로 우회할 수 있다.\n\n
vm.runInThisContext()
는 code
를 컴파일하고 실행해서 결과를 반환한다. 실행되는 코드는\n지역범위에 접근하지 않는다. filename
은 선택사항이며 스택트레이스에서만 사용된다.\n\n
같은 코드를 실행하는데 vm.runInThisContext
과 eval
을 사용한 예제\n\n
var localVar = 123,\n usingscript, evaled,\n vm = require('vm');\n\nusingscript = vm.runInThisContext('localVar = 1;',\n 'myfile.vm');\nconsole.log('localVar: ' + localVar + ', usingscript: ' +\n usingscript);\nevaled = eval('localVar = 1;');\nconsole.log('localVar: ' + localVar + ', evaled: ' +\n evaled);\n\n// localVar: 123, usingscript: 1\n// localVar: 1, evaled: 1
\nvm.runInThisContext
가 지역범위에 접근하지 않기 때문에 localVar
는 변경되지 않았다.\neval
은 지역범위에 접근하기 때문에 localVar
가 변경되었다.\n\n
code
에 문법오류가 있는 경우 vm.runInThisContext
는 stderr에 문법오류를 발생시키고 예외를\n던진다.\n\n\n
vm.runInNewContext
는 code
를 컴파일하고 sandbox
에서 실행한 뒤 결과를 반환한다.\n실행되는 코드는 지역범위에 접근하지 않는다. sandbox
객체는 code
의 전역객체로 사용될\n것이다.\nsandbox
와 filename
는 선택사항이고 filename
는 스택트레이스에서만 사용된다.\n\n
예제: 전역변수를 증가시키고 새로운 전역변수를 설정하는 코드를 컴파일하고 실행한다.\n이 전역변수들은 sandbox안에 포함되어 있다.\n\n
\nvar util = require('util'),\n vm = require('vm'),\n sandbox = {\n animal: 'cat',\n count: 2\n };\n\nvm.runInNewContext('count += 1; name = "kitty"', sandbox, 'myfile.vm');\nconsole.log(util.inspect(sandbox));\n\n// { animal: 'cat', count: 3, name: 'kitty' }
\n신뢰할 수 없는 코드를 실행하는 것은 아주 신중을 요하는 복잡한 작업이다. 의도치않은 전역변수의 누수를 막는데\nvm.runInNewContext
가 아주 유용하지만 신뢰하지 못하는 코드를 안전하게 실행하려면 프로세스를 분리할 필요가\n있다.\n\n
code
에서 문법오류가 있는 경우 vm.runInNewContext
는 stderr에 문법오류를 발생시키고\n예외를 던진다.\n\n
vm.runInContext
는 code
를 컴파일하고 context
에서 실행한 뒤 결과를 반환한다.\n(V8) 컨텍스트는 내장된 객체 및 기능들과 함께 하나의 전역객체로 이루어져 있다.\n실행되는 코드는 지역범위에 접근하지 않고 전역객체는 code
의 전역객체로 사용될\ncontext
내에 있다.\nfilename
는 선택사항이고 스택트레이스에서만 사용된다.\n\n
예제: 존재하는 컨텍스트에서 코드를 컴파일하고 실행한다.\n\n
\nvar util = require('util'),\n vm = require('vm'),\n initSandbox = {\n animal: 'cat',\n count: 2\n },\n context = vm.createContext(initSandbox);\n\nvm.runInContext('count += 1; name = "CATT"', context, 'myfile.vm');\nconsole.log(util.inspect(context));\n\n// { animal: 'cat', count: 3, name: 'CATT' }
\ncreateContext
는 새로 생성된 컨텍스트의 전역객체를 초기화하기 위해서 제공된 샌드박스 객체의 얕은 복제를\n수행할 것이다.\n\n
신뢰할 수 없는 코드를 실행하는 것은 아주 신중을 요하는 복잡한 작업이다. 의도치않은 전역변수의 누수를 막는데\nvm.runInContext
가 아주 유용하지만 신뢰하지 못하는 코드를 안전하게 실행하려면 프로세스를 분리할 필요가\n있다.\n\n
code
에서 문법오류가 있는 경우 vm.runInContext
는 stderr에 문법오류를 발생시키고\n예외를 던진다.\n\n
vm.createContext
는 뒤이은 vm.runInContext
호출의 두 번째 파라미터로 사용하기에 적합한 새로운\n컨텍스트를 생성한다. (V8) 컨텍스트트는 내장된 객체 및 기능들과 함께 하나의 전역객체로 이루어져 있다.\n선택적인 아규먼트인 initSandbox
는 컨텍스트가 사용할 전역객체의 초기 내용을 생성하려고 얕은\n복사가 될 것이다.\n\n
createScript
는 code
를 컴파일하지만 실행하지는 않는다. 대신 컴파일된 코드를 나타내는\nvm.Script
객체를 반환한다. 이 스크립트는 아래의 메서드들을 사용해서 나중에 여려 번\n실행할 수 있다. 반환된 스크립트는 어떤 전역객체에도 바인딩되지 않는다. 반환된 스크립트는 매번\n실행되기 전에 해당 실행에 대해서 바인딩된다. filename
는 선택사항이고 스택트레이스에서만\n사용될 것이다.\n\n
code
에 문법오류가 있는 경우 createScript
는 stderr에 문법오류를 출력하고\n예외를 던진다.\n\n\n
스크립트를 실행하는 클래스. vm.createScript가 반환하는 클래스다.\n\n
\n", "methods": [ { "textRaw": "script.runInThisContext()", "type": "method", "name": "runInThisContext", "desc": "vm.runInThisContext
와 유사하지만 미리 컴파일된 Script
객체의 메서드이다.\nscript.runInThisContext
는 script
의 코드를 실행하고 결과를 반환한다.\n실행되는 코드는 지역범위에 접근하지 않지만 global
객체에는 접근한다.\n(v8: 실제 컨텍스트에서)\n\n
한번 코드를 컴파일하고 여러 번 실행하는 script.runInThisContext
를 사용하는 예제\n\n
var vm = require('vm');\n\nglobalVar = 0;\n\nvar script = vm.createScript('globalVar += 1', 'myfile.vm');\n\nfor (var i = 0; i < 1000 ; i += 1) {\n script.runInThisContext();\n}\n\nconsole.log(globalVar);\n\n// 1000
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "script.runInNewContext([sandbox])",
"type": "method",
"name": "runInNewContext",
"desc": "vm.runInNewContext
와 유사하지만 미리 컴파일된 Script
객체의 메서드이다.\nscript.runInNewContext
는 전역객체인 sandbox
와 함께 script
의 코드를 실행하고 결과를 반환한다.\n실행되는 코드는 지역범위에 접근하지 않는다. sandbox
는 선택사항이다.\n\n
예제: 전역변수가 증가하고 전역변수를 설정하는 코드를 컴파일하고 이 코드를 여러 번 실행한다.\n이 전역변수들은 sandbox안에 있다.\n\n
\nvar util = require('util'),\n vm = require('vm'),\n sandbox = {\n animal: 'cat',\n count: 2\n };\n\nvar script = vm.createScript('count += 1; name = "kitty"', 'myfile.vm');\n\nfor (var i = 0; i < 10 ; i += 1) {\n script.runInNewContext(sandbox);\n}\n\nconsole.log(util.inspect(sandbox));\n\n// { animal: 'cat', count: 12, name: 'kitty' }
\n신뢰할 수 없는 코드를 실행하는 것은 아주 신중을 요하는 복잡한 작업이다. 의도치않은 전역변수의 누수를 막는데\nscript.runInNewContext
가 아주 유용하지만 신뢰하지 못하는 코드를 안전하게 실행하려면 프로세스를\n분리할 필요가 있다.\n\n
Node는 child_process
모듈로 세 방향의 popen(3)
기능을\n제공한다.\n\n
완전한 넌블락킹 방법으로 자식 프로세스의 stdin
, stdout
, stderr
에\n데이터를 스트리밍하는 것이 가능하다. (일부 프로그램은 내부적으로 라인버퍼링 I/O\n(line-buffered I/O)를 사용한다. 이는 node.js에는 영향을 주지 않지만 자식\n프로세스에 보낸 데이터가 즉시 소비되지 않는다는 것을 의미한다.)\n\n
자식 프로세스를 생성하려면 require('child_process').spawn()
나\nrequire('child_process').fork()
를 사용해라. 각각의 의미는\n약간 다른데 아래에서 설명한다.\n\n
ChildProcess
는 [EventEmitter][]이다.\n\n
자식 프로세스들은 자신들과 연관된 세 가지 스트림 child.stdin
, child.stdout
,\nchild.stderr
를 항상 가진다. 이 세 스트림은 부모 프로세스의 stdio 스트림을\n공유하거나 파이프로 연결될 수 있는 스크림을 구분할 것이다.\n\n
ChildProcess 클래스는 직접 사용하도록 만들어 진 것이 아니다. 자식 프로세스의\n인스턴스를 생성하려면 spawn()
나 fork()
를 사용해라.\n\n
다음과 같은 상황에 발생한다.\n\n
\nChildProcess#kill()
와\nChildProcess#send()
도\n참고해라.\n\n
이 이벤트는 자식프로세스가 종료된 후에 발생한다. 프로세스가 정상적으로 종료된다면\ncode
는 프로세스의 최종 종료코드이고 정상적으로 종료되지 않았다면 null
이다.\n프로세스가 신호를 받아서 종료되었다면 signal
는 문자열로 된 신호의 이름이고\n신호를 받아서 종료되지 않았다면 null
이다.\n\n
자식 프로세스의 stdio 스트림은 여전히 열려있을 것이다.\n\n
\nwaitpid(2)
를 봐라.\n\n
이 이벤트는 자식 프로세스의 stdio 스트림이 모두 종료되었을 때 발생한다. 이 이벤트는\n다중 프로세스가 같은 stdio 스트림을 공유할 수도 있으므로 'exit'와는 다르다.\n\n
\n" }, { "textRaw": "Event: 'disconnect'", "type": "event", "name": "disconnect", "desc": "이 이벤트는 부모나 자식의 .disconnect()
메서드를 사용한 수에 발생한다. 연결이 끊긴\n후에는 더이상 메시지를 보낼 수 없다. child.connected
프로퍼티가 true
인지 확인하는\n것이 메시지를 보낼 수 있는지 검사하는 또 다른 방법이다.\n\n
.send(message, [sendHandle])
로 보낸 메시지는 message
이벤트로 받는다.\n\n
자식 프로세스의 stdin
를 나타내는 Writable Stream
이다. end()
로\n이 스트림을 닫으면 종종 자식 프로세스가 종료되기도 한다.\n\n
자식 프로세스의 stdio 스트림이 부모 프로세스와 공유한다면 이 값은 설정되지\n않을 것이다.\n\n
\n" }, { "textRaw": "`stdout` {Stream 객체} ", "name": "stdout", "desc": "자식 프로세스의 stdout
를 나타내는 Readable Stream
이다.\n\n
자식 프로세스의 stdio 스트림이 부모 프로세스와 공유한다면 이 값은 설정되지\n않을 것이다.\n\n
\n" }, { "textRaw": "`stderr` {Stream 객체} ", "name": "stderr", "desc": "자식 프로세스의 stderr
를 나타내는 Readable Stream
이다.\n\n
자식 프로세스의 stdio 스트림이 부모 프로세스와 공유한다면 이 값은 설정되지\n않을 것이다.\n\n
\n" }, { "textRaw": "`pid` {정수} ", "name": "pid", "desc": "자식 프로세스의 PID.\n\n
\n예제:\n\n
\nvar spawn = require('child_process').spawn,\n grep = spawn('grep', ['ssh']);\n\nconsole.log('Spawned child pid: ' + grep.pid);\ngrep.stdin.end();
\n"
}
],
"methods": [
{
"textRaw": "child.kill([signal])",
"type": "method",
"name": "kill",
"signatures": [
{
"params": [
{
"textRaw": "`signal` {문자열} ",
"name": "signal",
"type": "문자열",
"optional": true
}
]
},
{
"params": [
{
"name": "signal",
"optional": true
}
]
}
],
"desc": "자식 프로세스에 신호를 보낸다. 아규먼트를 전달하지 않으면 프로세스는 'SIGTERM'
를 보낼\n것이다. 사용할 수 있는 신호 목록은 signal(7)
를 참고해라.\n\n
var spawn = require('child_process').spawn,\n grep = spawn('grep', ['ssh']);\n\ngrep.on('close', function (code, signal) {\n console.log('child process terminated due to receipt of signal '+signal);\n});\n\n// 프로세스에 SIGHUP를 보낸다\ngrep.kill('SIGHUP');
\n신호를 전송할 수 없을때는 'error'
를 발생시킬 것이다. 종료된 자식 프로세스에 신호를 보내는 것은\n오류가 아니지만 의도치 않은 결과가 될 수 있다. PID(프로세스 ID)가 다른 프로세스에 재할당되었다면\n신호는 해당 프로세스로 전달될 것이고 무슨 일이 일어날 지 아무도 짐작할 수 없다.\n\n
함수의 이름이 kill
이기는 하지만 자식 프로세스에 전달된 신호가 실제로 자식 프로세스를\n죽이지는 않을 것이다. kill
은 프로세스에 단지 신호를 보낼 뿐이다.\n\n
kill(2)
를 참고해라.\n\n
child_process.fork()
를 사용했을 때 child.send(message, [sendHandle])
를\n사용해서 자식에 작성할 수 있고 자식에서는 'message'
이벤트로 메시지를 받는다.\n\n
예를 들어:\n\n
\nvar cp = require('child_process');\n\nvar n = cp.fork(__dirname + '/sub.js');\n\nn.on('message', function(m) {\n console.log('PARENT got message:', m);\n});\n\nn.send({ hello: 'world' });
\n그리고 자식 스크립트인 'sub.js'
는 다음과 같을 것이다.\n\n
process.on('message', function(m) {\n console.log('CHILD got message:', m);\n});\n\nprocess.send({ foo: 'bar' });
\n자식에서 process
객체는 send()
메시지를 가질 것이고 process
는 채널에서\n메시지를 받을 때마다 객체를 발생시킬 것이다.\n\n
{cmd: 'NODE_foo'}
메시지를 보냈을 때 특별한 경우가 있다.\ncmd
프로퍼티에 NODE_
접두사가 있는 모든 메시지는 node 코어에서 사용되는 내부 메시지이므로\nmessage
이벤트에서 발생하지 않을 것이다. 접두사가 있는 메시지들은 internalMessage
이벤트를\n발생시킨다. 이는 별도의 공지없이 변경되므로 이 기능을 사용하지 말아야 한다는 것을 의미한다.\n\n
child.send()
의 sendHandle
옵션은 TCP 서버나 소켓 객체를 다른 프로세스에 보내는\n용도이다. 자식 프로세스는 message
이벤트의 두번째 아규먼트로 이 객체를 받을 것이다.\n\n
메시지를 보낼 수 없다면 'error'
이벤트를 발생시킨다. 예를 들어 자식프로세스가 이미 종료되었다면\n보낼 수 없다.\n\n
다음은 서버를 전송하는 예제다.\n\n
\nvar child = require('child_process').fork('child.js');\n\n// 서버객체를 열고 handle을 전송한다.\nvar server = require('net').createServer();\nserver.on('connection', function (socket) {\n socket.end('부모가 처리한다');\n});\nserver.listen(1337, function() {\n child.send('server', server);\n});
\n자식프로세스는 다음과 같이 서버 객체를 받는다.\n\n
\nprocess.on('message', function(m, server) {\n if (m === 'server') {\n server.on('connection', function (socket) {\n socket.end('자식이 처리한다');\n });\n }\n});
\n서버는 이제 부모와 자식사이에서 공유된다. 이는 연결들이 부모와 자식에서 모두 다룰 수\n있다는 의미이다.\n\n
\ndgram
서버에서 워크플로우는 완전히 동일하다. 여기서 connection
대신 message
이벤트를\n리스닝하고 server.listen
대신 server.bind
를 사용한다. (현재는 UNIX 플랫폼에서만\n지원한다.)\n\n
다음은 소켓을 전송하는 예제다. 이 예제는 두 자식 프로세스를 생성하고 "특별한" 자식 프로세스에\n소켓을 전송해서 VIP인 원격주소 74.125.127.100
의 연결을 다룬다. 다른 소켓들은 "보통의"\n프로세스로 갈 것이다.\n\n
var normal = require('child_process').fork('child.js', ['normal']);\nvar special = require('child_process').fork('child.js', ['special']);\n\n// 서버를 열고 자식 프로세스에 소켓을 전송한다\nvar server = require('net').createServer();\nserver.on('connection', function (socket) {\n\n // VIP 이라면\n if (socket.remoteAddress === '74.125.127.100') {\n special.send('socket', socket);\n return;\n }\n // 그냥 일반적인 소켓들\n normal.send('socket', socket);\n});\nserver.listen(1337);
\nchild.js
는 다음과 같다.\n\n
process.on('message', function(m, socket) {\n if (m === 'socket') {\n socket.end('You were handled as a ' + process.argv[2] + ' person');\n }\n});
\n일단 하나의 소켓을 자식 프로세스에 보내면 부모 프로세서는 소켓이 소멸된 것을 더이상\n추적할 수 없다. 소켓이 소멸된 것을 나타내기 위해 .connections
프로퍼티가\nnull
이 된다.\n이 경우에 .maxConnections
를 사용하지 않기를 권장한다.\n\n
부모와 자식간의 IPC 연결을 닫으려면 child.disconnect()
메서드를 사용해라. 이\n메서드는 살아있는 IPC 채널이 없기 때문에 자식프로세스가 안전적으로 종료할 수 있게 한다.\n이 메서드를 호출했을 때 부모와 자식 모두에서 disconnect
이벤트가 발생할 것이고\nconnected
플래그는 false
가 된다. 자식 프로세스에서 process.disconnect()
를\n호출할 수 있다는 것을 기억해라.\n\n
명령행 아규먼트 args
와 함께 주어진 command
로 새로운 프로세스를 실행한다. 생략할 경우\nargs
의 기본값은 비어있는 배열이다.\n\n
세 번째 아규먼트는 선택적으로 옵션을 지정하기 위해서 사용하면 기본값은 다음과 같다.\n\n
\n{ cwd: undefined,\n env: process.env\n}
\ncwd
로 프로세스가 생성되는(spawn)가 생성되는 워킹 디렉토리를 지정할 수 있다.\nenv
를 사용해서 새로운 프로세스에서 볼 수 있는 환경 변수를 지정한다.\n\n
다음은 ls -lh /usr
를 실행하고 stdout
, stderr
와 종료 코드를 잡는 예제다.\n\n
var spawn = require('child_process').spawn,\n ls = spawn('ls', ['-lh', '/usr']);\n\nls.stdout.on('data', function (data) {\n console.log('stdout: ' + data);\n});\n\nls.stderr.on('data', function (data) {\n console.log('stderr: ' + data);\n});\n\nls.on('close', function (code) {\n console.log('child process exited with code ' + code);\n});
\n예제: 'ps ax | grep ssh'를 실행하는 아주 정교한 방법.\n\n
\nvar spawn = require('child_process').spawn,\n ps = spawn('ps', ['ax']),\n grep = spawn('grep', ['ssh']);\n\nps.stdout.on('data', function (data) {\n grep.stdin.write(data);\n});\n\nps.stderr.on('data', function (data) {\n console.log('ps stderr: ' + data);\n});\n\nps.on('close', function (code) {\n if (code !== 0) {\n console.log('ps process exited with code ' + code);\n }\n grep.stdin.end();\n});\n\ngrep.stdout.on('data', function (data) {\n console.log('' + data);\n});\n\ngrep.stderr.on('data', function (data) {\n console.log('grep stderr: ' + data);\n});\n\ngrep.on('close', function (code) {\n if (code !== 0) {\n console.log('grep process exited with code ' + code);\n }\n});
\n실패한 실행을 확인하는 예제.\n\n
\nvar spawn = require('child_process').spawn,\n child = spawn('bad_command');\n\nchild.stderr.setEncoding('utf8');\nchild.stderr.on('data', function (data) {\n if (/^execvp\\(\\)/.test(data)) {\n console.log('Failed to start child process.');\n }\n});
\nspawn이 비어 있는 옵션 객체를 받으면 process.env
를 사용하는 대신 비어있는\n환경변수를 가진 프로세스를 생성(spawn)할 것이다. 이는 폐기된 API와 관련된 하위\n호환성때문에 존재하는 것이다.\n\n
child_process.spawn()
의 'stdio' 옵션은 자식 프로세스의 fd에 대응하는 각 인덱스\n배열이다. 값은 다음 중 하나이다.\n\n
'pipe'
- 자식프로세스와 부모프로세스간의 파이프를 생성한다.\n파이프의 부모 쪽은 ChildProcess.stdio[fd]
처럼 child_process
객체의 프로퍼티로\n부모에게 노출된다. fd 0 - 2에 대해 생성된 파이프들은 각각 ChildProcess.stdin,\nChildProcess.stdout, ChildProcess.stderr로 사용할 수도 있다.'ipc'
- 부모와 자식간에 메시지/파일 디스크립터를 전달하는 IPC 채널을 생성한다.\nChildProcess는 많아야 하나의 IPC stdio 파일 디스크립터를 가진다. 이 옵션을 설정하면\nChildProcess.send() 메서드가 활성화된다. 자식 프로세스가 이 파일 디스크립터에 JSON\n메시지를 작성한다면 파일디스크립터는 ChildProcess.on('message')를 실행한다. 자식\n프로세스가 Node.js 프로그램이면서 IPC 채널이 있으면 process.send()와\nprocess.on('message') 를 활성화한다.'ignore'
- 자식 프로세스에서 이 파일디스크립터를 설정하지 마라. Node는 생성한\n프로세스에 대해 항상 fd 0 - 2를 연다. 이 중에 무시되는 것이 있다면 node는\n/dev/null
를 열고 자식의 fd에 붙힐 것이다.Stream
객체 - tty, 파일, 소켓, 자식프로세스에 연결된 파이프를 참조하는 읽거나\n쓰기가 가능한 스트림을 공유한다. 스트림이 의존하는 파일 디스크립터는 자식 프로세스에서\nstdio
비열의 인덱스에 대응하는 fd로 복제된다.Stream
객체가 공유되는 방법과 유사하게 자식 프로세스와 공유된다.null
, undefined
- 기본값을 사용한다. stdio fd 0, 1, 2(즉 stdin, stdout,\nstderr)에 대한 파이프를 생성한다. fd 3 이상에 대한 기본값은 'ignore'
이다.간단하게 stdio
아규먼트는 배열보다는 다음 문자열중의 하나가 될 수도 있다.\n\n
ignore
- ['ignore', 'ignore', 'ignore']
pipe
- ['pipe', 'pipe', 'pipe']
inherit
- [process.stdin, process.stdout, process.stderr]
나 [0,1,2]
예제:\n\n
\nvar spawn = require('child_process').spawn;\n\n// 자식은 부모의 stdio를 사용할 것이다\nspawn('prg', [], { stdio: 'inherit' });\n\n// stderr만 공유하는 자식프로세스를 생성한다\nspawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });\n\n// startd 방식의 인터페이스를 제공하는 프로그램과 상호작용하기 위해\n// 여분의 fd=4를 연다\nspawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });
\ndetached
옵션을 설정하면 자식 프로세스가 새로운 프로세스 그룹의 리더가 될 것이다.\n이는 부모가 종료된 후에도 자식 프로세스가 계속해서 동작할 수 있게 한다.\n\n
기본적으로 부모는 분리된(detached) 자식프로세스가 종료되길 기다릴 것이다. 부모가\nchild
을 기다리지 않게 하려면 child.unref()
메서드를 사용해라. 부모의 이벤트루프는\n참조수에 자식을 포함시키지 않을 것이다.\n\n
오랫동안 실행되는 프로세스를 분리하고 출력을 파일로 보내는 예제.\n\n
\n var fs = require('fs'),\n spawn = require('child_process').spawn,\n out = fs.openSync('./out.log', 'a'),\n err = fs.openSync('./out.log', 'a');\n\n var child = spawn('prg', [], {\n detached: true,\n stdio: [ 'ignore', out, err ]\n });\n\n child.unref();
\n오랫동안 동작하는 프로세스를 시작하려고 detached
옵션을 사용해도 stdio
설정을 부모에\n접속하지 않도록 하지 않으면 프로세스는 백그라운드에서 동작하지 않을 것이다. 부모의\nstdio
를 상속받았다면 자식은 제어하는 터미널에 연결된 채로 유지될 것이다.\n\n
자식 프로세스의 stdio에 특정 파일 디스크립터를 지정하는 폐기된 옵션인 customFds
가\n있다. 이 API는 모든 플랫폼에서 사용할 수 있는 것이 아니라서 삭제되었다.\ncustomFds
를 사용해서 새로운 프로세스의 [stdin, stdout, stderr]
를 존재하는\n스트림으로 후킹할 수 있다. -1
은 새로운 스트림이 생성되어야 한다는 것을 의미한다.\n사용할 때는 위험을 감수해라.\n\n
child_process.exec()
와 child_process.fork()
도 참고해라.\n\n
쉘에서 명령어를 실행하고 출력을 버퍼에 넣는다.\n\n
\nvar exec = require('child_process').exec,\n child;\n\nchild = exec('cat *.js bad_file | wc -l',\n function (error, stdout, stderr) {\n console.log('stdout: ' + stdout);\n console.log('stderr: ' + stderr);\n if (error !== null) {\n console.log('exec error: ' + error);\n }\n});
\n콜백은 (error, stdout, stderr)
아규먼트를 받는다. 성공했을 때 error
는 null
이\n된다. 오류가 있을 경우 error
는 Error
의 인스턴스가 되고 err.code
는 자식 프로세스의\n종료코드가 되고 err.signal
은 프로세스를 종료하는 신호로 설정될 것이다.\n\n
두번째 선택적인 아규먼트는 여러가지 옵션을 지정한다. 기본 옵션은 다음과 같다.\n\n
\n{ encoding: 'utf8',\n timeout: 0,\n maxBuffer: 200*1024,\n killSignal: 'SIGTERM',\n cwd: null,\n env: null }
\ntimeout
이 0보다 크면 timeout
밀리초보다 오래 실행되는 경우 자식 프로세스를\n죽일 것이다. 자식 프로세스는 killSignal
(기본값: 'SIGTERM'
) 신호로 죽는다.\nmaxBuffer
는 stdout이나 stderr에서 사용할 수 있는 가장 큰 데이터의 양을\n지정한다. maxBuffer
갑을 초과하면 자식 프로세스는 죽을 것이다.\n\n
하위 쉘을 실행하는 대신에 지정한 파일을 직접 실행한다는 점을 제외하면\nchild_process.exec()
와 유사하다. child_process.exec
보다\n약간 의존적이게 만든다. 이는 같은 옵션을 가진다.\n\n\n
이는 Node 프로세스를 생성하기(spawn) 위해 spawn()
기능의 특별한 경우이다. 게다가\n보통의 ChildProcess 인스턴스에서 모든 메서드를 가지려고 반환된 객체는 내장된\n통신 채널을 가진다. 자세한 내용은 child.send(message, [sendHandle])
를 참고해라.\n\n
기본적으로 생성된(spawned) Node 프로세서는 부모의 stdout, stderr와 연관된\nstdout, stderr를 가질 것이다. 이 동작을 변경하려면 options
객체의 silent
\n프로퍼티를 true
로 설정해라.\n\n
자식 프로세스들은 완료되었다고 자동으로 종료되지 않으므로 명시적으로 process.exit()
를 호출해야\n한다. 차후에는 이 제약사항이 없어질 것이다.\n\n
이러한 자식 노드들도 V8의 완전한 새 인스턴스이다. 새로운 각 노드마다 최소한 30ms의\n구동시간과 10mb의 메모리를 가정해보자. 즉, 수천 개의 노드를 생성할 수 없다.\n\n
\noptions
객체의 execPath
프로퍼티는 현재 실행된 node
대신 자식을 위한 프로세스를 생성할\n수 있게 한다. 이는 조심히 수행되어야 하고 기본적으로 자식프로세스의 NODE_CHANNEL_FD
환경변수를\n나타내는 fd에 얘기할 것이다. 이 fd의 입력과 출력은 라인으로 구분된 JSON 객체일 것이다.\n\n
이 모듈을 어플리케이션에서 유닛 테스트를 작성하는데 사용하고 require('assert')
로\n이 모듈을 사용할 수 있다.\n\n
actual
과 expected
의 값을 보여주는 예외를 던진다.\noperator는 두 값을 무엇으로 비교했는지 표시하는 것이다.\n(역주, operator
는 결국 Error.captureStackTrace로 넘겨지는데 무슨 역활인지 이해할 수 없음. 하지만 assert.js의 코드를 보면 모두 스트링이다. 비교하는데 사용한 함수나 Operator 이름임)\n\n
value가 참인지 검사한다. 이는 assert.equal(true, !!value, message);
와 같다.\n\n
==
오퍼레이터로 같음(shallow, coercive equality)을 검사한다.\n\n
!=
오퍼레이터로 다름(shallow, coercive non-equality)을 검사한다.\n\n
깊은 동등성을 검사한다.\n(역주, deep equality는 한마디로 설명하기 어렵다. 타입마다 다른 방법으로 같음을 테스트한다. 예를 들어, Date의 경우 actual.getTime() === expected.getTime()
라고 비교한다. 필요하다면 assert.js을 일독하기를 권한다)\n\n
다름(deep inequality)를 검사한다.\n\n
\n", "signatures": [ { "params": [ { "name": "actual" }, { "name": "expected" }, { "name": "message", "optional": true } ] } ] }, { "textRaw": "assert.strictEqual(actual, expected, [message])", "type": "method", "name": "strictEqual", "desc": "===
오퍼레이터로 같음(strict equality)을 테스트한다.\n\n
!==
오퍼레이터로 다름(strict non-equality)을 테스트한다.\n\n
block
이 오류는 던지기를 기대한다. error
는 생성자, 정규표현식, 유효성검사 함수가\n될 수 있다.\n\n
생성자의 인스턴스인지 테스트한다.\n\n
\nassert.throws(\n function() {\n throw new Error("Wrong value");\n },\n Error\n);
\nRegExp를 사용해서 오류 메시지를 검증한다.\n\n
\nassert.throws(\n function() {\n throw new Error("Wrong value");\n },\n /value/\n);
\n자신만의 방법으로 오류를 검증한다.\n\n
\nassert.throws(\n function() {\n throw new Error("Wrong value");\n },\n function(err) {\n if ( (err instanceof Error) && /value/.test(err) ) {\n return true;\n }\n },\n "unexpected error"\n);
\n",
"signatures": [
{
"params": [
{
"name": "block"
},
{
"name": "error",
"optional": true
},
{
"name": "message",
"optional": true
}
]
}
]
},
{
"textRaw": "assert.doesNotThrow(block, [message])",
"type": "method",
"name": "doesNotThrow",
"desc": "block
이 오류를 던지지 않기를 기대한다. 자세한 내용은 assert.throws를 참고해라.\n\n
value가 true인지 테스트하고 true이면 그 value를 던진다. 콜백에서 첫 아규먼트\nerror
를 검사하는 데 유용하다.\n(역주, 예를 들면 fs.readFile('notfound.js', assert.ifError);
라고 사용할 수 있어서 유용하다는 것이다)\n\n
tty
모듈에는 tty.ReadStream
과 tty.WriteStream
클래스가 들어 있다. 보통 이 모듈을 직접 사용할 일은 별로 없다.\n\n
TTY 컨텍스트에서 실행되면 자동으로 process.stdin
을 tty.ReadStream
인스턴스로 만들고 process.stdout
은 tty.WriteStream
인스턴스로 만든다. process.stdout.isTTY
를 검사하면 node가 TTY 컨텍스트에서 실행되는지 아닌지 알 수 있다.\n\n
$ node -p -e "Boolean(process.stdout.isTTY)"\ntrue\n$ node -p -e "Boolean(process.stdout.isTTY)" | cat\nfalse
\n",
"methods": [
{
"textRaw": "tty.isatty(fd)",
"type": "method",
"name": "isatty",
"desc": "fd가 터미널 파일 디스크립터인지에 따라 true
나 false
를 리턴한다.\n\n
Deprecated 됐다. tty.ReadStream#setRawMode()
를 사용하라(i.e. process.stdin.setRawMode()
).\n\n
TTY 읽기를 담당하는 net.Socket
서브클래스이다. 보통 node 프로그램의 process.stdin
은 tty.ReadStream
인스턴스이다(isatty(0)
가 true일 때만).\n\n
이 프로퍼티는 false
로 초기화된다. tty.ReadStream
인스턴스가 현재 "raw" 상태임을 나타낸다.\n\n
mode
에는 true
나 false
를 넘긴다. mode가 true이면 tty.ReadStream
프로퍼티가 raw 디바이스 처럼 동작하도록 설정하고 아니면 기본 값이 설정된다. isRaw
프로퍼티로 어떻게 설정했는지 알 수 있다.\n\n
TTY 쓰기를 담당하는 net.Socket
서브클래스이다. 보통 node 프로그램의 process.stdout
은 tty.ReadStream
인스턴스이다(isatty(1)
가 true일 때만).\n\n\n
이 프로퍼티는 현 TTY의 컬럼 수이다. "resize" 이벤트 시 업데이트된다.\n\n
\n" }, { "textRaw": "ws.rows", "name": "rows", "desc": "이 프로퍼티는 현 TTY의 로우 수이다. "resize" 이벤트 시 업데이트된다.\n\n
\n" } ], "events": [ { "textRaw": "Event: 'resize'", "type": "event", "name": "resize", "desc": "function () {}
\n\n
columns
나 rows
프로퍼티가 변경될 때 발생한다.\n\n
process.stdout.on('resize', function() {\n console.log('screen size has changed!');\n console.log(process.stdout.columns + 'x' + process.stdout.rows);\n});
\n",
"params": []
}
]
}
],
"type": "module",
"displayName": "TTY"
},
{
"textRaw": "Zlib",
"name": "zlib",
"stability": 3,
"stabilityText": "Stable",
"desc": "이 모듈은 다음과 같은 방법으로 접근한다:\n\n
\nvar zlib = require('zlib');
\n이 모듈은 Gzip/Uunzip, Deflate/Inflate, DeflateRaw/InflateRaw 클래스에 대한 바인딩이다. 각 클래스는 읽기/쓰기 가능한 스트림이고 옵션은 모두 동일하다.\n\n
\n파일을 압축하거나 압축을 푸는 일은 fs.ReadStream()으로 파일을 읽어서 zlib 스트림으로 보내고 나서(pipe) 다시 fs.WriteStream에 보내는(pipe) 것으로 이루어진다.\n\n
\nvar gzip = zlib.createGzip();\nvar fs = require('fs');\nvar inp = fs.createReadStream('input.txt');\nvar out = fs.createWriteStream('input.txt.gz');\n\ninp.pipe(gzip).pipe(out);
\n데이터를 압축하고 압축을 푸는 일은 간단하게 단축 메소드로(convenience method) 한방에 할 수 있다:\n\n
\nvar input = '.................................';\nzlib.deflate(input, function(err, buffer) {\n if (!err) {\n console.log(buffer.toString('base64'));\n }\n});\n\nvar buffer = new Buffer('eJzT0yMAAGTvBe8=', 'base64');\nzlib.unzip(buffer, function(err, buffer) {\n if (!err) {\n console.log(buffer.toString());\n }\n});
\nHTTP client나 server에서 이 모듈를 사용하려면 request에서 사용할 수 있는 accept-encoding을 보고 response에서는 content-encoding를 보면 된다.\n\n
\nNote: 이 예제는 기본 개념을 보여주기 위해 극도로 단순화한 것임. Zlib 인코딩은 비싸서 결과물을 캐시하는게 좋다.\nMemory Usage Tuning을 보면 zlib 튜닝시 speed/memory/compression에 대해 고려해야 하는 점이 나와 있다.\n\n
\n// 클라이언트 요청 예제\nvar zlib = require('zlib');\nvar http = require('http');\nvar fs = require('fs');\nvar request = http.get({ host: 'izs.me',\n path: '/',\n port: 80,\n headers: { 'accept-encoding': 'gzip,deflate' } });\nrequest.on('response', function(response) {\n var output = fs.createWriteStream('izs.me_index.html');\n\n switch (response.headers['content-encoding']) {\n // 또는 두 경우를 모두 다루기 위해서 그냥 zlib.createUnzip()를 사용해라.\n case 'gzip':\n response.pipe(zlib.createGunzip()).pipe(output);\n break;\n case 'deflate':\n response.pipe(zlib.createInflate()).pipe(output);\n break;\n default:\n response.pipe(output);\n break;\n }\n});\n\n// 서버 예제\n// 요청마다 gzip을 수행하는 것은 비용이 큰 작업이다.\n// 압축된 버퍼를 캐시해서 훨씬 효율적이 될 수 있다.\nvar zlib = require('zlib');\nvar http = require('http');\nvar fs = require('fs');\nhttp.createServer(function(request, response) {\n var raw = fs.createReadStream('index.html');\n var acceptEncoding = request.headers['accept-encoding'];\n if (!acceptEncoding) {\n acceptEncoding = '';\n }\n\n // Note: 이는 적합한 accept-encoding 파서는 아니다.\n // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3 를 봐라.\n if (acceptEncoding.match(/\\bdeflate\\b/)) {\n response.writeHead(200, { 'content-encoding': 'deflate' });\n raw.pipe(zlib.createDeflate()).pipe(response);\n } else if (acceptEncoding.match(/\\bgzip\\b/)) {\n response.writeHead(200, { 'content-encoding': 'gzip' });\n raw.pipe(zlib.createGzip()).pipe(response);\n } else {\n response.writeHead(200, {});\n raw.pipe(response);\n }\n}).listen(1337);
\n",
"methods": [
{
"textRaw": "zlib.createGzip([options])",
"type": "method",
"name": "createGzip",
"desc": "options으로 Gzip 객채를 새로 만들어 리턴한다.\n\n
\n", "signatures": [ { "params": [ { "name": "options", "optional": true } ] } ] }, { "textRaw": "zlib.createGunzip([options])", "type": "method", "name": "createGunzip", "desc": "options으로 Gunzip 객채를 새로 만들어 리턴한다.\n\n
\n", "signatures": [ { "params": [ { "name": "options", "optional": true } ] } ] }, { "textRaw": "zlib.createDeflate([options])", "type": "method", "name": "createDeflate", "desc": "options으로 Deflate 객채를 새로 만들어 리턴한다.\n\n
\n", "signatures": [ { "params": [ { "name": "options", "optional": true } ] } ] }, { "textRaw": "zlib.createInflate([options])", "type": "method", "name": "createInflate", "desc": "options으로 Inflate 객채를 새로 만들어 리턴한다.\n\n
\n", "signatures": [ { "params": [ { "name": "options", "optional": true } ] } ] }, { "textRaw": "zlib.createDeflateRaw([options])", "type": "method", "name": "createDeflateRaw", "desc": "options으로 DeflateRaw 객채를 새로 만들어 리턴한다.\n\n
\n", "signatures": [ { "params": [ { "name": "options", "optional": true } ] } ] }, { "textRaw": "zlib.createInflateRaw([options])", "type": "method", "name": "createInflateRaw", "desc": "options으로 InflateRaw 객채를 새로 만들어 리턴한다.\n\n
\n", "signatures": [ { "params": [ { "name": "options", "optional": true } ] } ] }, { "textRaw": "zlib.createUnzip([options])", "type": "method", "name": "createUnzip", "desc": "options으로 Unzip 객채를 새로 만들어 리턴한다.\n\n\n
\n", "signatures": [ { "params": [ { "name": "options", "optional": true } ] } ] }, { "textRaw": "zlib.deflate(buf, callback)", "type": "method", "name": "deflate", "desc": "Deflate로 스트링을 압축한다.\n\n
\n", "signatures": [ { "params": [ { "name": "buf" }, { "name": "callback" } ] } ] }, { "textRaw": "zlib.deflateRaw(buf, callback)", "type": "method", "name": "deflateRaw", "desc": "DeflateRaw로 스트링을 압축한다.\n\n
\n", "signatures": [ { "params": [ { "name": "buf" }, { "name": "callback" } ] } ] }, { "textRaw": "zlib.gzip(buf, callback)", "type": "method", "name": "gzip", "desc": "Gzip으로 스트링을 압축한다.\n\n
\n", "signatures": [ { "params": [ { "name": "buf" }, { "name": "callback" } ] } ] }, { "textRaw": "zlib.gunzip(buf, callback)", "type": "method", "name": "gunzip", "desc": "Gunzip으로 Buffer의 압축을 푼다.\n\n
\n", "signatures": [ { "params": [ { "name": "buf" }, { "name": "callback" } ] } ] }, { "textRaw": "zlib.inflate(buf, callback)", "type": "method", "name": "inflate", "desc": "Inflate로 Buffer의 압축을 푼다.\n\n
\n", "signatures": [ { "params": [ { "name": "buf" }, { "name": "callback" } ] } ] }, { "textRaw": "zlib.inflateRaw(buf, callback)", "type": "method", "name": "inflateRaw", "desc": "InflateRaw로 Buffer의 압축을 푼다.\n\n
\n", "signatures": [ { "params": [ { "name": "buf" }, { "name": "callback" } ] } ] }, { "textRaw": "zlib.unzip(buf, callback)", "type": "method", "name": "unzip", "desc": "Unzip으로 Buffer의 압축을 푼다.\n\n
\n", "signatures": [ { "params": [ { "name": "buf" }, { "name": "callback" } ] } ] } ], "classes": [ { "textRaw": "Class: zlib.Zlib", "type": "class", "name": "zlib.Zlib", "desc": "zlib
모듈이 익스포트하지 않는다. 여기서 문서화한 이유는 compressor/decompressor 클래스의\n기반 클래스이기 때문이다.\n\n
지연되고 있는 데이터를 내보낸다. 경박하게 호출하지 말아라. 너무 이른 플러시는\n압축 알고리즘의 효율성에 부정적인 영향을 준다.\n\n
\n", "signatures": [ { "params": [ { "name": "callback" } ] } ] }, { "textRaw": "zlib.reset()", "type": "method", "name": "reset", "desc": "compressor/decompressor를 원래의 기본값으로 리셋한다.\ninflate와 deflate 알로리즘에만 적용할 수 있다.\n\n
\n", "signatures": [ { "params": [] } ] } ] }, { "textRaw": "Class: zlib.Gzip", "type": "class", "name": "zlib.Gzip", "desc": "gzip으로 데이터를 압축한다.\n\n
\n" }, { "textRaw": "Class: zlib.Gunzip", "type": "class", "name": "zlib.Gunzip", "desc": "gzip 스트림의 압축을 푼다.\n\n
\n" }, { "textRaw": "Class: zlib.Deflate", "type": "class", "name": "zlib.Deflate", "desc": "deflate로 데이터를 압축한다.\n\n
\n" }, { "textRaw": "Class: zlib.Inflate", "type": "class", "name": "zlib.Inflate", "desc": "deflate 스트림의 압축을 푼다.\n\n
\n" }, { "textRaw": "Class: zlib.DeflateRaw", "type": "class", "name": "zlib.DeflateRaw", "desc": "deflate로 데이터를 압축하지만 zlib 헤더는 넣지 않는다.\n\n
\n" }, { "textRaw": "Class: zlib.InflateRaw", "type": "class", "name": "zlib.InflateRaw", "desc": "raw deflate 스트림의 압축을 푼다.\n\n
\n" }, { "textRaw": "Class: zlib.Unzip", "type": "class", "name": "zlib.Unzip", "desc": "Gzip-이나 Deflate-로 압축한 스트림의 헤더를 자동으로 찾아서 압축을 푼다.\n\n
\n" } ], "miscs": [ { "textRaw": "Convenience Methods", "name": "Convenience Methods", "type": "misc", "desc": "여기에 있는 모든 메소드는 첫번째 아규먼트로 버퍼나 스트링을 받는다. 그리고 콜백도 callback(error, result)
형식으로 호출한다. 압축/압축해제 엔진은 기본 설정으로 생성하고 다른 옵션으로 생성하고 싶으면 zlib 클래스를 직접사용해야 한다.\n\n
모든 클래스는 옵션 객체를 아규먼트로 받고 생략 가능하다(단축 메소드는 기본값을 사용한다).\n\n
\n어떤 옵션은 압축 클래스에만 사용하고 압축을 푸는 클래스에서는 무시한다.\n\n
\nzlib.Z_NO_FLUSH
)deflateInit2
와 inflateInit2
의 설명은 http://zlib.net/manual.html#Advanced 페이지에서 보라.\n\n
zlib/zconf.h
에 있는 설정을 node에 맞게 수정하는 법:\n\n
deflate할 때 필요한 메모리(바이트 단위):\n\n
\n(1 << (windowBits+2)) + (1 << (memLevel+9))
\n이 표현은 windowBits=15일 때 128K가 필요하고 memLevel=8일 때 128k가 더 필요하다는 뜻이다(기본값임). 그리고 객체에 필요한 몇 킬로 바이트가 더 든다.\n\n
\n만약 필요한 메모리를 256K에서 128K로 줄이고 싶으면 옵션을 다음과 같이 주면된다:\n\n
\n{ windowBits: 14, memLevel: 7 }
\n물론 이 설정은 압축 성능을 떨어뜨린다(공짜 점심은 없다).\n\n
\ninflate에 필요한 메모리(바이트단위):\n\n
\n1 << windowBits
\n이 표현은 windowBits=15일 때 32K가 필요하다는 말이다(기본값임). 그리고 객체에 필요한 몇 킬로바이트가 더 든다.\n\n
\n그리고 내부에 결과물을 위한 버퍼가 하나 있다. chunkSize
의 값이 버퍼의 크기인데 기본 값은 16K이다.\n\n
zlib 압축의 속도는 level
설정이 가장 큰 영향을 끼친다. 레벨을 높이면 압축률은 높아지지만 더 오래 걸린다. 레벨을 낮추면 압축률은 낮아지지만 더 빨라진다.\n\n
보통 메모리를 크게 잡으면 write
오퍼레이션을 한번 할 때 데이터를 더 많이 처리하기 때문에 Node가 zlib을 더 적게 호출한다. 그래서 이 요소도 속도와 메모리 사용 효율에 영향을 준다.\n\n
zlib.h에 정의된 상수는 require('zlib')
에도 정의돼 있다. 보통은 세세한 설정이 필요하지 않지만, 여기에서는 어떤 상수들이 있는지 설명한다. 이 절의 내용은 zlib documentation에서 거의 그대로 베껴왔다. 자세한 내용은 http://zlib.net/manual.html#Constants를 보라.\n\n
허용되는 flush 옵션.\n\n
\nzlib.Z_NO_FLUSH
zlib.Z_PARTIAL_FLUSH
zlib.Z_SYNC_FLUSH
zlib.Z_FULL_FLUSH
zlib.Z_FINISH
zlib.Z_BLOCK
zlib.Z_TREES
압축/압축해제 함수가 리턴하는 코드. 에러일 경우 코드값이 음수 값이고 성공 시에는 양수 값이다.\n\n
\nzlib.Z_OK
zlib.Z_STREAM_END
zlib.Z_NEED_DICT
zlib.Z_ERRNO
zlib.Z_STREAM_ERROR
zlib.Z_DATA_ERROR
zlib.Z_MEM_ERROR
zlib.Z_BUF_ERROR
zlib.Z_VERSION_ERROR
압축 레벨.\n\n
\nzlib.Z_NO_COMPRESSION
zlib.Z_BEST_SPEED
zlib.Z_BEST_COMPRESSION
zlib.Z_DEFAULT_COMPRESSION
압축 전략.\n\n
\nzlib.Z_FILTERED
zlib.Z_HUFFMAN_ONLY
zlib.Z_RLE
zlib.Z_FIXED
zlib.Z_DEFAULT_STRATEGY
data_type 필드에서 허용하는 값.\n\n
\nzlib.Z_BINARY
zlib.Z_TEXT
zlib.Z_ASCII
zlib.Z_UNKNOWN
deflate 압축 방법(이 버전에서만 지원한다).\n\n
\nzlib.Z_DEFLATED
zalloc, zfree, opaque를 초기화를 위해 사용한다.\n\n
\nzlib.Z_NULL
OS 유틸리티 함수를 몇 개 제공한다.\n\n
\n이 모듈은 require('os')
로 접근한다.\n\n
OS의 임시 파일 디렉토리를 리턴한다.\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "os.endianness()", "type": "method", "name": "endianness", "desc": "CPU의 엔디언(endianness)을 반환한다. 가능한 값은 "BE"
나 "LE"
이다.\n\n
OS의 호스트 이름을 리턴한다.\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "os.type()", "type": "method", "name": "type", "desc": "OS 이름을 리턴한다(역주, 'Linux').\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "os.platform()", "type": "method", "name": "platform", "desc": "OS 플랫폼을 리턴한다(역주, 'linux').\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "os.arch()", "type": "method", "name": "arch", "desc": "OS CPU 아키텍처를 리턴한다(역주, 'x64').\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "os.release()", "type": "method", "name": "release", "desc": "OS 버전을 리턴한다(역주, '3.2.0-26-generic').\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "os.uptime()", "type": "method", "name": "uptime", "desc": "시스템 구동시간을 초 단위로 리턴한다(역주, 50515.673530518).\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "os.loadavg()", "type": "method", "name": "loadavg", "desc": "1, 5, 15 분 로드 평균값을 배열에 담아 리턴한다.\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "os.totalmem()", "type": "method", "name": "totalmem", "desc": "시스템 메모리의 총량을 바이트 단위로 리턴한다.\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "os.freemem()", "type": "method", "name": "freemem", "desc": "시스템의 여유 메모리를 바이트 단위로 리턴한다.\n\n
\n", "signatures": [ { "params": [] } ] }, { "textRaw": "os.cpus()", "type": "method", "name": "cpus", "desc": "모든 CPU/코어에 대한 정보를 배열에 담아서 그 배열을 리턴한다. CPU/코어에 대한 정보는\nmodel, speed(MHz 단위), times(user, nide, sys, idle, irq로 분류해서 각각\n사용한 CPU 타임(CPU 틱의 수)이다.\n\n
\nos.cpus의 결과:\n\n
\n[ { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',\n speed: 2926,\n times:\n { user: 252020,\n nice: 0,\n sys: 30340,\n idle: 1070356870,\n irq: 0 } },\n { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',\n speed: 2926,\n times:\n { user: 306960,\n nice: 0,\n sys: 26980,\n idle: 1071569080,\n irq: 0 } },\n { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',\n speed: 2926,\n times:\n { user: 248450,\n nice: 0,\n sys: 21750,\n idle: 1070919370,\n irq: 0 } },\n { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',\n speed: 2926,\n times:\n { user: 256880,\n nice: 0,\n sys: 19430,\n idle: 1070905480,\n irq: 20 } },\n { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',\n speed: 2926,\n times:\n { user: 511580,\n nice: 20,\n sys: 40900,\n idle: 1070842510,\n irq: 0 } },\n { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',\n speed: 2926,\n times:\n { user: 291660,\n nice: 0,\n sys: 34360,\n idle: 1070888000,\n irq: 10 } },\n { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',\n speed: 2926,\n times:\n { user: 308260,\n nice: 0,\n sys: 55410,\n idle: 1071129970,\n irq: 880 } },\n { model: 'Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz',\n speed: 2926,\n times:\n { user: 266450,\n nice: 1480,\n sys: 34920,\n idle: 1072572010,\n irq: 30 } } ]
\n",
"signatures": [
{
"params": []
}
]
},
{
"textRaw": "os.networkInterfaces()",
"type": "method",
"name": "networkInterfaces",
"desc": "네트워크 인터페이스의 목록을 리턴한다:\n\n
\n{ lo0:\n [ { address: '::1', family: 'IPv6', internal: true },\n { address: 'fe80::1', family: 'IPv6', internal: true },\n { address: '127.0.0.1', family: 'IPv4', internal: true } ],\n en1:\n [ { address: 'fe80::cabc:c8ff:feef:f996', family: 'IPv6',\n internal: false },\n { address: '10.0.1.123', family: 'IPv4', internal: false } ],\n vmnet1: [ { address: '10.99.99.254', family: 'IPv4', internal: false } ],\n vmnet8: [ { address: '10.88.88.1', family: 'IPv4', internal: false } ],\n ppp0: [ { address: '10.2.0.231', family: 'IPv4', internal: false } ] }
\n",
"signatures": [
{
"params": []
}
]
}
],
"properties": [
{
"textRaw": "os.EOL",
"name": "EOL",
"desc": "Node를 실행하는 OS용 End-of-line 상수.\n\n\n
\n" } ], "type": "module", "displayName": "os" }, { "textRaw": "Cluster", "name": "cluster", "stability": 1, "stabilityText": "Experimental", "desc": "Node 프로세스 하나는 쓰레드 하나로 동작한다. 멀티 코어 시스템을 이용해서 부하를 처리하려면\nNode 프로세스를 여러 개 띄울 필요가 있다.\n\n
\n이 cluster 모듈은 서버 포트를 공유하는 프로세스 다발을 쉽게 만들 수 있게 해준다.\n\n
\nvar cluster = require('cluster');\nvar http = require('http');\nvar numCPUs = require('os').cpus().length;\n\nif (cluster.isMaster) {\n // 워커를 포크한다.\n for (var i = 0; i < numCPUs; i++) {\n cluster.fork();\n }\n\n cluster.on('exit', function(worker, code, signal) {\n console.log('worker ' + worker.process.pid + ' died');\n });\n} else {\n // 워커는 TCP 연결을 공유할 수 있다.\n // 이 예제는 HTTP 서버이다.\n http.createServer(function(req, res) {\n res.writeHead(200);\n res.end("hello world\\n");\n }).listen(8000);\n}
\n이 프로그램에서 워커는 8000번 포트를 공유한다:\n\n
\n% NODE_DEBUG=cluster node server.js\n23521,Master Worker 23524 online\n23521,Master Worker 23526 online\n23521,Master Worker 23523 online\n23521,Master Worker 23528 online
\n이 기능은 최근에 추가돼서 앞으로 변경될 수 있다. 해보고 안되면 피드백을 주길 바란다.\n\n
\nWindows에서는 네임드 파이프 서버를 만들 수 없으므로 주의해야 한다.\n\n
\n", "miscs": [ { "textRaw": "How It Works", "name": "How It Works", "type": "misc", "desc": "워커 프로세스는 child_process.fork
메소드로 생성(spawn)하기 때문에 IPC로 부모 프로세스와\n통신하고 서버 핸들을 서로 주고받을 수 있다.\n\n
워커에서 server.listen(...)
를 호출하면 아규먼트를 직열화하고 요청을 마스터 프로세스에 보낸다.\n마스터 프로세스에 있는 리스닝 서버가 워커의 요구사항에 맞으면 그 핸들을 워커에 넘긴다. 만약 워커에\n필요한 리스닝 서버가 없으면 하나 만들어서 자식 프로세스에 핸들을 넘긴다.\n\n
그래서 극단적인 상황에서(edge case) 다음과 같은 행동을 보인다.:\n\n
\nserver.listen({fd: 7})
메시지를 마스터에 보내기 때문에 부모에서 7번 파일 디스크립터를\nListen하기 시작하고 그 핸들이 워커로 넘겨진다. 7번 파일 디스크립터가 무엇인지 워커에 묻거나\n하는 것이 아니다.server.listen(handle)
핸들에 직접 Listen하면 워커는 넘긴 핸들을 사용한다.\n마스터에 메시지를 보내지 않는다. 워커가 이미 핸들을 가지고 있으면 이렇게 호출하는 사람은\n자신이 무슨짓을 하는 것인지 알고 있다고 간주된다.server.listen(0)
이렇게 호출하면 서버는 랜덤 포트에 Listen한다. 하지만, cluster에서는\n워커가 listen(0)
를 호출할 때마다 동일한 랜덤 포트를 받는다. 사실 처음에만 랜덤이지\n그 다음부터는 예측 가능하다. 워커마다 고유한(unique) 포트를 사용하려면 워커 ID를 이용해서\n포트 넘버를 직접 생성하라.같은 리소스에 accept()
하는 프로세스가 여러 개이면 운영체제는 매우 효율적으로 Load-balance를\n한다. Node.js에는 라우팅 로직이 없고 워커끼리 상태 정보도 공유하지도 않는다. 그러므로 로그인이나\n세션 정보 같은 것을 메모리에 너무 과도하게 상주하지 않도록 프로그램을 설계하는 것이 중요하다.\n\n
워커는 서로 독립적인 프로세스이므로 프로그램의 필요에 따라 죽이거나(kill) 재생성(re-spawn)할 수\n있다. 워커가 살아 있는 한 새 연결을 계속 수락한다. Node는 워커를 관리해주지 않는다. 애플리케이션에\n필요한대로 워커 풀을 관리하는 것은 개발자 책임이다.\n\n
\n" } ], "properties": [ { "textRaw": "`settings` {Object} ", "name": "settings", "desc": ".setupMaster()
메소드로 설정하면 이 settings 객체에 저장된다.\n이 객체를 직접 수정하지 말아야 한다.\n\n
프로세스가 마스터이면 true를 리턴한다. 이 프로퍼티는 process.env.NODE_UNIQUE_ID
값을\n이용하는데 process.env.NODE_UNIQUE_ID
이 undefined이면 isMaster
는 true이다.\n\n
해당 프로세스가 워커면 true를 리턴한다. 이 프로퍼티는 process.env.NODE_UNIQUE_ID
값을\n이용하는데 process.env.NODE_UNIQUE_ID
프로퍼티에 값이 할당돼 있으면 true이다.\n\n
현재 워커 객체에 대한 참조. 마스터 프로세스에서는 사용할 수 없다.\n\n
\nvar cluster = require('cluster');\n\nif (cluster.isMaster) {\n console.log('I am master');\n cluster.fork();\n cluster.fork();\n} else if (cluster.isWorker) {\n console.log('I am worker #' + cluster.worker.id);\n}
\n"
},
{
"textRaw": "`workers` {Object} ",
"name": "workers",
"desc": "살아있는 워커 객체가 저장되는 해쉬로 id
필드가 키다. 모든 워커를 쉽게 순회할 수 있다.\n이는 마스터 프로세스에서만 사용할 수 있다.\n\n
// 모든 워커에 적용한다.\nfunction eachWorker(callback) {\n for (var id in cluster.workers) {\n callback(cluster.workers[id]);\n }\n}\neachWorker(function(worker) {\n worker.send('big announcement to all workers');\n});
\n통신으로 워커 레퍼런스를 주고받아야 하는 상황이라면 워커 id를 주고받는 것이 가장 좋다.\n\n
\nsocket.on('data', function(id) {\n var worker = cluster.workers[id];\n});
\n"
}
],
"events": [
{
"textRaw": "Event: 'fork'",
"type": "event",
"name": "fork",
"params": [],
"desc": "워커가 하나 새로 포크되면 cluster 모듈은 'fork' 이벤트를 발생(emit)시킨다. 워커의 액티비티\n로그를 남기거나 타임아웃을 생성하는 데 활용된다.\n\n
\nvar timeouts = [];\nfunction errorMsg() {\n console.error("Something must be wrong with the connection ...");\n}\n\ncluster.on('fork', function(worker) {\n timeouts[worker.id] = setTimeout(errorMsg, 2000);\n});\ncluster.on('listening', function(worker, address) {\n clearTimeout(timeouts[worker.id]);\n});\ncluster.on('exit', function(worker, code, signal) {\n clearTimeout(timeouts[worker.id]);\n errorMsg();\n});
\n"
},
{
"textRaw": "Event: 'online'",
"type": "event",
"name": "online",
"params": [],
"desc": "워커를 포크하면 워커는 '온라인' 메시지를 보낸다. 마스터가 그 '온라인' 메시지를 받으면 이 이벤트를\n발생한다. 'fork' 이벤트와 'online' 이벤트의 차이는 간단하다. 'fork' 이벤트는 마스터가\n워커 프로세스를 포크할 때 발생하는 것이고 'online' 이벤트는 워커가 실행되면 발생한다.\n\n
\ncluster.on('online', function(worker) {\n console.log("Yay, the worker responded after it was forked");\n});
\n"
},
{
"textRaw": "Event: 'listening'",
"type": "event",
"name": "listening",
"params": [],
"desc": "워커에서 listen()
을 호출하면 자동으로 'listening' 이벤트가 서버 인스턴스에 발생한다.\n서버가 listening 중이면 listening' 이벤트가 발생한 마스터는 메시지를 하나 받는다.\n\n
이벤트 핸들러의 아규먼트는 두 개다. worker
에는 해당 워커 객체가 넘어오고 address
에는\naddress
, port
, addressType
프로퍼티가 있는 address
객체가 넘어온다.\n이 이벤트는 워커가 하나 이상의 주소를 Listen할 때 유용하다.\n\n
cluster.on('listening', function(worker, address) {\n console.log("A worker is now connected to " + address.address + ":" + address.port);\n});
\n"
},
{
"textRaw": "Event: 'disconnect'",
"type": "event",
"name": "disconnect",
"params": [],
"desc": "워커의 IPC 채널이 끊기면 이 이벤트가 발생한다. 워커가 죽을 때도 이 이벤트가 발생한다.\n.kill()
를 호출해서 워커가 죽을 때도 발생한다.\n\n
.disconnect()
를 호출하면 disconnect
와 exit
이벤트 사이에 약간의 딜레이가 있을 수\n있다. 이 이벤트는 아직 살아있는 연결이 있는지 확인하거나 프로세스가 소거 중인지 확인할 때 유용하다:\n\n
cluster.on('disconnect', function(worker) {\n console.log('The worker #' + worker.id + ' has disconnected');\n});
\n"
},
{
"textRaw": "Event: 'exit'",
"type": "event",
"name": "exit",
"params": [],
"desc": "워커가 죽으면 cluster 모듈에 'exit' 이벤트가 발생한다. 그래서 워커가 죽으면 fork()
를\n호출해서 워커를 다시 띄울 수 있다.\n\n
cluster.on('exit', function(worker, code, signal) {\n var exitCode = worker.process.exitCode;\n console.log('worker ' + worker.process.pid + ' died ('+exitCode+'). restarting...');\n cluster.fork();\n});
\n"
},
{
"textRaw": "Event: 'setup'",
"type": "event",
"name": "setup",
"params": [],
"desc": ".setupMaster()
함수를 실행하면 이 이벤트가 발생한다. fork()
를 호출하기 전에\n.setupMaster()
가 한 번도 실행된 적이 없으면 fork()
를 실행할 때 아규먼트 없이\n.setupMaster()
가 한번 호출된다.\n\n
setupMaster
는 'fork'의 기본 행동을 수정하는데 사용한다. 사실상 새로운 설정은 즉각적이고\n영구적이라서 나중에 이를 수정할 수 없다.\n\n
예제:\n\n
\nvar cluster = require("cluster");\ncluster.setupMaster({\n exec : "worker.js",\n args : ["--use", "https"],\n silent : true\n});\ncluster.fork();
\n"
},
{
"textRaw": "cluster.fork([env])",
"type": "method",
"name": "fork",
"signatures": [
{
"return": {
"textRaw": "return {Worker 객체} ",
"name": "return",
"type": "Worker 객체"
},
"params": [
{
"textRaw": "`env` {Object} 자식 프로세스의 환경변수, Key/value ",
"name": "env",
"type": "Object",
"desc": "자식 프로세스의 환경변수, Key/value",
"optional": true
}
]
},
{
"params": [
{
"name": "env",
"optional": true
}
]
}
],
"desc": "워커 프로세스를 하나 만든다(spawn). 이 함수는 마스터 프로세스에서만 호출할 수 있다.\n\n
\n" }, { "textRaw": "cluster.disconnect([callback])", "type": "method", "name": "disconnect", "signatures": [ { "params": [ { "textRaw": "`callback` {Function} 모든 워커가 Disconnect되고 핸들러가 닫히면 호출되는 함수 ", "name": "callback", "type": "Function", "desc": "모든 워커가 Disconnect되고 핸들러가 닫히면 호출되는 함수", "optional": true } ] }, { "params": [ { "name": "callback", "optional": true } ] } ], "desc": "이 메소드를 호출하면 워커가 전부 정상(graceful) 종료한다. 워커가 종료하면서 내부 핸들러도\n닫힌다. 그래서 마스터 프로세스는 이벤트를 기다리는 것 없이 정상(graceful) 종료될 수 있다.\n\n
\n콜백을 아규먼트로 넘기면 끝날 때 호출된다.\n\n
\n" } ], "classes": [ { "textRaw": "Class: Worker", "type": "class", "name": "Worker", "desc": "워커에 대한 Public 정보와 메소드는 워커 객체에 들어 있다. 마스터에서는\ncluster.workers
로 워커 객체에 접근하고 워커에서는 cluster.worker
로 접근한다.\n\n
모든 워커에는 고유한 id가 부여되고 그 값은 id 프로퍼티에 저장된다.\n\n
\n이 id가 clsuter.workers 프로퍼티에서 해당 워커 객체의 인덱스다.\n워커가 살아 있는 동안에만 사용할 수 있다.\n\n
\n" }, { "textRaw": "`process` {ChildProcess 객체} ", "name": "process", "desc": "워커 프로세스는 child_process.fork()
로 생성하는 데 이 함수가 리턴한 객체가\nprocess 프로퍼티에 저장된다.\n\n
See: Child Process module\n\n
\n" }, { "textRaw": "`suicide` {Boolean} ", "name": "suicide", "desc": ".kill()
를 호출하고 나서 해당 워커가 죽으면 true가 할당되고 .disconnect()
를 호출하면\n즉시 true가 할당된다. 그때까지는 undefined
이다.\n\n
이 함수는 child_process.fork()
로 생기는 send 메소드와 동일하다. 마스터에서 워커에\n메시지를 보낼 때는 이 함수로 보내고 워커에서는 process.send(message)
로 보내지만,\n이 둘은 같은 함수다.\n\n
다음은 마스터가 워커에 보낸 매시지를 다시 그대로 리턴하는 echo 예제다:\n\n
\nif (cluster.isMaster) {\n var worker = cluster.fork();\n worker.send('hi there');\n\n} else if (cluster.isWorker) {\n process.on('message', function(msg) {\n process.send(msg);\n });\n}
\n"
},
{
"textRaw": "worker.kill([signal='SIGTERM'])",
"type": "method",
"name": "kill",
"signatures": [
{
"params": [
{
"textRaw": "`signal` {String} 워커 프로세스에 보내는 kill 신호의 이름. ",
"name": "signal",
"type": "String",
"desc": "워커 프로세스에 보내는 kill 신호의 이름.",
"optional": true,
"default": "'SIGTERM'"
}
]
},
{
"params": [
{
"name": "signal",
"optional": true,
"default": "'SIGTERM'"
}
]
}
],
"desc": "이 함수로 워커를 죽이고 워커를 다시 생성하지 말라고 마스터에게 알릴 수 있다.\nsuicide
프로퍼티를 이용하면 워커가 죽은 게 계획적인지 예외적인지 구분할 수 있다.\n\n
cluster.on('exit', function(worker, code, signal) {\n if (worker.suicide === true) {\n console.log('Oh, it was just suicide\\' – no need to worry').\n }\n});\n\n// 워커를 파괴\nworker.kill();
\n이 메서드는 하위 호환성을 위한 worker.destroy()
라는 별칭이 존재한다.\n\n
이 함수를 호출하면 해당 워커는 더는 연결을 수락하지 않는다(하지만, 다른 워커는 여전히 연결을\n수락한다). 이미 맺어진 연결도 종료할 수 있다. 맺어진 연결이 없으면 IPC 연결이 닫히고 워커가\n정상적으로(graceful) 죽는다. IPC 채널이 닫히면 disconnect
이벤트가 발생하고 이어서\n워커가 죽으면서 exit
이벤트가 발생한다.\n\n
바로 끊기지 않는 연결이 있을 수도 있기 때문에 타임아웃을 사용하는 게 좋다. 먼저 워커를\nDisconnect시키고 2초 후에 서버를 죽인다(destroy). 대신 2초 후에 worker.kill()
\n메소드를 실행할 수도 있지만, 워커가 충분히 소거하지 못할 수 있다.\n\n
if (cluster.isMaster) {\n var worker = cluster.fork();\n var timeout;\n\n worker.on('listening', function(address) {\n worker.disconnect();\n timeout = setTimeout(function() {\n worker.send('force kill');\n }, 2000);\n });\n\n worker.on('disconnect', function() {\n clearTimeout(timeout);\n });\n\n} else if (cluster.isWorker) {\n var net = require('net');\n var server = net.createServer(function(socket) {\n // 연결이 끝나지 않는다.\n });\n\n server.listen(8000);\n\n server.on('close', function() {\n // 마무리\n });\n\n process.on('message', function(msg) {\n if (msg === 'force kill') {\n server.close();\n }\n });\n}
\n",
"signatures": [
{
"params": []
}
]
}
],
"events": [
{
"textRaw": "Event: 'message'",
"type": "event",
"name": "message",
"params": [],
"desc": "이 이벤트는 child_process.fork()
의 것과 같다. 마스터에서 이 이벤트를 사용하고\n워커에서는 process.on('message')
를 사용한다.\n\n
다음은 마스터 프로세스에서 총 요청 수를 세는 예제다. 메시지 시스템을 사용해서 구현한다:\n\n
\nvar cluster = require('cluster');\nvar http = require('http');\n\nif (cluster.isMaster) {\n\n // HTTP 요청 수를 저장한다.\n var numReqs = 0;\n setInterval(function() {\n console.log("numReqs =", numReqs);\n }, 1000);\n\n // 요청을 센다.\n function messageHandler(msg) {\n if (msg.cmd && msg.cmd == 'notifyRequest') {\n numReqs += 1;\n }\n }\n\n // 워커를 생성하고 메시지를 Listen한다.\n var numCPUs = require('os').cpus().length;\n for (var i = 0; i < numCPUs; i++) {\n cluster.fork();\n }\n\n Object.keys(cluster.workers).forEach(function(id) {\n cluster.workers[id].on('message', messageHandler);\n });\n\n} else {\n\n // 워커 프로세스에 HTTP 서버가 있다..\n http.Server(function(req, res) {\n res.writeHead(200);\n res.end("hello world\\n");\n\n // 마스터에 'notifyRequest' 메시지를 보낸다.\n process.send({ cmd: 'notifyRequest' });\n }).listen(8000);\n}
\n"
},
{
"textRaw": "Event: 'online'",
"type": "event",
"name": "online",
"desc": "cluster.on('online')
이벤트와 같지만, 해당 워커의 상태가 변경됐을 때만 발생한다.\n\n
cluster.fork().on('online', function() {\n // Worker is online\n});
\n",
"params": []
},
{
"textRaw": "Event: 'listening'",
"type": "event",
"name": "listening",
"params": [],
"desc": "cluster.on('listening')
이벤트와 같지만, 해당 워커의 상태가 변경됐을 때만 발생한다.\n\n
cluster.fork().on('listening', function(address) {\n // Worker is listening\n});
\n"
},
{
"textRaw": "Event: 'disconnect'",
"type": "event",
"name": "disconnect",
"desc": "cluster.on('disconnect')
이벤트와 같지만, 해당 워커의 상태가 변경됐을 때만 발생한다.\n\n
cluster.fork().on('disconnect', function() {\n // Worker has disconnected\n});
\n",
"params": []
},
{
"textRaw": "Event: 'exit'",
"type": "event",
"name": "exit",
"params": [],
"desc": "워커 프로세스가 종료할 때 발생한다. 자세한 건\nchild_process Event: 'exit'을\n봐라.\n\n
\nvar worker = cluster.fork();\nworker.on('exit', function(code, signal) {\n if( signal ) {\n console.log("worker was killed by signal: "+signal);\n } else if( code !== 0 ) {\n console.log("worker exited with error code: "+code);\n } else {\n console.log("worker success!");\n }\n});
\n"
}
]
}
],
"type": "module",
"displayName": "Cluster"
}
],
"stability": 3,
"stabilityText": "Stable"
}