Express middleware는 Java 진영의 Springframework의 interceptor, aop 와 비슷한 성향을 가지고 있습니다.



위 그림을 참고 해보자.


서버로 요청이 들어오면 middleware 는 route / 모든 주소에 대해서 처리하라는 지시를 받습니다. 그 후 특정 url 에 대해서 처리를 한 후 응답을 하게 됩니다.


실제로 log를 확인해 봤습니다.


app object 중 stack

  stack: 
   [ { route: '', handle: [Function: query] },
     { route: '', handle: [Function: expressInit] },
     { route: '', handle: [Function: logger] },
     { route: '', handle: [Function: cookieParser] },
     { route: '', handle: [Function: bodyParser] },
     { route: '', handle: [Function: methodOverride] },
     { route: '', handle: [Function: test] },
     { route: '', handle: [Function: session] },
     { route: '', handle: [Function] },
     { route: '', handle: [Function] },
     { route: '', handle: [Function: router] },
     { route: '', handle: [Function: errorHandler] } ]


app object 중 router

_router: 
   { map: 
      { get: 
         [ { path: '/test/test',
             method: 'get',
             callbacks: [ [Function] ],
             keys: [],
             regexp: /^\/test\/test\/?$/i },
            ....
         ],
         post: 
         [ { path: '/test/test',
             method: 'get',
             callbacks: [ [Function] ],
             keys: [],
             regexp: /^\/test\/test\/?$/i },
            ....
         ]
      }
   }


서버로 request가 들어오는 이벤트가 발생할 경우 stack 을 통과하게 됩니다. 

개발자가 직접 정의 하는 middleware 는 test 라는 함수이고, 모든 url 처리는 stack 를 통과하고 특정 url은 router 에게 처리를 위임 하게 됩니다. 실제 code를 보도록 하자.


./express/lib/application.js 중 일부 입니다.

/** * Proxy `connect#use()` to apply settings to * mounted applications. * * @param {String|Function|Server} route * @param {Function|Server} fn * @return {app} for chaining * @api public */ app.use = function(route, fn){ var app; // default route to '/' if ('string' != typeof route) fn = route, route = '/'; // express app if (fn.handle && fn.set) app = fn; // restore .app property on req and res if (app) { app.route = route; fn = function(req, res, next) { var orig = req.app; app.handle(req, res, function(err){ req.app = res.app = orig; req.__proto__ = orig.request; res.__proto__ = orig.response; next(err); }); }; } connect.proto.use.call(this, route, fn); // mounted an app if (app) { app.parent = this; app.emit('mount', this); } return this; };

"default route to '/'" 내부적으로 기본 값으로 설정이 되는 것을 확인 할 수 있습니다. 


이제 실제 사용법을 알아보도록 하자.



http://expressjs.com/api.html#app.use 공식 홈페이지 Reference 자료 입니다.

두번째 인자로 function 이 사용 됩니다.


위 자료를 참고 하여 Sample Code 작성 해보자.

함수형으로 return 하자.

function test() {
  return function test(req, res, next) {
    console.log('test');   

    next();
  }
}

next() 는 stack 의 다음 주소로 가라는 함수 입니다. 실제로 next() 를 호출 하지 않는 경우 응답을 하지 못하고 서버에서 멈춰버리게 됩니다.


app.js 설정의 일부 입니다. 실제로 적용 하자.

function setting() {
  app.configure(function(){
    app.set('port', process.env.PORT);
    app.use(express.logger('dev'));
    app.use(express.cookieParser());
    app.use(express.bodyParser());
    app.use(express.methodOverride());

    // user middleware
    app.use(test());
    
    // session config
    app.use(express.session({
      secret: config.redis.secret,
      store: new RedisStore(config.options),
      cookie: config.cookie
    }));

    app.use(passport.initialize());
    app.use(passport.session());

    // router
    app.use(app.router);
  });  
}

use 함수 호출 하는 부분을 볼 수 있는데, 해당 행위는 모든 요청에 대해서 처리를 하겠다는 말입니다. 

위와 같이 적용 하면 모든 요청에 대해서 test 함수가 호출 되는 것을 확인 할 수 있습니다.


※ 참고 사이트: http://expressjs.com/


+ Recent posts