2장 RestApi, Sequelize

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

에러핸들러가 없다

셋팅

https://beanbroker.github.io/2018/08/29/nodejs/restapi1/ 참고

1) 에러 처리

/service/userread.service.js

1
2
3
4
5
6
7
8
9
const exec = async (id) =>{

const user = await User.findById(id);
//이부분 추가
if (!user) {
throw new Error('NONE_EXISTENCE_USER');
}
return user;
}

유저가 존재하지 않으면 에러 Throw하게 되면 router catch부분에 잡게됨

기본 제공 Error Object는

1
2
3
4
5
interface Error {
name: string;
message: string;
stack?: string;
}

위와같이 생겼다.

router에 수정없이 진행하게 될경우 정확한 메시지를 전달받을 수가 없다.

router수정

/routes/user.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);

//주석 처리 및 messge로 변경
//res.send(err);
res.send(err.message);
}));
});

localhost:3005/users/없는값 을 호출하게되면
NONE_EXISTENCE_USER 값을 받을수 있다.

무언가 허접하지 아니한가!
STATUS CODE와 정확한 에러 Object를 관리하게 만들어보자

2) 에러처리 고도화

예측할수 있는 에러들을 error객체를 상속받아 적용해보자

root에서 components폴더 생성
components 폴더 안에 error폴더 생성

/components/error.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
'use strict'
class InternalError extends Error{

constructor(message) {
super(message);

if (message) {
this.alertMessage = "INTERNAL_ERROR"
}
if (message.data) {
this.data = message.data;
}

this.name = this.constructor.name;
this.status = 500;
}
}


class CommonError extends Error{

constructor(message, code){
super(message, code);

if(message){
this.alertMessage = message;
}

this.code = code;
this.name = this.constructor.name;
this.status = code;
}

}

module.exports ={
InternalError,
CommonError,

}

위처럼 error상속받아서 구현

자바처럼 멤버변수 선언하여 생성자를 셋팅하는 부분이 곧? 나올예정?이란 소문이….

/routes/users.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
//기존 get하던부분 아래오 같이 수정
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(errorHandler(res));

});



//추가
const errorHandler = (res) =>{
return (err) => {
switch (err.name) {
case 'CommonError':
return setResponse(res, err);
default:
return respondDefaultError(res, err);
}
};
}
//추가
const setResponse = (res,err) => {
if(err.code){
res.status(err.code).json(err)
}
res.end(err);
}

router에 setResponse와 errorHandler가 있는 것은 보기 좋지 않지만 일단 넘어가자

/service/userread.service.js

1
2
3
4
5
6
7
8
9
10
11
12
//추가
const {CommonError} = require('../../components/error/error')

//수정
const exec = async (id) =>{

const user = await User.findById(id);
if (!user) {
throw new CommonError('NONE_EXISTENCE_USER', 404);
}
return user;
}

위처럼 셋팅이 끝낫다면!

req

1
localhost:3005/users/3

res

1
2
3
4
5
6
7
8
HTTP_STATUS = 404

{
"alertMessage": "NONE_EXISTENCE_USER",
"code": 404,
"name": "CommonError",
"status": 404
}

흠…. 물론 CommonError로 모든 에러를 던질때 code값을던질수도 있지만 좀더 세분화하게되면 좋다
ex)
NotFoundError
InternalError
등등

error값을 던질때 Http Status code값을 셋팅하는 것처럼! 정상 200대의 code를 줄때! 알맞는 Status code를 찾아보고 보내는 노력을 하자!