[프로젝트] 글로벌 예외처리(AOP)

박연주·2022년 8월 9일
0

일반적인 예외처리

  • Spring에서는 발생한 Exception을 기반으로 오류를 처리할 수 있도록 @ExceptionHandler를 제공
  • 해당 애너테이션에 선언된 예외 및 하위 예외에 대해서 특정 메서드가 처리할 수 있도록 함
    -> 보통의 핸들러와 마찬가지로 @ResponseStatus를 통해 응답 코드 정의가능
    -> ModelAndView, String을 반환하여 view를 resolve할 수 있고, ResponseEntity<T> 반환도 가능

@RestController
@RequestMapping("/boards")
public class BoardController {

  @GetMapping("/{id}")
  public Board get(@PathVariable Long id) {
    if (id < 1L) {
      throw new BoardNotFoundException("invalid id: " + id);
    }
    return new Board("title", "content");
  }

  @ResponseStatus(HttpStatus.NOT_FOUND)
  @ExceptionHandler(BoardNotFoundException.class)
  public Map<String, String> handle(BoardNotFoundException e) {
      log.error(e.getMessage(), e);
      Map<String, String> errorAttributes = new HashMap<>();
      errorAttributes.put("code", "BOARD_NOT_FOUND");
      errorAttributes.put("message", e.getMessage());
      return errorAttribute;
  }
}


글로벌 예외처리

왜 해야하는가,

  • handleLineException 메소드를 통해 컨트롤러, 서비스 내에서 발생하는 예외를 처리할 수 있음
    -> 컨트롤러가 늘어나면 중복 코드가 늘어나고, 유지보수 또한 어려워짐
    -> 전역 예외처리를 통해 해결 가능

ControllerAdvice, RestControllerAdvice 사용으로 예외 처리

  • 전역에서 예외처리를 하기 위해 @ControllerAdvice 또는 @RestControllerAdvice 사용
  • AOP(Aspect Oriented Programming)의 방식이며 Application 전역에 발생하는 모든 서비스의 예외를 한 곳에서 관리할 수 있게 해줌
  • 컨트롤러에서 발생하는 모든 예외는 @RestControllerAdvice가 잡고, @ExceptionHandler가 개별적으로 예외를 잡아 처리하는 방식


@RestControllerAdvice
@ControllerAdvice
public class ExceptionController {
    
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<ExceptionResponse> clientBadRequest(final IllegalArgumentException ex){
        return new ResponseEntity<>(new ExceptionResponse(ex.getMessage()), HttpStatus.BAD_REQUEST);
    }

}

// IllegalArgumentException 발생 시 clientBadRequest() 메소드 실행
// 메세지와 상태코드 담아서 반환


모든 예외를 하나의 Enum 클래스로

  • 동일한 구조의 응답 포맷을 미리 설정하기 위해 enum 클래스로 관리
@AllArgsConstructor
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum ExceptionStatus {
    USER_NOT_FOUND("회원을 찾을 수 없습니다."),
    EVENT_BOOKMARK_NOT_FOUND("이벤트 북마크를 찾을 수 없습니다."),
    EVENT_NOT_FOUND("이벤트를 찾을 수 없습니다."),
    POST_NOT_FOUND("게시글을 찾을 수 없습니다."),
    COMMENT_NOT_FOUND("댓글을 찾을 수 없습니다."),
    CAFE_NOT_FOUND("카페를 찾을 수 없습니다.");

    private final String message;

    public String getStatus(){
        return name();
    }

    public String getMessage(){
        return message;
    }
}


ExceptionResponse

  • 예외 응답을 처리할 Response 클래스
  • ResponseEntity<ExceptionResponse> 예외가 발생했을 때 ExceptionResponse 형식으로 예외 정보를 Response로 내려줌
@AllArgsConstructor
@Getter
public class ExceptionResponse {
    private String message;
}

기타 궁금점

  • @ControllerAdvice, @RestControllerAdvice의 차이는 뭘까
RestController = Controller + ResponseBody
RestControllerAdvice = ControllerAdvice + ResponseBody

-> 위 같은 구조이기때문에 controller의 예외도 RestControllerAdvice가 잡아줄 수 있음
  • @RestControllerAdvice@RestController와 마찬가지로 @ResponseBody가 있어서 자바 객체를 Json/Xml 형태로 반환하여 HTTP Response Body에 담을 수 있다는 차이가 있음


Spring 전역에서 예외처리

profile
하루에 한 개념씩

0개의 댓글