Introduction

간만에, Node.js로 서버를 구성하는데, 뭔가 이상하던군요. 예제 코드를 차근 차근 따라해 보는 와중에, 말도 안되는 오류가 났습니다.

Error: Most middleware (like logger) is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.

아니, 이게 무슨 소리인지 번뜩 이해가 안갔습니다. 더 이상 middleware를 지원하지 않는다니, 야속함이 느껴졌습니다.

Express 4.0

보름 전인 4월 9일에, Express 4.0이 나왔습니다. 4.0이 나오면서, 기존의 거대한 Express가 쪼개진 것 입니다. 정확히는, 중립적인 Express가 되었다고 표현하는게 맞을 것 같습니다. middleware라고 불리는 녀석들을 모두 놓아주고, 개발자가 필요한 module들을 설치하여 사용하도록 변경되었습니다. 이런 차이 점을 정리해 보도록 하겠습니다.

App.Configure() 제거

실은, 이번에 간단한 서버를 작성하면 가장 황당한 부분이었습니다. 늘, Configure를 통해서 Express를 셋팅하다가, 갑자기 이 녀석이 사라져 버렸기 때문입니다. 이전의 Configure를 통해서, middleware를 등록하던 방식은 불가능합니다. 이런 경우라면, if문을 사용하라고 하네요.

// configure를 통한 셋팅은 사용할 수 없습니다.
app.configure( function() {
    app.set('views', config.rootPath + '/server/views');
    app.set('view engine', 'jade');

    // middleware 등록도 불가
    app.use(express.logger('dev'));
    app.use(express.cookieParser());
    ...
});

예를 들면, 다음과 같습니다.

if (config.mode == 'development') {
    app.set('views', config.devPath + '/server/views');
    ...
} else if (config.mode == 'production') {
    app.set('views', config.rootPath + '/server/views');
    ...
}

위와 같이 구성하시면, 크게 무리 없을실거라 생각됩니다.

middleware 분리

middleware라는 것은, 기존에 express와 함께 제공되면, bodyParser, cookieParser, session 등과 같은 편의적인 library입니다. 이전에는 app.configure와 함께 다음과 같이 사용했습니다.

// express 3.x 스타일
app.configure( function() {
    app.set('views', config.rootPath + '/server/views');
    app.set('view engine', 'jade');
    app.use(express.logger('dev'));
    app.use(express.cookieParser());
    app.use(express.bodyParser());
    app.use(express.session({secret:'I DO I DO'}));
});

그러나, 이제는 달라졌습니다. 번들로 제공되던, middleware가 없으므로 모두 require시켜야 합니다.

var express = require('express'),
    morgan = require('morgan'),
    cookieParser = require('cookie-parser'),
    session = require('express-session'),
    bodyParser = require('body-parser');

var app = express();

if ( 'development' == config.mode ) {
   app.use(morgan('dev'));
   app.use(bodyParser());
   app.use(cookieParser());
   app.use(session({secret: 'multi vision unicorns'}));
}

눈치 빠른 분들은 짐작하셨겠지만, npm으로 위의 middleware를 관리해 주셔야 합니다. 그래서, 저의 package.json의 경우는 다음과 같습니다.

{
  ...
  "dependencies": {
    "body-parser": "^1.0.2",
    "cookie-parser": "^1.0.1",
    "express": "^4.0.0",
    "express-session": "^1.0.3",
    "jade": "^1.3.1",
    "method-override": "^1.0.0",
    "mongoose": "^3.8.8",
    "morgan": "^1.0.0",
    "stylus": "^0.43.1"
  }
}

보시다 싶이, 필요한 middleware들이 모두 추가되었습니다. 이는 ExpressJS 4.0: New Features and Upgrading from 3.0에 잘 정리되어 있었습니다. 발췌를 좀 하자면...

Express 3.0 Name Express 4.0 Name
bodyParser body-parser
compress compression
cookieSession cookie-session
logger morgan
cookieParser cookie-parser
session express-session
favicon static-favicon
response-time response-time
error-handler errorhandler
method-override method-override
timeout connect-timeout
vhost vhost
csrf csurf

과 같으니 참고 하시기 바랍니다.

Router 객체 추가

이전의 router는 express의 인스턴스인 app에 직접적으로 할당하여 진행되는 구조였습니다. 예를 들면 다음과 같습니다.

app.get('/api/users', auth.requiresRole('admin'), function(req, res) {
    User.find({}).exec(function(err, collection) {
        res.send(collection);
    })
});

app.get('/partials/*', function (req, res) {
    res.render('../../public/app/' + req.params);
});

위와 같은 형태로 구성하였는데요, 이제는 Router 객체를 통해서 셋팅하도록 변경되었습니다. 다음 코드와 같이, 먼저 router객체를 생성하여 등록한 다음, 최종적으로 app 객체에 바인딩하는 형태입니다.

var router = express.Router(); // router 객체를 생성합니다.

router.use(function(req, res, next) {
    // do logging - 모든 request에 대해 수행됩니다.
    next();
});

router.route('/jobs')
    .post(jobController.create)
    .get(jobController.getList); // post, get에 대해 등록하였습니다.

router.route('/jobs/:name')
    .get(jobController.get)
    .put(jobController.update)
    .delete(jobController.delete);

app.use('/', router);

개인적으로는 훨씬 깔끔하게 router 코드를 작성하게 된 것이 아닌가 합니다. 별도의 파일로 작성하는 것은 예전부터 해 왔으나, 금번의 업데이트로 가독성이 더욱 좋아진 느낌입니다.

Conclusion

그 외에도, 변경된 점들이 있으니 History 참고 하시면 되겠습니다. 간략하게 express 4.0에 대해서 정리해 보았습니다. 저처럼 당황하지 마시길, 바랍니다.

Reference