1. @RestControllerAdvice 사용해서 Controller 예외처리
@RestControllerAdvice 어노테이션은 Spring Framework에서 예외 처리를 위해 사용되는 특별한 클래스에 붙이는 어노테이션입니다. 이 어노테이션을 사용하면 전역에서 발생할 수 있는 예외를 캡처하고, 공통된 예외 처리 로직을 적용하여 API 응답을 일관성 있게 관리할 수 있습니다. @RestControllerAdvice는 @ControllerAdvice에 @ResponseBody가 추가된 형태로, REST API 개발 시 JSON 등의 응답 바디를 직접 제어할 수 있게 해줍니다.
1-1. 동작 방식
- Spring의 AOP(Aspect-Oriented Programming)를 이용하여, 애플리케이션의 컨트롤러 계층에서 발생하는 예외를 잡아낸 후, 지정된 예외 처리 로직에 따라 처리합니다.
- @ExceptionHandler 어노테이션을 사용하여 특정 예외를 처리하는 메서드를 정의할 수 있습니다.
- @RestControllerAdvice 어노테이션을 사용한 클래스는 애플리케이션 전역에서 발생하는 예외를 처리할 수 있는 공통의 예외 처리기 역할을 합니다.
- 예외 처리 메서드는 예외 유형별로 다르게 정의할 수 있으며, 예외 발생 시 적절한 HTTP 상태 코드와 메시지를 응답으로 반환할 수 있습니다.
1-2. 전역 예외 처리기 구현
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.http.ResponseEntity;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public ResponseEntity<String> handleGenericException(Exception e) {
// 모든 예외를 처리하고 500 Internal Server Error 반환
return ResponseEntity
.status(500)
.body("Internal Server Error: " + e.getMessage());
}
@ExceptionHandler(value = NullPointerException.class)
public ResponseEntity<String> handleNullPointerException(NullPointerException e) {
// NullPointerException을 처리하고 400 Bad Request 반환
return ResponseEntity
.status(400)
.body("Null Pointer Exception: " + e.getMessage());
}
@ExceptionHandler(value = CustomException.class)
public ResponseEntity<String> handleCustomException(CustomException e) {
// 사용자 정의 예외 처리
return ResponseEntity
.status(e.getStatusCode())
.body("Custom Error: " + e.getMessage());
}
}
이 예시에서는 세 가지 예외 처리 메서드를 정의하고 있습니다:
- Exception.class에 대한 처리: 모든 종류의 예외를 처리하며, HTTP 상태 코드 500을 반환합니다.
- NullPointerException.class에 대한 처리: NullPointerException을 처리하며, HTTP 상태 코드 400을 반환합니다.
- CustomException.class에 대한 처리: 사용자 정의 예외를 처리하며, 예외에 설정된 상태 코드와 메시지를 반환합니다.
@RestControllerAdvice를 사용함으로써 애플리케이션 전역에서 발생하는 예외를 효과적으로 관리할 수 있으며, API 응답의 일관성을 유지할 수 있습니다.
2. 상속 관계에서의 예외처리는 어떻게 되는 것일까?
Spring에서는 예외 처리 시 클래스 간의 상속 관계를 고려하여 더 구체적인 예외, 즉 자식 예외 클래스에 대한 처리기(**@ExceptionHandler**가 붙은 메서드)가 있을 경우, 그 처리기를 우선적으로 사용합니다. 이는 예외가 발생했을 때 더 세밀한 예외 처리를 가능하게 합니다.
예를 들어, **NullPointerException**이 **RuntimeException**의 자식 클래스인 경우, 두 예외 모두를 처리할 수 있는 **@ExceptionHandler**가 있다면 **NullPointerException**에 대한 처리기가 우선적으로 호출됩니다. 만약 해당하는 구체적인 예외를 처리하는 **@ExceptionHandler**가 없다면, 상위 클래스를 처리하는 **@ExceptionHandler**가 대신 호출됩니다.
이러한 방식은 예외를 더 정확하게 처리하고, 다양한 예외 상황에 대해 더 상세한 응답을 제공하는 데 유용합니다. 예외 클래스의 상속 구조를 이해하고 올바르게 활용하면, 예외 처리 로직을 효과적으로 구성할 수 있습니다.
2-1. 상속 관계에서의 예시
아래는 상속 관계에 있는 예외를 처리하는 간단한 예시입니다. 이 예시에서는 RuntimeException과 그 자식 예외인 ArithmeticException을 처리하는 방법을 보여줍니다. ArithmeticException이 발생하면, 더 구체적인 예외 처리기인 handleArithmeticException 메서드가 호출되며, RuntimeException이나 그 외의 자식 예외들이 발생할 경우 handleRuntimeException 메서드가 호출됩니다.
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.http.ResponseEntity;
@RestControllerAdvice
public class ExceptionHandlingController {
// ArithmeticException 처리
@ExceptionHandler(ArithmeticException.class)
public ResponseEntity<String> handleArithmeticException(ArithmeticException e) {
return ResponseEntity
.badRequest()
.body("Arithmetic Exception Occurred: " + e.getMessage());
}
// RuntimeException 및 그 자식들 처리 (ArithmeticException 제외)
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleRuntimeException(RuntimeException e) {
return ResponseEntity
.status(500)
.body("Runtime Exception Occurred: " + e.getMessage());
}
}
이 예시에서는 다음과 같은 작동 방식을 확인할 수 있습니다:
- ArithmeticException 발생 시: handleArithmeticException 메서드가 호출되어 HTTP 상태 코드 400(Bad Request)과 함께 "Arithmetic Exception Occurred: [에러 메시지]"라는 응답 바디를 반환합니다.
- ArithmeticException 이외의 RuntimeException 발생 시: handleRuntimeException 메서드가 호출되어 HTTP 상태 코드 500(Internal Server Error)과 함께 "Runtime Exception Occurred: [에러 메시지]"라는 응답 바디를 반환합니다.
이 방식을 통해 애플리케이션에서 발생할 수 있는 다양한 예외 상황에 대해 더 세분화된 예외 처리를 구현할 수 있으며, 예외의 유형에 따라 적절한 응답을 제공할 수 있습니다.
'Back-end > Spring' 카테고리의 다른 글
[Spring] JPA Query 메서드 DTO 바로 생성하기 (0) | 2024.04.07 |
---|---|
[Spring] Security CSRF 비활성화 (6.1 버전 이상) (0) | 2024.02.09 |
[Spring] @SuperBuilder 의 특징과 간단한 예제 (0) | 2024.02.09 |
[Spring] DTO 간 복사(BeanUtils, ModelMapper커스텀 하는방법 포함) (0) | 2024.02.09 |
[Spring] 시큐리티 예외 처리와 사용자 인증 (시큐리티6 이상) (1) | 2024.01.30 |