일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- nodejs express
- C/C++
- 베트남어
- flex3
- Node.js
- Eclipse
- 디즈니씨
- ejb
- 명사 뽑아내기
- 책이야기
- rss
- php
- express for node.js
- scala
- ror실행
- node.js web framework
- 명사 추출기
- 메일왕창보내는법
- 나의 프로젝트
- iBatis
- php thumbnail
- ajax
- 스킨 스쿠버
- Lift
- Cross
- 명사 분석기
- 도커
- 주식이야기
- docker
- 나의 취미
- Today
- Total
nkdk의 세상
node.js express node.js 웹 프레임워크? 파헤치기 본문
안녕하세요. express 웹 기본 프레임 워크 설명에 들어갑니다. 일단..
저번에 올린 자료를 참고 하셔서 설치를 완료 하셨으면..
설명에 들어갑니다.
app.js 를 보시면..
var app = require('express').createServer();
app.get('/', function(req, res){
res.send('hello world');
});
app.listen(3000);
이런 부분이 있는데요. 이 부분은 서버를 만든 부분입니다.
https 로 만드는 것도 가능한데요.
http://nodejs.org/docs/v0.3.7/api/https.html#https.createServer 여길 참조 해 보세요.
그 다음은 설정 부분입니다.
app.configure(function(){
app.use(express.methodOverride());
app.use(express.bodyParser());
app.use(app.router);
});
app.configure('development', function(){
app.use(express.static(__dirname + '/public'));
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
var oneYear = 31557600000;
app.use(express.static(__dirname + '/public', { maxAge: oneYear }));
app.use(express.errorHandler());
});
보시면 아시겠지만 개발자 환경, 운영환경 이렇게 2개로 나눠서 설정하는 것이 가능합니다.
app.configure('stage', 'prod', function(){
// config
});
비슷한 환경에서 여러 환경을 문자열로 전달 할 수 있습니다.
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('views');
// => "/absolute/path/to/views"
app.enable('some feature');
// same as app.set('some feature', true);
app.disable('some feature');
// same as app.set('some feature', false);
app.enabled('some feature')
// => false
});
이런식으로 enable 및 disable 도 가능합니다.
개발 환경 및 운영 환경을 띄울 때 다음과 같이 구분해서 띄울 수 있습니다.
> NODE_ENV=production node app.js // 운영 환경을 띄울 경우
개발 환경이냐 아니면 운영 환경 이건 엄청 중요합니다. 왜냐하면 캐싱메커니즘이라던지 여러가지에 영향을 끼치거든요.
Express 에서 지원하는 셋팅
basepath = 응용 프로그램의 기본 경로 res.redirect() 를 사용합니다.
views = 기본적으로 CWD/views 부분에 디렉토리입니다.
view engine = 확장자 없는 렌더링 되는 뷰 엔진을 어떤걸 쓸 것이냐.
view options = object 형 특별한 뷰옵션입니다.
view cache = 프로덕션에서 이네이블 되는 view caching 입니다.
case sensitive routes = case-sensitive 루팅을 이네이블 합니다.
strict routing = 활성화가 되면 더 이상 슬래쉬를 무시하지 않습니다.
jsonp callback Enable = res.send() / res.json()가 jsonp 의 전송을 지원합니다.
경로(라우팅)에 대한 설명
설정 안에서 라우팅에 대한 규칙을 정의할 수 있습니다.
예를들면 http://localhost:3000/user/500 http://localhost:3000/user/40 이런 것들에 url을 받으려면
app.get('/user/:id', function(req, res){
res.send('user ' + req.params.id);
});
이런 소스를 app.js 에 추가 시키시고 실행하시면 인식이 됩니다.
그리고 RegEXP를 이용하시면 정규표현으로 선언하는 것이 가능합니다.
\/user\/([^\/]+)\/? 와 같이 추가를 한다던지 , 아래와 같이 추가도 가능합니다.
app.get(/^\/users?(?:\/(\d+)(?:\.\.(\d+))?)?/, function(req, res){
res.send(req.params);
});
위에 내용을 넣으면 다음과 같이 테스트가 가능합니다.
> curl http://dev:3000/user
[null,null]
> $ curl http://dev:3000/users
[null,null]
> $ curl http://dev:3000/users/1
["1",null]
> $ curl http://dev:3000/users/1..15
["1","15"]
아래와 같이 라우팅 추가가 가능합니다.
라우팅 인식이 가능한 형식
------------------------------------------
"/user/:id"
/user/12
"/users/:id?"
/users/5
/users
"/files/*"
/files/jquery.js
/files/javascripts/jquery.js
"/file/*.*"
/files/jquery.js
/files/javascripts/jquery.js
"/user/:id/:operation?"
/user/1
/user/1/edit
"/products.:format"
/products.json
/products.xml
"/products.:format?"
/products.json
/products.xml
/products
"/user/:id.:format?"
/user/12
/user/12.json
------------------------------------------
json 이라던지 값을 받을 때 받는 방법에 대해서 설명해 보겠습니다.
bodyParser 라는 것을 중간에서 사용해서 req.body 로 뽑아 내는데요 다음과 같이 사용합니다.
var express = require('express')
, app = express.createServer();
app.use(express.bodyParser());
app.post('/', function(req, res){
res.send(req.body);
});
app.listen(3000);
app.js 에 다 지우고 이 내용을 넣어 주시면 다음과 같이 나옵니다.
> curl http://localhost:3000/ancd=good
위와 같이 쳐 보세요.
아 그리고 라우팅 규칙에서 다음과 같은 것도 가능합니다.
‘/user/:id([0-9]+)’
이 규칙은 유저 아이디가 숫자로만 가능하다고 선언해 주는 것입니다.
경로(라우팅) 규칙을 전달하는 규칙
매칭이 되는 경우와 매칭이 되지 않는 경우를 판별하는 것인데요. 다음과 같이 가능합니다.
app.get('/users/:id?', function(req, res, next){
var id = req.params.id;
if (id) {
// do something
} else {
next();
}
});
app.get('/users', function(req, res){
// do something else
});
즉 req.params.id 가 있는 경우에는 뭔가를 실행하고요. 없는 경우에는 다음으로 넘어가는 next() 를 실행합니다.
app.all 이라는 것도 존재 하는데요. 다음과 같이 사용합니다.
var express = require('express')
, app = express.createServer();
var users = [{ name: 'nkdk' }];
app.all('/user/:id/:op?', function(req, res, next){
req.user = users[req.params.id];
if (req.user) {
next();
} else {
next(new Error('cannot find user ' + req.params.id));
}
});
app.get('/user/:id', function(req, res){
res.send('viewing ' + req.user.name);
});
app.get('/user/:id/edit', function(req, res){
res.send('editing ' + req.user.name);
});
app.put('/user/:id', function(req, res){
res.send('updating ' + req.user.name);
});
app.get('*', function(req, res){
res.send('what???', 404);
});
app.listen(3000);
다음과 같이 넣고..
> curl http://localhost:3000/user
> curl http://localhost:3000/user/0
> curl http://localhost:3000/user/0/edit
하시면 각각 결과가 다릅니다.
미들웨어
접속했을 당시에 미들웨어(미들 처리?)를 선언하는 것이 가능합니다. 선언은 간단합니다.
var express = require('express');
var app = express.createServer(
express.logger()
, express.bodyParser()
);
app.use(express.logger({ format: ':method :url' }));
이렇게 넣어 놓으면 node node.js 실행하실때 url 로그를 남깁니다. 접속시에..
x.xx.xx.x - - [Thu, 05 Apr 2012 07:04:18 GMT] "GET /user/0 HTTP/1.1" 200 12 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.10xx.142 Safari/535.19"
이런식으로 로그를 남기네요.
표준적으로는
var connect = require('connect');
app.use(connect.logger());
app.use(connect.bodyParser());
이렇게도 가능한데요.
app.use 와 같이.. 중간에 미들웨어를 넣는 것도 가능합니다.
종류는 다음과 같습니다.
app.use(express.logger(...));
app.use(express.bodyParser(...));
app.use(express.cookieParser(...));
app.use(express.session(...));
app.use(app.router);
app.use(express.static(...));
app.use(express.errorHandler(...));
사용법은 아래와 같습니다.
var downloads = {};
app.use(app.router);
app.use(express.static(__dirname + '/public'));
app.get('/*', function(req, res, next){
var file = req.params[0];
downloads[file] = downloads[file] || 0;
downloads[file]++;
next();
});
정말 좋네요.
경로 관련 미들웨어
경로를 결정할 때에도 여러가지 미들웨어가 필요하다 생각된다. 그 방법은 간단하게 해결 가능합니다.
(잘못된 예)
app.get('/user/:id', function(req, res, next){
loadUser(req.params.id, function(err, user){
if (err) return next(err);
res.send('Viewing user ' + user.name);
});
});
위에 소스에서 loadUser 라는 부분이 보이네요.
그런데 아무래도 너무 복잡하지 않나요? 안될거 같아요. 저런 코드로는..
(잘 된 코드 예)
function loadUser(req, res, next) {
// You would fetch your user from the db
var user = users[req.params.id];
if (user) {
req.user = user;
next();
} else {
next(new Error('Failed to load user ' + req.params.id));
}
}
app.get('/user/:id', loadUser, function(req, res){
res.send('Viewing user ' + req.user.name);
});
다음과 같이 사용하면 loadUser에 req, res, next 도 모두 넘겨 주게 됨으로 인해 코드의 가독성이 올라갑니다.
DRY 규칙을 성공적으로 완수하는 거죠 :)
비슷한 예로 접속 가능할지 안할지에 대한 것도 아래와 같이 가능하고요.
function andRestrictToSelf(req, res, next) {
req.authenticatedUser.id == req.user.id
? next()
: next(new Error('Unauthorized'));
}
app.get('/user/:id/edit', loadUser, andRestrictToSelf, function(req, res){
res.send('Editing user ' + req.user.name);
});
아래와 같이 인수를 넘기는 것도 가능합니다.
function andRestrictTo(role) {
return function(req, res, next) {
req.authenticatedUser.role == role
? next()
: next(new Error('Unauthorized'));
}
}
app.del('/user/:id', loadUser, andRestrictTo('admin'), function(req, res){
res.send('Deleted user ' + req.user.name);
});
공통적으로 다음과 같이 사용할 수 있습니다.
var a = [middleware1, middleware2]
, b = [middleware3, middleware4]
, all = [a, b];
app.get('/foo', a, function(){});
app.get('/bar', a, function(){});
app.get('/', a, middleware3, middleware4, function(){});
app.get('/', a, b, function(){});
app.get('/', all, function(){});
자세한 내용은 샘플이 준비되어 있으니,
https://github.com/visionmedia/express/blob/master/examples/route-middleware/app.js
여기를 참조 하세요.
HTTP Methods
app.get() 이라던지 app.post(), app.del(), 등을 가지고 있는데요. POST를 사용할 때의 일반적인 예제를 보겠습니다.
일단 저의 경우는 /public 이라는 폴더에 post.html 이라는 걸 만들었습니다.
<form method="post" action="/">
<input type="hidden" name="_method" value="put" />
<input type="text" name="user[name]" />
<input type="text" name="user[email]" />
<input type="submit" value="Submit" />
</form>
app.js 에는
app.put('/', function(){
console.log(req.body.user);
res.redirect('back');
});
다음과 같이 하면 됩니다. 이렇게 하면 콘솔에 name, email 이 나오게 됩니다.
{ name: 'asd', email: '222' }
에러 핸들링
// Error Handling
function NotFound(msg){
this.name = 'NotFound';
Error.call(this, msg);
Error.captureStackTrace(this, arguments.callee);
}
NotFound.prototype.__proto__ = Error.prototype;
app.get('/404', function(req, res){
throw new NotFound;
});
app.get('/500', function(req, res){
throw new Error('keyboard cat!');
});
app.error(function(err, req, res, next){
if (err instanceof NotFound) {
res.render('404.jade');
} else {
next(err);
}
});
app.error(function(err, req, res){
res.render('500.jade', {
error: err
});
});
app.use(express.errorHandler({ showStack: true, dumpExceptions: true }));
app.set('view engine', 'jade');
그리고 get 설정은
app.get('/', function(req, res){
res.render('index.jade', { title: 'My Site' });
});
app.set('view engine', 'jade');
res.render('index'); 이렇게 써도 됩니다. jade 를 빼도 되죠.
그런데 물론
res.render('another-page.ejs');
이것도 가능합니다.
app.set('view options', {
layout: false
});
이렇게 하면 레이아웃 설정이 false 가 됩니다.
/views/layout.jade 에 사용을 안하게 되는거죠.
그런데 레이아웃 이름을 layout.jade 에서 바꾸고 싶은 경우가 있으시죠?
그 경우는
res.render('page', { layout: 'mylayout.jade' });
이런식으로 mylayout 으로 이름을 바꿔줄 수 있습니다.
res.render('page', { layout: __dirname + '/../../mylayout.jade' });
이런식으로 패스를 바꿀수도 있고요.
ejs 방식에서 좋은 예제가 하나 있습니다. 열고 닫기 태그인데요.
app.set('view options', {
open: '{{',
close: '}}'
});
이렇게 설정이 가능합니다.
뷰의 부분만 나오게 하기(view Partials)
뷰에서 작은 부분만을 표시 할 때 사용합니다.
partial('comment', { collection: comments }); 라던지
object 를 넣는 것도 가능합니다.
partial('comment', comments);
다음과 같은 것들을 지원합니다.
firstInCollection: true 이면 첫번째 오브젝트
indexInCollection: 콜렉션의 몇번째인가
lastInCollection: 마지막 컬렉션
collectionLength: 컬력션의 크기
var RedisStore = require('connect-redis')(express);
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat", store: new RedisStore }));
이렇게 하시면.. 일단 세션에 저장은 되겠습니다.
간단히 쇼핑카트를 구현한다고 했을 때
var RedisStore = require('connect-redis')(express);
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat", store: new RedisStore }));
app.post('/add-to-cart', function(req, res){
// Perhaps we posted several items with a form
// (use the bodyParser() middleware for this)
var items = req.body.items;
req.session.items = items;
res.redirect('back');
});
app.get('/add-to-cart', function(req, res){
// When redirected back to GET /add-to-cart
// we could check req.session.items && req.session.items.length
// to print out a message
if (req.session.items && req.session.items.length) {
req.flash('info', 'You have %s items in your cart', req.session.items.length);
}
res.render('shopping-cart');
});
이런 처리가 가능하겠네요.
req.param(name[, default])