요약
Controller
-Service
-Dao
각 레이어 별로 서로 다른 목적으로 에러 핸들링을 적용한다.- 에러가 발생하는 위치와 실제 에러 메세지를 던지는 위치가 실제와 상이할 수 있다.
- 각 레이어별 에러 핸들링 시
동기, 비동기적 에러 처리
에 유의하여 코드를 작성합니다.
KEY_ERROR
클라이언트 Request로 보낸 정보 가운데 누락된 key가 있을 때 발생하는 에러.
case 1. request body라는 객체 안에 email 이라는 특정 키가 없는 경우
console.log(req.body) // { password : 'myPassword' }
const { email, password } = req.body
console.log(email) // undefined
console.log(password) // 'myPassword'
if (!email) {
throw new Error('KEY_ERROR')
} // 에러 발생 시점
case 2.
// 키에러가 발생하지 않으나, 값이 빈 상태
console.log(req.body) // { email: '', password: 'myPassword' }
const { email, password } = req.body
console.log(email) // ''
console.log(password) // 'myPassword''
if (!email) {
const err = new Error('KEY_ERROR')
err.statusCode = 400;
throw err
} // 에러 발생하지 않음.
참고
case 1. 회원가입 시 email, password 등 필수 필요 정보가 누락되었을 때
case 3. 주문 생성 시 주문 제품의 필수 정보 product_id, quantity, user_id 등이 누락되었을 때
👉 case 1.은 key는 있지만 해당하는 키에 빈 값이 들어오는 case 3.과는 다르다!controller는 key가 아예 들어오지 않아서, 요청 자체에 문제가 있는 상황을 처리한다
👉 사용자에게 출력을 보낼 때 (http response)에도 에러가 발생할 수 있다.
👉 입출력 외에도 컨트롤러가 하는 일을 따로 정해두었다면, 해당 작업중 발생 가능한 에러를 사전에 핸들링 해두는 것이 좋다.
👉 사용자 입력이 잘못되었다면, 주로 400번대 http status code를 보낸다.
비즈니스 로직과 규칙을 설정하는 곳
기획, 비즈니스 규칙에 따라 개발자가 직접 의도한 예외
와 관련된 에러가 발생한다.
에러의 발생 위치
Service 단 하위에 위치한 계층의 모듈
직접 이곳에서 호출하는 서비스 모듈
만일 비즈니스 규칙에 위반되는 사항이 발생 가능하다면 꼭 이곳에서 필히 해당 문제의 경우에 상응한 Status Code와 함께 에러를 발생시켜야 한다.
사용자의 요청의 문제가 아니라 내부 처리 과정 중 문제라면 500번대 Status Code를 보내는 것이 일반적입니다.
case 1. 회원 가입시 올바른 형태의 비밀번호를 적었는지 유효성 처리
//service/userService.js
const userDao = require('../models/userDao')
// 정규 표현식을 이용한 비밀번호 유효성 검증
const signUp = async (name, email, password, profileImage) => {
const pwValidation = new RegExp(
'^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,20})'
);
if (!pwValidation.test(password)) {
const err = new Error('PASSWORD_IS_NOT_VALID');
err.statusCode = 409;
throw err;
}
const createUser = await userDao.createUser(
name,
email,
password,
profileImage
);
return createUser;
};
module.exports = {
signUp
}
영속적인 저장소와 관련된 코드를 작성하는 곳.
데이터베이스 드라이버가 위치하는 곳이므로 DB에 의존적인 에러가 발생할 수 있다.
아울러 Node + Express와는 다른 외부 시스템으로서 연동되어 있고, 이 때 주로 비동기 호출을 하기 때문에, 비동기 에러 핸들링
에 적합한 방법을 이용해야 합니다.
const { DataSource } = require('typeorm');
const myDataSource = new DataSource({
type: process.env.TYPEORM_CONNECTION,
host: process.env.TYPEORM_HOST,
port: process.env.TYPEORM_PORT,
username: process.env.TYPEORM_USERNAME,
password: process.env.TYPEORM_PASSWORD,
database: process.env.TYPEORM_DATABASE
})
myDataSource.initialize()
.then(() => {
console.log("Data Source has been initialized!");
})
.catch((err) => {
console.error("Error during Data Source initialization", err);
myDatasource.destroy()
});
const createUser = async ( name, email, password, profileImage ) => {
try {
return await myDataSource.query(
`INSERT INTO users(
name,
email,
profile_image,
password
) VALUES (?, ?, ?, ?);
`,
[ name, email, password, profileImage ]
);
}
catch (err) {
const err = new Error('INVALID_DATA_INPUT');
err.statusCode = 500;
throw err;
}
};
module.exports = {
createUser
}