안녕세계
[SK고용디딤돌]Node.js (1/10) - 5주차 본문
[SK고용디딤돌]Node.js (1/10) - 5주차
Junhong Kim 2016. 8. 4. 18:05[ Node.js 과정을 진행하면서 우리가 만들 서비스는? 전자상거래 서비스 ]
* 인증(Authentication)
- FB, Twitter, Google을 이용한 인증 서비스가 있다.
- 즉, OAuth 인증 서비스 (보안성↑, 편의성↑)
장바구니 → 주문 → 결제 (↔ PG : payment gateway와 계약을 체결해야 함) → | 배송 (↔ 물류사와 체결)
[ Node.js ]
1) 자바스크립트 기반
2) 이벤트기반
3) 비동기식
- 동기
A 실행 - A 결과 - B 실행 - B 결과
실행이 끝나고 다음 실행
- 비동기
A 실행 - B 실행 - (B 결과) - (A 결과)
실행결과가 끝날때까지 기다리지 않는다
[ Node.js에서의 error 처리]
fs.readFile('textfile.txt', 'utf-8', function(err, text) {
console.log('Read file Async', text)';;
}
// 콜백은 에러가 발생하면 발생한 에러객체를 첫번째 인자로,
// 성공하면 해당 내용을 2번째 매개변수로 지정함으로써 에러의 처리를 수행한다
[ Node.js의 특징 ]
- event loop thread(libev)가 하나이고 (빠르고, 자원이 적게들어 감)
- thread pool(libeio)에는 여러개의 스레드가 있다.
- 입출력이 작은 것에 아주 최적화 되어있음
- 스트리밍으로는 이용할 수 없다. 병목이 발생할 수 있음
- 이벤트 루프를 기반으로 비동기 I/O
- 이벤트 루프를 담당하는것이 1개 쓰레드는 멀티 쓰레드
- non-blocking I/O : 읽고 쓰는 행위를 할 때 기다리지 않음
- 모바일 서비스에 node.js가 대세
- 기존 게임서버에는 C/C++ 네트워크 서버로 TCP/IP 했지만, 빠르게 생산 & 자원이 적게드는 모바일 게임 서버에는 node.js가 대세
(1) Servelet/JSP 구조
(2) Node.js 구조
* Apache vs Nginx
- 아파치는 멀티 쓰레드 즉, 동기 프로그램을 위한 것
- Nginx는 단일 이벤트 쓰레드 덕분에 자원이 Apache에 비해 약 3배 적게 듬
[ Webstorm에서 Node.js 셋팅 ]
[ 서버돌리기 위한 설정(1) ]
[ 서버돌리기 위한 설정(2) ]
-> createServer는 server 객체를 return 해준다
var http = require('http');
http.createServer(function(request, resposne) {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<h1>Hello World!</h1>');
}).listen(52273, function() {
console.log('Server running at http://127.0.0.1:52273/');
});
resposne.end에 내용을 기술하면 response.write 기능도 같이 수행함
// -- 서버 생성(1)
var http = require('http'); // [1]
var httpServer = http.createServer(); // [2]
httpServer.on("request", function(request, response) { // [3]
response.writeHead(200, {'Content-Type' : 'text/html'}); // 응답의 헤드 [5]
response.end('Hello Node.js!!!') // 응답의 바디
});
httpServer.listen(8888, function () { // [4]
console.log("Server listening... at 8888")
});
//-- 서버 생성(2)
var httpServer = http.createServer(function(request, response) {
response.writeHead(200, {'Content-Type' : 'text/html'}); // 응답의 헤드
response.end('Hello Node.js!!!') // 응답의 바디
}).listen(8888, function () { // 소켓의 포트 바인딩
console.log("Server listening... at 8888")
});
[ Python - 다운]
[ 컴파일러 - 다운]
VS2013 Commnuity
[ 모듈설치 ]
(1) -g 옵션(global) : npm install async -g → C:\Users\Tacademy\AppData\Roaming\npm\node_modules\async 에 설치
(2) npm install async → 현재 디렉토리에 설치
[ 모듈 ]
node_modules 아래 module이 설치 되어있어야 모듈경로 없이 이름으로 가져다가 쓸 수 있다.
[ 전역객체 ]
- 전역객체는 global이다
- 별도의 모듈 없이 로딩없이 사용
- glboal.console.log()
ㄴ global 생략 가능 → console.log()
[ (예제1) process.argv ]
function sum(start, vargs) {
var result = 0;
for(var i = arguments[0]; i < arguments[1].length; i++) // arguments[0] = start, arguments[1] = vargs
result += parseInt(arguments[1][i]); // arguments[1][i] = 1, 2, 3, 4, 5 ...
return result;
}
console.log(sum(2, process.argv));
[ (예제2) 명렴 프롬포트에서 포트 지정해서 구동 ]
var http = require('http');
var port = parseInt(process.argv[2] || '8888');
http.createServer(function(request, response) {
response.writeHead(200, {'Content-Type' : 'text/html'}); // 응답의 헤드
response.end('Hello Node.js!!!') // 응답의 바디
}).listen(port, function () { // 소켓의 포트 바인딩
console.log("Server listening... at ", port)
});
<포맷>
var str = util.format('%d + %d = %d', 1, 2, (1+2)가능)
<상속>
util.inherits(constructor, superConstructor)
<이벤트> : defautl 이벤트 최대 10개, setEventL
emitter.addListener(event, listener) // 이벤트 발생할 때마다 처리
emitter.on(event., listener) // 이벤트 발생할 때마다 처리
emitter.once(event.listener) // 한 번만 동작하는 리스너 등록
emitter.removeListener(event, listener) // 해당 이벤트에 등록된 개별 리스너 제거
emitter.removeAllListeners([event]) // 해당 이벤트에 등록된 모든 리스너 제거
emitter.setMaxListeners(n) // 기본적으로 10개 이벤트 등록가능, 최대 이벤트 수정 가능
emitter.getMaxListeners()
eventemitter.defaultMaxListeners
<exit 이벤트>
process.on('exit', function(){ console.log("end...")}); // exit 이벤트 : exit 이벤트는 동기적인 방식을 해야함, 프로세스가 종료할 때 실행
[ 예제(3) 비동기 코드와 동기 코드의 순서 ]
function a(x, y, callback) {
callback(x + y, x - y);
}
a(3, 2, function(arg1, arg2) {
setTimeout(function() { // 비동기 코드
console.log(arg1);
console.log(arg2);
}, 0);
});
console.log("start..."); // 비동기 코드는 동기 코드 보다 늦게 실행 된다. I/O가 발생하는 CASE는 더욱 그렇다.
// 비동기 코드에서 선/후 제어 하면 안된다. 무의미. 제어하면 성능을 낮춘다.
// 병렬처리 단위 시간당 처리량 증가
process.nextTick(function() { //마지막에 실행하도록 제어
});
[ 예제(4) 커스텀 이벤트 ]
emit 함수 호출 결과 : true, false
emitter.emit(event[, arg1][, arg2][, ...])
// 이벤트 처리하려면 EventEmitter를 상속 받아야 한다.
// process 객체는 이미 EventEmitter가 있다. 약속 되어있는 Event가 존재한다.
// 우리는 process 객체에 대해서 약속되어 있는 event만 등록하면 됨
var util = require('util');
var EventEmitter = require('events').EventEmitter;; // EventEmitter 있는 곳
function Car() {}
util.inherits(Car, EventEmitter);
Car.prototype.accelerate = function() {
this.emit('gogogo', '1', '2'); // emitter.emit(eventName[, arg1][, arg2][, ...])
};
var myCar = new Car();
myCar.on('gogogo', function(arg1, arg2) {
console.log(arg1, arg2);
});
myCar.accelerate();
내가 제외하겠다고 설계하지 못한것을 잡기위해
- 예외처리 되지 않는 상황 : uncaughtException
<버퍼>
- Buffer : 바이너리 데이터 다루는 모듈
- 글로벌이므로 별도의 로딩(require) 불필요
* 버퍼 얻기
(2)파일에서 읽기
var fileBuffer = fs.readFileSync('image.jpg');
(3)네트워크에서 읽기
socket.on('data', function(data) {
// data-buffer
});
* 버퍼 만들기
- 생성후 크기 변경 발가
new Buffer(size)
new Buffer(array)
new Buffer(str[, encoding]) // defulat UTF-8
- 버퍼에 문자열 쓰기
buf.write(string[, offset][, length][, encoding])
- 변환
buf.toString([encdoing][, start][, end]) // defulat 기본 UTF-8
- 붙이기(모듈 함수)
Buffer.concat(;ist[, totalLength])
- 자르기
buf.slice([strat[, end]])
- 길이
buffer.length
<스트림>
데이터의 전송 흐름
- 콘솔 입력/출력
- 파일 읽기/쓰기 // socket
- 서버/클라이언트 // 데이터 전송
<스트림 종류> // 바이너리 처리하는 것을 기준 , 모든 스트림은 EventEmitter를 상속
1. Readable Stream
fs.createReadStream(파일)
(1)이벤트
- readable : 읽기 가능한 상태
- data : 읽을 수 있는 데이터 도착(중요★)
- end : 더 이상 읽을 데이터가 없는 상태 // 다 읽으면 end event 발생
- close : 스트림이 닫힌 상태 // 스트림 다쓰고 나면 close 해줘야 함
- error : 에러
(2) Readable 메소드
읽기, 인코딩
- readable.read([size])
- readable.setEncdoing(encoding) // 스트림에다가 encoding 정보 지정
중지, 재개
- readable.pause() // 읽을게 없을 때
- readable.resume() // 읽을게 있을 때
파이프
// readable.pause() / readable.resume()을 자동화 해줌
readable.pipe(destination[, options])
readable.unpipe([destination])
2. Writable Stream
fs.createWriteStream(파일) // 파일 업로드는 스트림을 직접 다루지 않음, 스트림은 파일을 클라이언트가 요청할 때
http 클라이언트의 요청
http 서버의 응답
파일 쓰기 스트림
tcp 소켓 ( 소케슨 둘다 가지고있음)
(1)이벤트
- drain : 출력 스트림에 남은 데이터를 모두 보낸 이벤트, 스트림 다시 쓸 수 있는 상태(중요★)
error : 에러
close : 닫힘 이벤트
finish : 모든 데이터를 쓴 이벤트
writable : 쓰기 가능
pipe : 읽기 스트림과 연결된 이벤트
unpipe : 연결 해제 이벤트
end fin이라는 signal을 교환하면서 연결스트림 종료
(2)메소드
데이터 쓰기, 인코딩
writable.setDefaultEncoding(encdoing)
writable.write(chunk[, encoding][,callback])
스트림 닫기
버퍼
협의OS : (3/4대 기능) 커널 프로세스, 메모리, 디바이스 매니저먼트, (+파일시스템 매니저먼트 (ex) RealTime OS ->Rader를 구동시키는 OS)
커널에는 send buffer와 receive buffer가 있다.
kernel 이 꽉찼는데 또 하면 false가 발생하고, 그렇다면 우리는 버퍼가 빌때까지 pause() 한다. drain 이벤트가 발생하면 다시 resume().
근데 이 기능을 pipe가 이 기능을 다 해 준다. RealTime OS가 적용될 분야, 미래 자동차
<path 모듈>
var path = require('path'); // 경로를 다루는 작업을 하기 위해
var fs = require('fs'); // 파일시스템 관련 작업을 하기 위해
//var npath = path.normalize('c:/foo/bar/../baz/asdf/quux/..');
// 경로에 대한 정규화 작업
// (/foo/bar//baz/asdf/quux/..'); -- \foo\bar\baz\asdf
// ('c:/foo/bar//baz/asdf/quux/..'); -- c:\foo\bar\baz\asdf
// ('c:/foo/bar/../baz/asdf/quux/..'); -- c:\foo\baz\asdf
var npath = path.join('c:/images', 'user00', '2016', 'img_1111.jpg');
// ('images', 'user00', '2016') -- images\user00\2016
// ('c:/images', 'user00', '2016') -- c:\images\user00\2016
// ('c:/images', 'user00', '2016', 'img_1111.jpg') -- c:\images\user00\2016\img_1111.jpg
// var os = fs.createWriteStream(npath);
// os.write();
// console.log(path.dirname(npath)); // -- c:\images\user00\2016 (디렉토리만)
// console.log(path.basename(npath)); // -- img_1111.jpg (확장자 포함 파일 이름)
// console.log(path.extname(npath)); // .jpg (확자자 제외)
// console.log(path.basename(npath, path.extname(npath))); // img_1111 (확장자 제외 파일 이름)
// console.log(path.parse(npath)); // 자바스크립트 객체를 리턴해줌
var pathObj = path.parse(npath);
console.log(pathObj.dir);
<동기/ 비동기식 API>
비동기는 읽은결과가 callback으로 넘어감
<파일 다루기>
open() => fd (보통 정수로 되어있음)
fopen() => FILE *
표준 입력 stdin : 0
표준 출력 stdout : 1
표준 에러 stderr : 2
1)FileDescription로 파일 다루기
- 보통 FD 다룰 일이 없다. 그러나 라이브러리를 만들겠다하면 FD 제어해서 만들어야 함
2) 파일 경로로 파일 다루기
- 파일 경로로 파일을 다루는 것은 FILE *가 유사하다.
<파일 상태 : 존재 확인>
- fs.stat(Sync)를 사용
이것보다 한단계 더 향상 된것은 createReadStream & createWriteStream
fs.stat(npath, function(err,stats) {
if(err) {
// npath에 해당하는 파일 없을 때, 404 처리
} else {
if (stats.isDirectory()) {
// 403 처리
} else {
// 200 처리
}
}
});
<querystring 모듈>
queryString 구분자 ?
key=value 쌍으로 구성 됨. -> 전달되는 매개 변수임 -> 서버에서 해당하는 값 가져오고 &으로 구분
key=value&key= -> 값이 없으면 undefined 임
[쿼리 스트링 처리할 때 가장많이 사용하는 모듈 qs]
https://www.npmjs.com/package/qs
[과제 MIME이 무엇인가 조사]
인터넷에 통신하는 모든 데이터들은 MIMB정보 없이는 통신할 수 없다. 하나의 약속이라고 생각하자.
MIMB정보는 Content-Tpye이라는 키의 값을 들어간다. 이것도 약속
MIMB정보가 있어야 브라우저가 읽는 방법을 알려준다.
ex) 내려오는 정보가 JavaScript인 경우 이것이 JavaScript라는 메타정보를 알려주어야한다.
이렇게 알려주어야해당언어에 맞는 엔진이 동작한다.
통신할때 필요한 socket은 파일이다
[ 링크 ]
https://nodejs.org/en/
https://www.npmjs.com/
http://mvnrepository.com/
https://www.python.org/
https://www.visualstudio.com/
'My Trace > SK고용디딤돌2기' 카테고리의 다른 글
[SK고용디딤돌] Node.js (3/10) - 6주차 (0) | 2016.08.08 |
---|---|
[SK고용디딤돌] Node.js (2/10) - 5주차 (0) | 2016.08.05 |
[SK고용디딤돌] MySQL (보충) - 5주차 (0) | 2016.08.03 |
[SK고용디딤돌] MySQL (TEST) - 5주차 (0) | 2016.08.02 |
[SK고용디딤돌] MySQL (7/7) - 4주차 (0) | 2016.07.27 |