세네카와 익스프레스 연동

세네카는 웹 프레임워크가 아니기에 Express와 같은 웹 프레임워크와 연동을 해야 한다.

필요한 모듈을 설치해보자

npm install --save express
npm install --save seneca-web
npm install --save seneca-web-adapter-express

익스프레스와 세네카를 연동시키기 위해서는 seneca-web 모듈뿐만 아니라 adapter가 필요하다. seneca-web-adapter-express 모듈 역시 설치하고 세네카에 적용시켜주도록 하자.

var SenecaWeb = require('seneca-web');
var Express = require('express');
var Router = Express.Router;
var context = new Router();
 
var senecaWebConfig = {
      context: context,
      adapter: require('seneca-web-adapter-express'),
      options: { parseBody: false } // so we can use body-parser
};
 
var app = Express()
      .use( require('body-parser').json() )
      .use( context )
      .listen({port:3000});
 
var seneca = require('seneca')()
      .use(SenecaWeb, senecaWebConfig )
      // api 모듈
      .use('api')
      .client( { type:'tcp', pin:'role:math' } );

세네카와 익스프레스의 연동을 위한 부분은 아래와 같다.

.use(SenecaWeb, senecaWebConfig)
//This code means
//seneca.act('role:web', {routes:routes})

api 테스트

테스트를 위해 간단한 api를 작성해보도록 하자.

//api.js
 
module.exports = function api(options) {
  var valid_ops = { sum:'sum', product:'product' };
 
  this.add('role:math, cmd:product', function(msg, respond) {
    var product = msg.left * msg.right;
    respond(null, { answer: product});
  });
 
  this.add('role:math, cmd:sum', function(msg, respond) {
    var sum = parseInt(msg.left) + parseInt(msg.right);
    respond(null, {answer: sum});
  });
 
  this.add('role:api, path:calculate', function (msg, respond) {
    var operation = msg.args.params.operation;
    console.log(operation);
 
    var left = msg.args.query.left;
    var right = msg.args.query.right;
 
    this.act('role:math', {
      cmd:   valid_ops[operation],
      left:  left,
      right: right,
    }, respond);
  });
 
  this.add('init:api', function (msg, respond) {
    this.act('role:web',{routes:{
      prefix: '/api',
      pin:    'role:api,path:*',
      map: {
        //GET, POST 모두 호출 가능하게 함.
        calculate: { GET:true, POST: true, suffix:'/:operation' }
      }
    }}, respond);
  });
};

위의 role:web 패턴은 routes의 속성을 정의하고 있습니다.

  • prefix : URL

  • pin : map으로 전달될 패턴 집합

  • map : pin에서 * 로 매칭된 집합 리스트이며 URL의 엔드포인터로서의 값

init은 그냥 패턴일 줄 알았는데 세네카의 속성값이었다. url호출시 init:api 부분을 호출한다.

this.add('init:api')

POST로 요청해보자

GET과 같은 원리로 POST를 추가해보았는데 라우터 설정은 잘 되어있는 거 같은데 계속 body를 읽을 수 없다고 한다. 그래서 express처럼 bodyParser추가하는 방식으로 해보았더니 잘 되었다.

//app.js
 
...
var bodyParser = require('body-parser');
...
 
var app = Express();
 
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
 
app.use( context );
app.listen(3000);
 
...

this.add(init:api)의 map 부분에 user라는 path를 추가하였다.

//api.js
 
...
 
this.add('init:api', function (msg, respond) {
  this.act('role:web',{routes:{
    prefix: '/api',
    pin:    'role:api,path:*',
    map: {
      calculate: { GET:true, suffix:'/:operation' },
      user: { POST:true }
    }
  }}, respond);
});

seneca에 해당 패턴을 추가한다.

//api.js
 
this.add('display:userPw', function(msg, respond) {
  respond(null, {userPw: msg.userPw});
});
 
this.add('role:api, path:user', function (msg, respond) {
  console.log(msg);
  this.act('display:userPw', {
    userPw: msg.args.body.userPw
  }, respond);
});

테스트를 위해 포스트맨으로 x-www-form-urlencoded 방식으로 호출하였더니 다음과 같이 출력이 됨을 확인할 수 있다.

{
  "userPw": 1234
}

마치며

post로 데이터 전송을 하는데 계속 데이터 출력이 안되서 엄청 삽질을 하였다. 결국 익스프레스 사용할 때처럼 bodyParser를 적용하였다. 그래도 seneca 설정부분에서 options: { parseBody: false } 은 해줘야하는 것 같다. 이 부분을 제거해보니 전송이 안됨을 확인하였다.

'Framework > Nodejs' 카테고리의 다른 글

express-session  (0) 2018.01.03
pm2에 대해 알아보자  (0) 2017.10.06
[마이크로서비스] Seneca  (0) 2017.10.02
비동기와 CPU Bound  (0) 2017.09.04
node js, mongodb 연동 with mongoose  (0) 2017.08.16

+ Recent posts