본문 바로가기
BackEnd

각 Layer 별 Error Handling에 대해

by SoriKim 2023. 11. 23.
반응형

1. Controller Error

컨트롤러는 표현 계층, 즉 입력과 출력에 관련한 부분을 담당합니다. 

HTTP 통신을 처리하는 웹 서버의 관점에서는 http request(요청 입력), http response(응답 츨력)을 담당하는 레이어입니다. 따라서 통신이 처음 시작될 때, 사용자로부터 받은 정보를 클라이언트(프론트 엔드)가 전달해 주면, 해당 입력에 대한 유효성 검증을 처리하며 에러 및 예외가 발생할 수 있습니다. 

 

이런 에러 및 예외 발생 시 전달하는 메시지에 KEY_ERROR가 대표적입니다. Request로 들어와야 하는 정보 가운데 누락된 key가 있을 때를 지칭하며 클라이언트가 키를 누락시켰다는 것은, 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')
} // 에러 발생 시점
  • 회원가입 시 email, password 등 필수 정보가 누락될 경우 
  • 주문 생성 시 주문하는 제품에 대한 필수 정보 product_id, quantity, user_id 등이 누락될 경우 

이런 키에러 상황은 key는 있지만 해당하는 키에 빈 값이 들어오는 것과는 다른 상황입니다. controller에서 처리해야 하는 예외 상황은 key가 아예 들어오지 않아서, 요청 자체에 문제가 있는 상황입니다. 

// 키에러가 발생하지 않으나, 값이 빈 상태

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
} // 에러 발생하지 않음.

 

물론 이렇게 입력하고 있을 때가 아니라, 사용자에게 출력을 보낼 때(http response)에도 에러가 발생할 수 있습니다. 

입출력 외 컨트롤러가 하는 일을 따로 정해두었다면, 해당 작업 중 발생 가능한 에러를 사전에 핸들링 해두는 것이 좋습니다. 사용자 입력이 잘못되었다면, 주로 400번대 http status code를 보내게 됩니다. 

 

2. Service Error

서비스 레이어는 주로 비즈니스 로직과 규칙을 설정하는 곳입니다. 보통 기획에 따른 비즈니스 규칙에 비롯된, 개발자가 직접 의도한 예외와 관련된 에러가 발생합니다. 에러의 발생 위치는 Service 단 하위에 위치한 계층의 모듈과 직접 이곳에서 호출하는 서비스 모듈의 에러가 발생할 수 있습니다.

 

만일 비즈니스 규칙에 위반되는 사항이 발생 할 수 있다면 Service단에서 해당 문제의 경우에 상응한 Status Code와 함께 에러를 발생시켜야 합니다. 사용자의 요청의 문제가 아닌 내부 처리 과정 중 문제라면 500번대 Status Code를 보내는 것이 일반적입니다. 

 

다음 예시 코드는 회원가입 시 service단에서 기획에 맞게 꼭 설정되어야 하는 비밀번호 보안성에 대해 올바른 형태로 비밀번호를 적었는지 유효성 확인합니다. 

//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
  }

 

 

3. Dao Error

데이터 엑세스 레이어는 데이터베이스와 관련된 코드를 작성하는 곳입니다. 데이터 베이스 드라이버가 위치하는 곳으로 DB 의존적인 에러가 발생할 수 있습니다. 

Node + Express와는 다른 외부 시스템으로 연동되어 주로 비동기 호출을 하기 때문에 비동기 에러 핸들링에 적합한 방법을 이용해야 합니다. 데이터 베이스 관련된 문제로 에러가 발생한다면 500번대 status code를 보내줄 수 있습니다. 

나머지 예외사항(DB에 데이터 없음 등)에는 적절한 status code 및 에러를 던져주면 됩니다. 

 

코드 예시 

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
}
반응형

'BackEnd' 카테고리의 다른 글

세션(Session)과 토큰(Token)에 대해서  (0) 2023.11.24
인증 & 인가에 대해서  (0) 2023.11.23
Error Handing 적용하기  (0) 2023.11.19
Error Handing에 대해서  (0) 2023.11.19
[API] Middleware에 대해서  (0) 2023.11.15

댓글