1장 RestApi, Sequelize

Sequelize3장에서 끝낸 아래문제를 해결 및

1
2
3
1. 서비스로직이 필요하다!
2. 에러핸들러가 없다
3. 통일된 res object가 없다

Sequelize orm과! 좀더restful하게 api를 만들어보자!

서비스로직이 필요하다!

셋팅

  1. 루트폴더에 service폴더 생성
  2. service폴더 및에 user폴더 생성(도메인 폴더 생성)
  3. 기존에 쓰던 app.js, /routes/user.js수정

app.js

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');

var app = express();


const sequelize = require('./models').sequelize;

const bodyParser = require('body-parser');


sequelize
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});


sequelize.sync();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

app.use(bodyParser.json());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));


app.use('/', indexRouter);
app.use('/users', usersRouter);


// catch 404 and forward to error handler
app.use(function(req, res, next) {

res.status(err.status || 404);
res.send('404 not found');


});

// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};

// render the error page
res.status(err.status || 500);
res.render('error');
});

app.listen(3005, function(){
console.log('3005 port connected');
});

module.exports = app;

/routes/user.js

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
'use strict'
const express = require('express');
const router = express.Router();


const userCreateService = require('../service/user/usercreate.service');
const useReadService = require('../service/user/userread.service');
const userUpdateService = require('../service/user/userupdate.service');
const userDeleteService = require('../service/user/userdelete.service');
const userListService = require('../service/user/userlist.service');


/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('User Api');
});


router.get('/list', (req,res,next)=> {
userListService.exec()
.then((users) => {
console.log(users);
console.log('finish to findAll');
res.json(users);
})
.catch((err => {
console.error(err);
res.send(err);
}));
});

router.get('/:id', function(req, res, next) {
useReadService.exec(req.params.id)
.then((user) => {
console.log(user);
console.log('finish to findById');
res.json(user);
})
.catch((err => {
console.error(err);
res.send(err);
}));
});




router.post('/', (req,res,next) => {

userCreateService.exec(req.body)
.then((result) => {
console.log(result);
console.log('finish to create');
res.status(201).json(result);
})
.catch((err => {
console.error(err);
res.send(err);
}));

});


router.put('/:id', (req,res,next) => {
userUpdateService.exec(req.body, req.params.id)
.then((result) => {
console.log(result);
console.log('finish to update');
res.json(result);
})
.catch((err => {
console.error(err);
res.send(err);
}));

});


router.delete('/:id', function(req, res, next) {
userDeleteService.exec(req.params.id)
.then((result) => {
res.json(result);
})
.catch((err) => {
console.error(err);
next(err);
});
});



module.exports = router;

Rest CRUD

Service

‘비지니스 로직을 담당’

UserService처럼 하나만 만들어도 되지만 전부 쪼개서 만들자! 실제 하나의 서비스에 다양한 많은 로직을 담게 될경우 변경할경우 힘든경우가..있다.. 파일이 많이 만들어지더라도… 이렇게 해보자…

(‘use strict’을 항상 모든 js파일 맨위에 붙이자! 습관습관)

CreateService -> /service/user/usercreate.service.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
'use strict'
const User = require('../../models').User;
const exec = async (body) =>{

const user = await User.create({
name : body.name,
age : body.age,
gender : body.gender,

});
return user;
}


module.exports = {

exec,

}

ReadService -> /service/user/userread.service.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
'use strict'
const User = require('../../models').User;
const exec = async (id) =>{

const user = await User.findById(id);
return user;
}


module.exports = {

exec,

}

UpdateServce -> /service/user/userupdate.service.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
'use strict'
const User = require('../../models').User;
const exec = async (body, id) =>{

const user = await User.update(
{
name : body.name,
age : body.age,
gender : body.gender,
}, {
where : {id : id}
})

return user;
}


module.exports = {

exec,

}

DeleteService -> /service/user/userdelete.service.js

1
2
3
4
5
6
7
8
9
10
11
12
const User = require('../../models').User;
const exec = async (id) =>{

const result = await User.destroy({ where: { id: id } })
return result;
}

module.exports = {

exec,

}

ListService -> /service/user/userlist.service.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
'use strict'
const User = require('../../models').User;
const exec = async () =>{

const userList = await User.findAll();
return userList
}


module.exports = {

exec,

}

위와같이 CRUD서비스를 만들어보았다. 포스트맨을 활용하여 테스트를 진행할경우 정상적으로 작동함을 확인할수 있다!

간단 소스 설명

노드로 서버를 개발을 하게될경우! 무조건 무조건 비동기로 만들어한다.. 동기로 짜도 돌아가는 것처럼 보이지만 절대 그렇게 하지말라 공식문서에도 나와있다…

라우터

  1. router를 controller라 생각!하여
  2. localhost:3005/users/list로 request가 들어오면
  3. 유저리스트 서비스(비지니스로직을 담당) 데이터를 받아와서
  4. 해당데이터를 json으로 말아서 보낸다!
1
2
3
4
5
6
7
8
9
10
11
12
router.get('/list', (req,res,next)=> {
userListService.exec()
.then((users) => {
console.log(users);
console.log('finish to findAll');
res.json(users);
})
.catch((err => {
console.error(err);
res.send(err);
}));
});

서비스

  1. User모델 필요
  2. body가 param으로 넘어왔고
  3. 해당 파람맵핑하여 user생성
  4. 기다리다 생성되면 리턴
    디비접근부분은.. async await으로 쓰는 것을 선호한다…
1
2
3
4
5
6
7
8
9
10
11
const User = require('../../models').User;
const exec = async (body) =>{

const user = await User.create({
name : body.name,
age : body.age,
gender : body.gender,

});
return user;
}

코드를 짜는 모든사람들의 취향존중을 해주어야한다! 하지만 왜 그렇게 하는지는 확고히 가지고 있어야 된다 생각한다.

async, await에서는 try catch가 가능하다(퍼포먼스가 좋은지는 모름…. 사실 안써봄…)! 물론 이를 이용하여 router를 구현할수 있으나! router에 promise를 적용함을 통해 얻는 부분이 존재한다.

  • then -> 서비스로직에서 결과가 나오면!!!!!!
  • catch -> 서비스로직에서 에러를 던지면 받는 곳!!이라 생각

궁금점이 생기는 부분

이렇게 코드를 짜놓고 보니 서비스로직의 공통된 부분이 있자. 객체지향언어인 자바 또는 C#으로 개발을 진행해본사람은!

1
const User = require('../../models').User;

상위 Object에 추상화를 꿈꿀것이다! 하지만 여기선 그럴필요가 없다!
찾아보니 이유인 즉슨 require로 한번 호출된 이후로 캐싱이 자동적으로 되어서 알아서 잘 처리가 된다고 한다.. (정확한 작동원리는 모름)