01. 기본개념
노드는 크롬의 V8 자바스크립트 엔진 위에서 실행됩니다. 엔진에 필요한 기능을 병렬로 실행하는 '스레드풀'과 이벤트를 받아 처리하는 '이벤트루프'를 기본구조로, 그 위에 네트워킹을 담당하는 소켓, http 라이브러리가 있습니다. 그 위에는 표준 라이브러리가 있으며 자바스크립트를 사용해서 라이브러리를 사용할 수 있습니다.Process 객체
: 프로그램을 실행했을 때 만들어지는 프로세스 정보를 다루고 있는 객체입니다.
- argv: 프로세스를 실행할 때 전달되는 파라미터 정보
- env: 환경 변수 정보
- exit(): 프로세스를 끝내는 메소드
console.log(process.argv.length);
console.dir(process.argv);
//result
[ '/usr/local/bin/node',
'/Users/naver/Desktop/nodejs/ch02_test2.js' ]
node.exe 파일이 첫 번째 파라미터이고 실행된 자바스크립트 파일은 두 번째 파라미터가 됩니다.
노드를 설치하면 미리 정의된 내장모듈 사용이 가능합니다. 그 중에서 os 모듈, path 모듈 등이 있습니다. 파일 패스를 다루는 path 모듈은 아래와 같습니다. (path 문서)
console.log(process.argv.length);
var path = require('path');
var directories = ["users", "mike", "docs"];
var docsDirectory = directories.join(path.sep);
console.log(docsDirectory);
var curPath = path.join('/Users/mike', 'notepad.exe');
console.log(curPath);
주소 문자열과 요청파라미터: url 모듈을 사용하면 일반 주소 문자열을 URL 객체로 만들 수 있으며 일반 문자열로 변환이 쉬어집니다.
- parse(): 주소 문자열을 파싱하여 URL 객체를 만들어 줍니다.
- format(): URL 객체를 주소 문자열로 변환합니다.
var url = require('url');
var curURL = url.parse('https://www.youtube.com/watch?v=Wgs2ahWHjHQ&index=24&list=RDEMN0b_oSABQRVM34ADsmrK2w');
console.log(curURL);
// result
Url {
protocol: 'https:',
slashes: true,
auth: null,
host: 'www.youtube.com',
port: null,
hostname: 'www.youtube.com',
hash: null,
search: '?v=Wgs2ahWHjHQ&index=24&list=RDEMN0b_oSABQRVM34ADsmrK2w',
query: 'v=Wgs2ahWHjHQ&index=24&list=RDEMN0b_oSABQRVM34ADsmrK2w',
pathname: '/watch',
path: '/watch?v=Wgs2ahWHjHQ&index=24&list=RDEMN0b_oSABQRVM34ADsmrK2w',
href: 'https://www.youtube.com/watch?v=Wgs2ahWHjHQ&index=24&list=RDEMN0b_oSABQRVM34ADsmrK2w' }
querystring 모듈을 사용해서 요청 파라미터를 쉽게 분리할 수 있습니다.
- parse(): 요청 파라미터 문자열을 파싱하여 요청 파라미터 객체로 만들어 줍니다.
- stringify(): 요청 파라미터 객체를 문자열로 변환합니다.
간단 모듈 만들어보기
파일 및 디렉터리를 다루는 기능이 있으며, 동기식, 비동기식을 함께 제공합니다. 파일을 비동기식으로 불러오는 방법을 더 많이 사용합니다.
winston 라이브러리를 사용하면 로그 파일을 남길 수 있습니다.
//file1
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var Calc = function() {
var self = this;
this.on('stop',function(){
console.log('event occured!');
});
};
util.inherits(Calc, EventEmitter);
Calc.prototype.add = function(a, b) {
return a + b;
}
module.exports = Calc;
module.exports.title = 'calculator';
//file2
var Calc = require('./file1');
var calc = new Calc();
calc.emit('stop');
파일 다루기파일 및 디렉터리를 다루는 기능이 있으며, 동기식, 비동기식을 함께 제공합니다. 파일을 비동기식으로 불러오는 방법을 더 많이 사용합니다.
//파일 읽기
var fs = require('fs');
fs.readFile('./package.json', 'utf8', function(err, data){
console.log(data)
});
//파일 쓰기
fs.writeFile('./package.json', 'hello world', function(err){
console.log('completed')
});
실제로 파일에 데이터를 기록하기 위해서는 open -> write -> close 단계가 필요합니다.
var fs = require('fs');
fs.open('./output.txt', 'w', function(err, fd){
if(err) throw err;
var buf = new Buffer('hello\n'); // 기본 utf-8 인코딩.
fs.write(fd, buf, 0, buf.length, null, function(err, written, buffer){
if(err) throw err;
console.log(err, written, buffer);
fs.close(fd, function(){
console.log('completed')
})
})
});
데이터는 필요한 만큼 Buffer 객체 안에 기입합니다. 파일이 열리면 파일을 구별하는 fd객체를 전달 받습니다. Buffer 객체는 바이너리 데이터를 읽고 쓰는데 사용됩니다. new로 생성한 다음 안에 들어갈 바이트 데이터의 크기만 지정하면 됩니다. 자바스크립트에서 바이너리 데이터 관리를 위해 Buffer을 사용합니다.winston 라이브러리를 사용하면 로그 파일을 남길 수 있습니다.
02. 웹 서버 만들기
노드에서 웹 서버는 다른 서버 기능을 추가할 수 있습니다. 웹 서버는 일반적으로 웹 브라우저(클라이언트)에서 HTTP 프로토콜로 요청한 정보를 처리한후 응답을 보내주는 역할을 합니다.
var http = require('http');
var server = http.createServer();
var port = 3000;
server.listen(port, function(){
console.log('test')
})
클라이언트가 웹 서버에 요청할 때 발생하는 이벤트 처리가 필요하며 주로, connection, request 이벤트가 자주 사용됩니다. connection은 클라이언트가 접속되었을 때, request는 요청을 발생할 때 생기는 이벤트입니다.
var http = require('http');
var server = http.createServer();
var port = 3000;
server.listen(port, function(){
console.log('works!');
});
server.on('connection', function(socket){
var addr = socket.address();
console.log('cconnection', addr.address, addr.port);
});
server.on('request', function(req, res){
console.log('request');
res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"});
res.write("<!DOCTYPE html>");
res.write("<html>");
res.write("<h1>Hello World!</h1>")
res.write("</html>");
});
request 요청이 오면, writeHead(), write() 메소드로 데이터를 만들어 클라이언트로 보냅니다. 이제부터는 좀 더 편하게 express로 웹 서버를 만들어 보도록 하겠습니다.
var express = require('express');
var http = require('http');
var app = express();
app.set('port', process.env.Port || 3000);
http.createServer(app).listen(app.get('port'), function(){
console.log('start!')
});
express 모듈은 웹서버를 만들기위한 것으로 http 모듈 위에서 작동합니다. 그렇기 때문에 이 두 가지 모듈은 항상 함께 불러들어야 합니다. 여기서 app 객체는 express() 메소드 호출로 만들어지는 익스프레스 서버 객체로서 주요 메소드를 가지고 있습니다.set(서버설정 속성지정), get(설정속성을 가져옴), use(미들웨어사용), get(특정 패스로 요청된 정보 처리)
03. 미들웨어와 라우터
미들웨어와 라우터는 하나의 독립된 함수입니다. 예를들어, 로그를 남기는 간단한 함수를 만든 후 use() 메소드를 사용해 미들웨어로 등록해 사용이 가능합니다. next()를 사용해서 여러개의 미들웨어를 순차적으로 사용할 수 있습니다.라우터는 클라이언트의 요청 패스를 보고 정보를 처리하는 것을 말하며 흔히 라우팅이라고 합니다. use()의 사용법을 보도록 하겠습니다.
var express = require('express');
var http = require('http');
var app = express();
app.use(function(req, res, next){
console.log('first middleware');
});
http.createServer(app).listen(3000, function(){
console.log('start!');
});
미들웨어를 연속적으로 사용하기 위해서는 next()가 필요합니다.
var express = require('express');
var http = require('http');
var app = express();
app.use(function(req, res, next){
console.log('first middleware');
req.user = 'Ryan';
next();
});
app.use('/', function(req, res, next){
console.log('second middleware');
res.end('My name is ' + req.user);
});
http.createServer(app).listen(3000, function(){
console.log('start!');
});
클라이언트로부터 요청을 받으면 미들웨어로 요청이 가고 그 안에 정의된 함수가 실행되고 완료가 되면 다시 클라이언트로 응답이 갑니다. 익스프레스에서 사용하는 응답/요청 객체의 종류는 아래와 같습니다. send(), status(), sendStatus(), redirect(), render(). 다음은 요청 객체에서 사용가능한 헤더와 파라미터를 살펴보도록 하겠습니다.- query: 클라이언트에서 GET 방식으로 전송한 요청 파라미터를 확인 함.
- body: 클라이언트에서 POST 방식으로 전송한 요청 파라미터를 확인 함. 단, body-parser와 같은 외장 모듈을 사용해야함.
- header: 헤더를 확인 함.
04. 미들웨어 사용하기
1. static 미들웨어
특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 함. 예를들어, public 폴더를 웹서버의 루트 패스로 접근할 수 있도록 만들기 위해서는 아래와 같이 설정하면 public 폴더 안에 있는 파일들을 클라이언트에서 바로 접근이 가능합니다.
var static = require('serve-static');
app.use('/public', static(path.join(__dirname, 'public')));
2. body-parser미들웨어 POST 요청시 주소 문자열에 요청 파라미터가 들어오는 것이 아닌, 본문영역(body)에 요청 파라미터가 들어가 있기 때문에 body-parser를 사용하여 파라미터를 파싱하여 body 속성에 넣어줍니다.
app.js
public
|_login.html
app.js 파일을 만들고 public 폴더 안에 login.html 을 생성합니다. body-parser 모듈을 이용하여 파싱을합니다(링크)
var express = require('express');
var http = require('http');
var path = require('path');
var bodyParser = require('body-parser');
var static = require('serve-static');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(static(path.join(__dirname, 'public')));
app.use(function(req, res, next){
var paramId = req.body.id || req.query.id;
var paramPassword = req.body.password || req.query.password;
res.writeHead('200', {'Content-Type' : 'text/html;charset=utf8'});
res.write('<h1>' + paramId + '</h1>');
res.write('<h1>' + paramPassword + '</h1>');
res.end();
});
http.createServer(app).listen(3000, function(){
console.log('start!');
});
05. 요청 라우팅 & 쿠키, 섹션
라우터 미들웨어를 사용하면 사용자가 요청한 기능을 패스로 구별하여합니다. 요청 패스를 라우터 객체에 등록할 때 메소드는 다음과 같습니다.
- get
- post
- put
- delete
- all
var router = express.Router();
router.route('/process/login').get(...);
router.route('/process/login').post(...);
app.use('/', router);
<form method="post" action="/process/login">
클라이언트에서 요청시 URL뒤에 ? 를 추가하면 요청 파라미터를 추가하여 보낼 수 있습니다. 이외에도 URL파라미터 방식도 있습니다. 다른점이 있다면 URL주소의 일부로 들어갑니다.
var router = express.Router();
router.route('/process/login').post(function(req, res){
var paramId = req.body.id || req.query.id;
var paramPassword = req.body.password || req.query.password;
res.writeHead('200', {'Content-Type' : 'text/html;charset=utf8'});
res.write('<h1>' + paramId + '</h1>');
res.write('<h1>' + paramPassword + '</h1>');
res.end();
});
app.use('/', router);
router를 사용할 때 중요한 것이 라우터 객체를 app 객체에 등록해야 사용 가능합니다. URL 파라미터는 아래와 같이 사용할 수 있습니다.
router.route('/process/login/:name').post(function(req, res){
var paramName = req.params.name;
var paramId = req.body.id || req.query.id;
var paramPassword = req.body.password || req.query.password;
res.writeHead('200', {'Content-Type' : 'text/html;charset=utf8'});
res.write('<h1>' + paramName + '</h1>');
res.write('<h1>' + paramId + '</h1>');
res.write('<h1>' + paramPassword + '</h1>');
res.end();
});
페이지오류를 처리하는 미들웨어도 추가할 수 있습니다. express-error-handler 모듈을 설치해줍니다. expressErrorHandelr가 404 오류를 감지하면 미리 등록해놓은 404.html 페이지를 노출시킵니다.
var expressErrorHandler = require('express-error-handler');
var errorHandler = expressErrorHandler({
static: {
'404': './public/404.html'
}
});
app.use(expressErrorHandler.httpError(404));
app.use(errorHandler);
쿠키와 세션을 통해 사용자가 로그인한 상태인지 아닌지 확인이 가능합니다. 쿠키는 클라이언트 웹 브라우저에 저장되는 정보이며, 세션은웹 서버에 저장됩니다. 세션을 만들어 보도록 하겠습니다. 익스프레스에서 세션을 사용하기 위해서는 express-session 모듈을 사용합니다.참고링크
https://github.com/shlee1353/react-contents
Comments
Post a Comment