[TIL] Error Handling 23.07.21

이상훈·2023년 7월 21일
0

[내일배움캠프]

목록 보기
47/68

leve5과제 피드백을 받았다.
예외처리 및 에러를 컨트롤러에서 errorMessage라는 형태로 받았는데, 상당히 위험한 패턴이라고 하셨다. errorMessage가 있다는 이유만으로 에러를 100% 판단할 수 있는지에 대해 보장할 수 없고 서비스는 반드시 errorMessage라는 값을 내릴 수 있는 구조여야만 하기 때문에 종속성이 커보인다고 하셨다.
기존 에러처리 방법

// controller
if(userData.errorMessage)
  
//service
return {code : 400, errorMessage : ""}

이런식으로 서비스에서 컨트롤러로 보내주는 구조였다.
피드백을 받고 난 후 이번 팀과제를 진행하면서 커스텀에러로 에러핸들링을 해보는 시도를 했다. 이 방법이 맞는지는 모르겠지만 이번 팀과제 피드백을 받아보면서 한번 여쭤보는게 좋을 것 같다.

먼저 에러를 핸들링할 errorHandler를 만들어주었다.

class CustomError {
  constructor(status, errorMessage) {
    this.status = status;
    this.errorMessage = errorMessage;
  }
}

// status 코드 구글링 후 수정필요
const errorHandler = {
  // signup
  emailFormat: new CustomError(400, '이메일 형식이 올바르지 않습니다. 다시 입력해 주세요'),
  passwordFormat: new CustomError(
    400,
    '패스워드는 4자리 이상이고 이메일과 같은 값이 포함될 수 없습니다.'
  ),
  checkPassword: new CustomError(412, '비밀번호가 일치하지 않습니다.'),
  // login
  checkUser: new CustomError(412, '회원가입되지 않은 이메일이거나 비밀번호가 다릅니다.'),
  // user common error
  existEmail: new CustomError(409, '이미 존재하는 이메일입니다.'),
  // kakaoCallBack
  nonToken: new CustomError(409, '토큰이 존재하지 않습니다.'),

  // registerStore
  existStore: new CustomError(409, '이미 존재하는 매장 이름입니다.'),
  addStoreForbidden: new CustomError(401, '매장을 추가로 등록할 수 없습니다.'),

  // getStoreRanking
  periodError: new CustomError(400, '기간은 숫자만 들어올 수 있으며 31일을 초과할 수 없습니다.'),

  // store common error
  noStore: new CustomError(404, '보유한 매장이 없습니다.'),
  duplicateMenu: new CustomError(409, '이미 등록된 메뉴입니다.'),
  noSeller: new CustomError(401, '사장으로 로그인한 계정만 이용할 수 있는 기능입니다.'),

  // orderMenu
  pointLess: new CustomError(400, '잔여포인트가 부족해 주문 할 수 없습니다.'),
  nonList: new CustomError(400, '주문할 음식이 없습니다.'),
  // isDelivered
  noOrder: new CustomError(404, '주문 내역이 없습니다.'),
  completedOrder: new CustomError(400, '이미 배달이 완료된 주문입니다.'),
  refundOrder: new CustomError(400, '고객님이 환불 요청한 주문입니다.'),
  cancelledOrder: new CustomError(400, '이미 환불된 주문입니다.'),
  // refundRequest
  completedRefund: new CustomError(400, '이미 환불된 주문입니다.'),
  requestingRefund: new CustomError(400, '이미 환불 요청 중인 주문입니다.'),
  // refundCompleted
  notRequestRefund: new CustomError(400, '주문 환불 요청이 들어온 주문이 아닙니다.'),
  // order common error
  notRegistered: new CustomError(404, '등록한 사업장이 없습니다.'),
  orderNotFound: new CustomError(404, '해당 주문을 찾을 수 없습니다.'),

  // postReivew
  duplicateReview: new CustomError(409, '해당 주문에 대한 리뷰를 이미 작성하셨습니다.'),
  noOrderHistory: new CustomError(400, '주문 내역이 없어 리뷰를 작성 할 수 없습니다.'),
  // updateReview
  nonExistReview: new CustomError(404, '작성된 리뷰가 존재하지 않습니다.'),

  // common error
  nonExistStore: new CustomError(404, '해당 매장이 존재하지 않습니다.'),
  nonExistMenu: new CustomError(404, '존재하지 않는 메뉴입니다.'),
  noPermissions: new CustomError(401, '해당 권한이 없습니다.'),
  emptyContent: new CustomError(400, '내용을 모두 입력해주세요.'),
};
module.exports = errorHandler;

에러 핸들러를 만들어 준 뒤 service 와 controller에서는 에러가 발생하면 throw하고 next()로 app.js에 넘겨준 뒤 app.js에서 핸들링 하는 구조로 만들었다.
Service

  likeReview = async (userId, storeId, reviewId) => {
    try {
      const getReviewDetail = await this.reviewRepository.getReviewDetail(storeId, reviewId);

      if (!getReviewDetail) throw errorHandler.nonExistReview;

      const likeReview = await this.likeRepository.likeReview(userId, reviewId);
      return { code: 200, message: likeReview.message, likeCount: likeReview.likeCount };
    } catch (err) {
      throw err;
    }
  };
}

Controller

  likeReview = async (req, res, next) => {
    try {
      const user = res.locals.user;
      const { storeId, reviewId } = req.params;

      const likeReview = await this.reviewService.likeReview(user.id, storeId, reviewId);

      return res.status(likeReview.code).json({
        message: likeReview.message,
        likeCount: likeReview.likeCount,
      });
    } catch (err) {
      next(err);
    }
  };
}

app.js

app.use(async (err, req, res, next) => {
  const { status, errorMessage } = await err;
  console.error(errorMessage);

  res.status(status || 500).json({ errorMessage: errorMessage || '서버 오류가 발생했습니다.' });
});

이번 팀과제 제출 후 피드백을 받아본 뒤 좀 더 개선해봐야겠다.

profile
코린이

0개의 댓글