안녕세계

[SK고용디딤돌]Node.js (1/10) - 5주차 본문

[SK고용디딤돌]Node.js (1/10) - 5주차

Junhong Kim 2016. 8. 4. 18:05
728x90
반응형

[ 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/

728x90
반응형
Comments