[Spring] 예외 처리

zini9188·2023년 2월 21일
0

Spring

목록 보기
19/33

예외 처리

자바에서 try-catch를 활용하여 예외를 잡던 것 처럼 스프링에서도 throw로 예외를 던진 것을 @ExceptionHandler를 통해 잡을 수 있다.

@ExceptionHandler를 활용하면 애플리케이션에서 예외가 발생했을 때 예외를 잡아 원인을 응답 메세지로 받아볼 수 있다.

@ExceptionHandler
public ResponseEntity handleException(MethodArgumentNotValidException e) {        
        final List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();        
        return new ResponseEntity<>(fieldErrors, HttpStatus.BAD_REQUEST);
}       

예외가 발생했을 때 응답 메세지는 다음과 같은데, 기본적으로 지원하는 fieldErrors는 원하지 않는 정보까지 전달해줄 수도 있다.

[
    {
        "codes": [
            "Email.memberPostDto.email",
            "Email.email",
            "Email.java.lang.String",
            "Email"
        ],
        "arguments": [
            {
                "codes": [
                    "memberPostDto.email",
                    "email"
                ],
                "arguments": null,
                "defaultMessage": "email",
                "code": "email"
            },
            [],
            {
                "arguments": null,
                "defaultMessage": ".*",
                "codes": [
                    ".*"
                ]
            }
        ],
        "defaultMessage": "올바른 형식의 이메일 주소여야 합니다",
        "objectName": "memberPostDto",
        "field": "email",
        "rejectedValue": "hgd@",
        "bindingFailure": false,
        "code": "Email"
    }
]

원하는 정보만 전달하는 방법

원하는 정보만을 전달하기 위해서는 원하는 예외 정보만을 담는 클래스가 필요하다. 특정 클래스를 생성하여 필요한 정보만을 담을 수 있다.

@Getter
@AllArgsConstructor
public class ErrorResponse {
    private List<FieldError> fieldErrors;

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

이를 기반으로 핸들러 메서드의 예외 메세지를 반환받으면 다음과 같은 결과를 얻을 수 있다. 이름과 이메일이 유효성 검증에 실패해 오류 메세지로 반환 되었다.

AOP를 활용한 예외 처리

Controller에서 예외를 잡으면 모든 Controller에 예외 처리 핸들러 메서드가 필요하게 된다. Controller가 늘어나면 작성해야할 @ExceptionHandler 또한 늘어난다.

이러한 문제를 해결하기 위해서는 @RestControllerAdvice를 활용하여 예외 처리를 공통화하면 각각의 Controller에 예외 처리 핸들러 메서드를 추가하지 않고 공통적으로 사용할 수 있다.

@RestControllerAdvice
public class GlobalExceptionAdvice{
}

비즈니스적인 예외 던지기와 예외 처리

애플리케이션의 예외는 두 가지로 나눌 수 있다.

체크 예외

예외를 잡아 해당 예외를 복구하거나 회피하는 어떤 구체적인 처리를 해야하는 예외를 말한다. 대표적으로 ClassNotFoundException가 있다.

언체크 예외

예외를 잡아 해당 예외에 대한 처리를 할 필요가 없는 예외를 의미하며 명시적으로 잡아서 처리할 필요가 없다. 대표적으로 NullPointerException, ArrayIndexOutOfBoundsException 등이 있다.

RuntimeException을 상속하는 예외는 모두 언체크 예외이며 RuntimException을 상속하여 개발자가 직접 사용자 정의 예외를 구현할 수 있다.

개발자가 의도적으로 예외를 던지는 상황

  • 백엔드 서버와 외부 시스템과의 연동에서 발생하는 에러 처리

  • 시스템 내부에서 조회하려는 리소스가 없는 경우

이외에도 여러 상황에서 예외를 던져야하는 상황이 발생한다. 예외도 상황이 다양하게 존재하기 때문에 구체적으로 어떤 예외가 발생하였는지에 대한 예외 처리가 필요하다.

profile
백엔드를 지망하는 개발자

0개의 댓글