1. 3장 노드의 기본 모듈
아꿈사
http://cafe.naver.com/architect1
황윤희
yoonheecode@gmail.com
2. 3.1 전역 객체
3.2 유틸리티
3.3 이벤트
3.4 버퍼
3.5 스트림
3.6 파일시스템
3.7 경로
3.8 네트워크
3.9 HTTP와 HTTPS
3.10 URL과 쿼리 문자열
3.11 자식 프로세스
3.12 클러스터
3.13 TCP를 이용한 채팅 예제
3. 3.1 전역 객체
소스 어느 곳에서나 접근할 수 있는 객체
클라이언트 자바스크립트의 최상위 객체: window
node.js의 최상위 객체: global
node의 전역 변수: __filename, __dirname
node의 전역 함수: require(), setTimeout()
node의 전역 객체: console, exports, process, Buffer
4. 3.1 전역 객체 : 전역 변수
__filename : 현재 코드의 파일 경로
__dirname : 현재 코드의 폴더 경로
[사용 예]
console.log(‘filename : ‘, __filename);
console.log(‘dirname : ‘, __dirname);
5. 3.1 전역 객체 : 전역 함수
setTimeout(callback, delay)
delay시간이 지난 다음 callback 실행
(그러나 정확한 실행을 보장하는 것은 아니고... ‘가능한한’ 이라고...)
require()
사용할 모듈을 불러온다.
6. 3.1 전역 객체 : process (1)
프로세스 정보를 담고 있는 전역 객체로
실행시간, 메모리 사용률, 워킹 디렉토리 등의 정보를 알 수 있다.
표준 입력, 표준 출력과 관련된 함수 제공
EventEmitter의 instance
Event: exit - 프로세스가 종료되는 시점에 발생
[사용 예]
process.on('exit', function(){
process.nextTick(function(){
console.log('이건 실행이 안될꺼야.');
});
console.log('Good Bye');
});
7. 3.1 전역 객체 : process (2)
try-catch로 예외 처리 가능
Event: uncaughtException - 예상치 못한 예외 처리
[사용 예]
process.on('uncaughtException', function(err){
console.log('예외: '+err);
});
setTimeout(function(){
console.log('이 코드는 실행됩니다.');
}, 2000);
// 존재하지 않는 함수 실행
nonExistentFunction();
console.log('이 코드는 실행되지 않습니다.');
8. 3.1 전역 객체 : process (3)
process.nextTick(callback)
CPU 연산이 많이 필요한 작업을 비동기로 실행할 수 있게 함
callback을 이벤트 큐에 등록
싱글 스레드가 현재 작업 완료 후 다음 이벤트 처리시 실행
setTimeout() 보다 효율적
[사용 예]
function onNextTick(){
console.log('nextTick으로 호출되었다.');
}
process.nextTick(onNextTick);
console.log('이 메세지가 먼저 출력된다.');
9. 3.1 전역 객체 : Buffer (1)
자바스크립트는 유니코드에 적합 but 바이너리 데이터는 잘 다루지 못함.
TCP 스트림이나 파일 스트림을 사용하려면 Octet Stream을 다룰수 있어야.
옥텟 : 8비트로 이루어진 단위
Buffer 클래스 : 바이너리 데이터를 다루기 위한 것.
옥텟 스트림을 다루는 함수를 제공.
raw 데이터는 Buffer 클래스의 객체에 저장.
Buffer는 정수의 배열. (각 정수는 V8 힙 메모리 밖 로우 메모리에 할당된 주소를 가리킴.)
자바스크립트 문자열과 버퍼 사이에 변환을 하려면 인코딩을 지정해야.
ascii 7비트 ASCII 데이터
utf8 멀티바이트로 인코딩된 유니코드
ucs2 2바이트 little endian으로 인코딩된 유니코드
base64 Base64 문자열 인코딩
hex 각 바이트를 2개의 16진수로 인코딩
10. 3.1 전역 객체 : Buffer (2)
버퍼 생성 : new Buffer, 생성시 반드시 인코딩 방법 지정.
buffer.write(string, offset=0, length=buffer.length-offset, encoding=‘utf8’)
버퍼의 오프셋 위치에 string 작성.
buffer.toString(encoding, start=0, end=buffer.length)
start부터 end까지의 버퍼를 문자열로 변환.
buffer[index]
index 위치의 옥텟을 가져오거나 설정. 범위 0~255
buffer.isBuffer() : 객체가 버퍼 타입인지 검사.
buffer.length : 버퍼 객체의 메모리의 크기. 버퍼에 저장된 내용의 길이와 다름.
buffer.copy : 버퍼 복사
buffer.slice() : 버퍼 잘라냄.
11. 3.2 유틸리티 : util
유틸리티성 함수가 포함된 유틸리티 기본 모듈
require(‘util’) 로 불러온다
util.format() : 문자열을 포매팅한다.
%s : string
%d : number (integer, float)
%j : JSON
%% : % 출력
12. 3.3 이벤트 : Events (1)
노드는 이벤트 루프 기반. 많은 객체가 이벤트 발생시킴
require(‘event’) 로 불러온다
이벤트 발생 : emit
실행되는 함수 : listener
객체에 이벤트 추가
emitter.addListener(eventName, listener)
emitter.on(eventName, listener)
server.on(‘connection’, function(stream) {
console.log(‘서버에 연결됐습니다’);
});
13. 3.3 이벤트 : Events (2)
한 번만 실행해야 하는 리스너
emitter.once(eventName, listener)
지정한 이벤트에서 전달한 리스너 제거
emitter.removeListener(eventName, listener)
연결된 모든 리스너 제거
emitter.removeAllListener([eventName])
등록된 리스터가 10개 이상이면 경고 메시지 출력
리스너 개수 제한 늘리기
emitter.setMaxListeners(n)
등록된 리스너 배열
emitter.listeners(event)
강제로 이벤트를 발생시킴
emitter.emit(eventName, [arg1], [arg2]...)
15. 3.5 스트림 : stream - Readable Stream (1)
스트림을 다루는 모드 객체의 추상 인터페이스.
Readable Stream과 Writable Stream이 있다.
Readable Stream
Event: data
새로운 데이터가 들어왔을 때 발생.
기본적으로 Buffer 사용. setEncoding() 사용되면 문자열 사용.
Event: end
EOF나 FIN을 받았을 때 발생.
Event: error
데이터를 받는 동안 에러가 있을때 발생.
Event: close
사용하는 파일 디스크립터가 닫혔을 때 발생.
16. 3.5 스트림 : stream - Readable Stream (2)
stream.readable
스트림이 읽을 수 있는 상태인지.
stream.setEncoding()
data 이벤트가 Buffer 대신 문자열을 사용하게 한다.
utf8, ascii, base64 사용 가능.
stream.pause()
들어오는 data 이벤트를 멈춘다.
stream.resume()
pause()로 멈춘 data 이벤트를 재개.
stream.destroy()
사용하는 파일 디스크립터를 닫는다.
stream.destroySoon()
큐에 있는 내용을 모두 소비한 다음에 파일 디스크립터를 닫는다.
stream.pipe()
읽어 들인 내용을 지정된 쓰기 스트림에 연결.
17. 3.5 스트림 : stream - Writable Stream (1)
Writable Stream
Event: drain
write() 가 false를 돌려준 후 스트림이 다시 쓸 수 있는 상태가 되었음을 알림.
Event: error
스트림에 에러가 생기면 발생.
Event: close
사용하는 파일 디스크립터가 닫히면 발생.
Event: pipe
Readable Stream의 pipe() 로 스트림이 전달됐을 때 발생
18. 3.5 스트림 : stream - Writable Stream (2)
stream.writable
스트림이 쓰기 가능한 상태인지.
stream.write(string, encoding=‘utf8’)
string 문자열을 encoding 해 스트림에 쓴다.
버퍼를 쓰려면 stream.write(buffer)
stream.end()
EOF나 FIN으로 스트림을 종료.
종료전에 큐에 있는 데이터를 모두 내보냄.
stream.destroy()
사용중인 파일 디스크립터를 닫는다.
stream.destroySoon()
큐에 있는 데이터를 모두 소비한 후 파일 디스크립터를 닫는다.
19. 3.6 파일시스템 : fs
require(‘fs’) 로 불러온다.
대부분 함수는 동기 함수 제공. 접미사 Sync가 붙어있음.
fs.rename() : 파일명을 바꾼다.
fs.stat() : 파일의 정보를 확인한다.
fs.writeFile() : 파일의 내용을 작성한다.
fs.readFile() : 파일의 내용을 읽는다.
fs.watchFile() : 파일의 변경사항을 감시한다.
fs.unlink() : 파일을 삭제한다.
fs.rmdir() : 디렉토리를 삭제한다.
fs.realpath() : 파일의 절대경로를 가져온다.
......
20. 3.7 경로 : path
경로에 관련된 모듈. require(‘path’) 로 불러온다.
path.normalize() : 전달받은 문자열을 수정해서 올바른 경로로 수정.
path.join() : 전달받은 경로를 이어 붙인다.
path.resolve() : 전달받은 경로의 절대 경로를 돌려준다.
path.relative(from,to) : from에서 to까지의 상대경로를 출력한다.
path.dirname() : 전달받은 경로의 디렉토리 명을 돌려준다.
path.basename() : 전달받은 경로의 마지막 부분을 돌려준다.
path.extname() : 전달받은 파일병의 확장자를 돌려준다.
path.exists() : 파일의 존재 여부를 확인한다.
21. 3.8 네트워크 : net
비동기 네트워크를 다루는 클래스. require(‘net’)으로 불러온다.
var net = require('net');
function onListen(){
console.log('서버가 %d포트로 연결됐습니다.', server.address().port);
}
function onConnectClose(){
console.log('연결이 종료됐습니다.');
}
function onConnectResult(socket){
console.log('서버에 연결되었습니다.');
socket.on('end', onConnectClose);
socket.write('Hellorn');
}
var server = net.createServer(onConnectResult);
server.listen(8124, onListen);
22. 3.8 네트워크 : net.Server (1)
생성된 TCP 서버는 net.Server 클래스의 객체이며,
새로운 연결을 받기 위한 net.Socket의 객체
server.listen()
특정 호스트와 포트로부터 연결을 받기 시작.
port로 전달한 포트에 서버가 바인딩되면 listening 이벤트 발생
server.address()
호스트와 포트에 대한 정보
server.pause()
파라미터의 밀리초만큼 서버가 새로운 요청을 받지 않는다.
server.close()
서버가 더 이상 새로운 요청을 받지 않는다.
close 이벤트 발생
server.maxConnections
서버가 최대로 받아들일 수 있는 연결수 지정
server.connections
현재 서버의 동시 연결 수
23. 3.8 네트워크 : net.Server (2)
Event: listening
server.listen()이 호출돼고 서버가 바운딩 되면 발생.
Event: connection
새로운 연결이 생기면 발생.
콜백함수의 파라미터 socket은 연결된 소켓, net.Socket의 객체.
Event: close
서버가 닫혔을 때 발생.
Event: error
서버에 에러가 생겼을 때 발생.
error 이벤트가 발생한 뒤에는 close 이벤트가 발생한다.
24. 3.8 네트워크 : net.Socket (1)
서버에서 connection 이벤트가 발생하면 콜백함수로 소켓 전달.
socket.setEncoding()
소켓으로 받는 데이터의 인코딩 지정 (ascii, utf-8, base64)
socket.write()
소켓에 데이터를 보낸다.
socket.end()
소켓을 종료한다.
socket.pause()
소켓에서 데이터 읽는 것을 멈춤. data 이벤트 발생을 막음.
socket.resume()
다시 데이터를 받을 때 실행.
socket.remoteAddress
접속한 클라이언트의 원격 IP를 돌려줌.
socket.bufferSize
현재 버퍼에 있는 캐릭터의 크기. 인코딩되기 전의 문자 크기.
25. 3.8 네트워크 : net.Socket (2)
Event: connect
소켓 연결이 이뤄졌을 때 발생.
Event: data
소켓에서 데이터를 받았을 때 발생.
Event: end
소켓으로 FIN 패킷을 받았을 때 발생.
Event: drain
쓰기 버퍼가 비워졌을 때 발생.
Event: error
에러가 생겼을 때 발생.
에러 발생 뒤 이어서 close 이벤트가 발생.
Event: close
소켓이 완전히 닫혔을 때 발생.
26. 3.9 HTTP와 HTTPS : http.Server
HTTP : require(‘http’)
HTTPS : require(‘https’)
TLS/SSL 모듈에 기반, HTTP 모듈과 사용법이 거의 동일
http.createServer() : HTTP 서버 생성
http.Server 의 이벤트
Event: request
요청이 들어올 때마다 발생.
콜백함수의 파라미터 request는 http.ServerRequest의 객체.
콜백함수의 파라미터 response는 http.ServerResponse의 객체.
Event: connection
새로운 TCP 스트림이 생성되면 발생하는 이벤트.
콜백함수의 파라미터 socket은 net.Socket의 객체.
Event: close
서버가 닫힐 때 발생.
27. 3.9 HTTP와 HTTPS : http.ServerRequest
HTTP 요청의 객체.
Event: data
메시지 바디의 일부를 받으면 발생.
Event: end
요청이 종료될 때 요청당 딱 한번만 발생.
end 이벤트 후에는 더 이상 data 이벤트가 발생하지 않는다.
request.method : HTTP 메소드를 돌려줌. (GET/POST)
request.url : 요청의 URL
request.headers : 헤더 정보
request.httpVersion : HTTP 요청의 버전
request.setEncoding() : 요청바디의 인코딩 설정.
utf8이나 binary 사용. null 이면 Buffer객체 사용
request.pause()/request.resume() : 요청에서 이벤트 발생을 멈추거나 재개.
29. 3.10 URL과 쿼리 문자열 : URL
require(‘url’)로 불러온다.
url.parse()
받은 URL 문자열을 호스트명, 쿼리 문자열, 경로 등으로 파싱한 객체로 돌려준다.
url.format()
URL 객체를 다시 URL 문자열로 만든다.
30. 3.10 URL과 쿼리 문자열 : querystring
URL에서 ? 뒤에 붙는 값. require(‘querystring’)으로 불러온다.
querystring.stringify()
JSON 객체의 키와 값을 이용해 쿼리 문자열로 만든다.
querystring.parse()
쿼리 문자열을 다시 JSON 객체로 변환한다.
31. 3.11 자식 프로세스 : child_process (1)
require(‘child_process’).spawn() 이나
require(‘child_process’).fork() 로 자식 프로세스 생성.
require(‘child_process’).spawn(command, args, option)
command를 사용하는 자식 프로세스 생성.
option {cwd:undefined, env:process.env, setsid:false}
cwd - 생성된 프로세스가 실행되는 디렉토리 지정
env - 새 프로세스가 접근할 수 있는 환경 변수 지정
setsid - true이면 서브프로세스를 새로운 세션으로 생성
생성된 자식 프로세스는 세 가지 스트림 사용.
child.stdin, child.stdout, child.stderr
32. 3.11 자식 프로세스 : child_process (2)
child_process.exec(command, option, callback)
command를 실행하고 결과를 돌려준다.
child_process.execFile()
파일을 실행
child.Kill()
자식 프로세스 종료
33. 3.12 클러스터 : cluster (1)
싱글 스레드여서 CPU 계산양이 많은 부분에서 취약한 부분을 해결.
다중 프로세스의 로드밸런싱을 통합해 클러스터 모듈로 제공.
require(‘cluster’) 로 불러온다.
마스터 프로세스만 호출할 수 있고, CPU 개수만큼 워커 프로세스 생성
cluster.fork()
34. 3.12 클러스터 : cluster (2)
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster)
{
// CPU 개수만큼 워커 생성 ... 마스터 프로세스만 부를수 있다.
for (var i=0; i<numCPUs; i++) {
cluster.fork();
}
// 프로세스가 종료할 때, death 이벤트 발생할때 프로세스 아이디 출력하도록 함.
cluster.on('death', function(worker) {
console.log('worker '+worker.pid+' died');
});
} else {
// 워커프로세스는 HTTP 서버를 생성한다.
http.Server(function(req,res) {
res.writeHead(200);
res.end("hello worldn");
}).listen(8000);
}
35. 3.12 클러스터 : cluster (3)
워커 프로세스에서 마스터 프로세스로 메시지를 전달. 전체 요청수를 기록하는 예
var cluster = require('cluster');
var http = require('http');
var numReqs = 0;
if (cluster.isMaster) {
// 마스터 프로세스는 워커 생성
for (var i=0; i<2; i++) {
var worker = cluster.fork();
// message 이벤트 리스너에 notifyRequest 전달되면 요청수 증가
worker.on('message', function(msg) {
if (msg.cmd && msg.cmd == 'notifyRequest') {
numReqs++;
}
});
}
......
36. 3.12 클러스터 : cluster (4)
......
// 1000ms 간격으로 요청수를 찍어준다.
setInterval(function() {
console.log("numReqs =", numReqs);
}, 1000);
} else {
// 워커 프로세스는 HTTP 서버를 생성한다.
http.Server(function(req, res) {
res.writeHead(200);
res.end("hello world ..... messagen");
// 마스터 프로세스로 메시지를 보낸다.
process.send({ cmd: 'notyfyRequest'});
}).listen(8000);
}