예외 처리

InSeok·2022년 9월 22일
0

TIL

목록 보기
35/51

목차


  1. **ExceptionHandler**
  2. **RestControllerAdvice**
  3. 체크 예외
  4. 언체크 예외
  5. **사용자 정의 예외(Custom Exception)**

배운 내용


**@ExceptionHandler**

**Controller 레벨에서의 예외 처리**

  • Spring에서 내부적으로 처리하는 에러 응답 메시지를 우리가 직접 처리하도록 코드를 수정해보자.
  • 에러 메시지를 구체적으로 전송해주기 때문에 클라이언트 입장에서 어느 곳에 문제가 있는지를 구체적으로 알 수있게 된다.
@ExceptionHandler
    public ResponseEntity handleException(MethodArgumentNotValidException e) {
// 메소드 파라미터데이터 유효성 검증실패 -> 아래 메서드를 통해 발생한 에러정보 확인
        final List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();

        return new ResponseEntity<>(fieldErrors, HttpStatus.BAD_REQUEST);
    }
  • Request Body의 JSON 프로퍼티 중에서 문제가 된 프로퍼티는 무엇인지와 에러 메시지 정도만 전달 받아도 충분하다.
    • 에러 정보를 기반으로 한 Error Response 클래스를 만들어서 필요한 정보만 담은 후에 클라이언트 쪽에 전달
@Getter
@AllArgsConstructor
public class ErrorResponse {
		
//한 개 이상의 유효성 검증에 실패한 필드의 에러 정보를 담기 위한 List 객체
    private List<FieldError> fieldErrors;

    @Getter
    @AllArgsConstructor
    public static class FieldError {
        private String field;
        private Object rejectedValue;
        private String reason;
    }
}

단점

  1. Controller마다 동일하게 발생하는 예외 처리에 대한 중복 코드가 발생
  2. 하나의 Controller 클래스 내에서 @ExceptionHandler를 추가한 에러 처리 핸들러 메서드가 늘어남(예외 종류가 하나만 있는것이 아니므로)
  3. 다양한 유형의 예외를 처리하기에는 적절하지 않은 방식

**@RestControllerAdvice**

**예외 처리 공통화**

  • 특정 클래스에 @RestControllerAdvice애너테이션을 추가하면 여러개의 Controller 클래스에서 @ExceptionHandler, @InitBinder또는 @ModelAttribute가 추가된 메서드를 공유해서 사용가능
  • @RestControllerAdvice애너테이션을 추가한 클래스를 이용하면 예외 처리를 공통화 할 수 있다
  • @RestControllerAdvice@ControllerAdvice + @ResponseBody
    • JSON 형식의 데이터를 Response Body로 전송하기 위해서 ResponseEntity로 데이터를 래핑할 필요가 없다

of()메서드
네이밍 컨벤션(Naming Convention) ,
주로 객체 생성시 어떤 값들의(of~)
객체를 생성한다는 의미에서 of() 메서드를 사용한다

  • @ResponseStatus애너테이션을 이용해서 HTTP Status를 HTTP Response에 포함가능

**체크 예외(Checked Exception)와 언체크 예외(Unchecked Exception)**

체크 예외

  • 발생한 예외를 잡아서(catch) 체크한 후에 해당 예외를 복구 하든가 아니면 회피 하든가 등의 어떤 구체적인 처리를 해야 하는 예외
  • ex)ClassNotFoundException

언체크 예외

  • 예외를 잡아서(catch) 해당 예외에 대한 어떤 처리를 할 필요가 없는 예외
  • ex) NullPointerException

개발자가 코드를 잘못 작성해서 발생하는 이런 오류들은 모두 RuntimeException
을 상속한 예외이며, 언체크예외

**개발자가 의도적으로 예외를 던져야하는 경우**

  • 백엔드 서버와 외부 시스템과의 연동에서 발생하는 에러 처리
  • 시스템 내부에서 조회하려는 리소스(자원, Resource)가 없는 경우

**의도적인 예외 던지기/받기(throw/catch)**

  • Java에서는 throw 키워드를 사용해서 예외를 메서드 바깥으로 던질 수 있다.
    • 던져진 예외는 메서드 바깥 즉, 메서드를 호출한 지점으로 던져진다.
    • 서비스 계층에서 던져진 예외는 Controller의 핸들러 메서드 쪽에서 잡아서 처리가능
      • 이미 Controller에서 발생하는 예외를 Exception Advice에서 처리하도록 공통화 →서비스 계층에서 던진 예외 역시 Exception Advice에서 처리하면 된다.

**사용자 정의 예외(Custom Exception) 사용**

  • RuntimeException을 상속해서 개발자가 직접 사용자 정의 예외(Custom Exception)를 만들 수 있다.
  • 사용자 정의 예외(Custom Exception)를 정의해서 서비스 계층의 비즈니스 로직에서 발생하는 다양한 예외를 던질 수 있고, 던져진 예외는 Exception Advice에서 처리가능
  • ExceptionCodeenum으로 정의하면 비즈니스 로직에서 발생하는 다양한 유형의 예외를 enum에 추가하여 간편하게 사용가능
  • RuntimeException을 상속한 CustomException 정의 ,
  • ExceptionCode를 멤버 변수로 지정하여 생성자를 통해서 조금 더 구체적인 예외 정보들을 제공
  • 상위 클래스인 RuntimeException의 생성자(super)로 예외 메시지를 전달
  • 예외를 던져야 하는 다양한 상황에서 ExceptionCode 정보만 바꿔가며 던질 수 있다.
public enum ExceptionCode {
    MEMBER_NOT_FOUND(404, "Member Not Found");

    @Getter
    private int status;

    @Getter
    private String message;

    ExceptionCode(int status, String message) {
        this.status = status;
        this.message = message;
    }
}

public class CustomException extends RuntimeException {
    @Getter
    private ExceptionCode exceptionCode;

    public CustomException(ExceptionCode exceptionCode) {
        super(exceptionCode.getMessage());
        this.exceptionCode = exceptionCode;
    }
}

고정된 예외를 처리할 경우에는 @ResponseStatus로 HttpStatus를 지정해서 사용

BusinessLogicException처럼 다양한 유형의 Custom Exception을 처리하고자 할 경우에는 ResponseEntity를 사용

profile
백엔드 개발자

0개의 댓글