백엔드/Spring Boot
Spring boot Exception Handling
whooooo
2024. 1. 17. 15:41
예외 처리는 안전한 프로그램을 만들기 위한 필수 항목.. 아닐까요?!
스프링 부트에서는 @ControllerAdvice로 전역에서 발생하는 모든 컨트롤러에 대한 예외를 효과적으로 관리하고, @ExceptionHandler를 활용하여 각 컨트롤러 내부에서 발생하는 예외처리를 세부적으로 다룰 수 있습니다. 이 두 가지 방식을 조합하여 사용하면 코드 일관성과 예외 처리 효율을 동시에 유지할 수 있습니다. 그럼 이제 스프링 부트 에서의 예외 처리에 대하여 알아보도록 하겠습니다 😀
1️⃣ 스프링에서의 예외 처리를 위한 어노테이션
# @ControllerAdvice, @ExceptionHandler
Spring에서는 예외를 핸들링하기 위해서 @ControllerAdvice, @ExceptionHandler 어노테이션을 사용합니다.
기존에는 Exception을 처리하기 위해 try~catch문을 사용했지만 같은 예외라도 다른 위치에서 발생하게 되는 경우 코드가 중복되는 현상이 있었습니다. 그리고 어노테이션을 사용하여 예외에 대한 부분을 따로 처리하게 되면 비즈니스 로직과 예외 처리 로직이 분리되어 유지보수하기 편해지기 때문에 어노테이션을 이용하여 예외처리를 하는 것을 추천합니다.
(😱 외부에서 호출되는 함수에는 접근제한자를 protected or private로 선언해주자! )
@ControllerAdvice
- 전역(모든 컨트롤러) 에서 발생하는 예외를 처리해 주는 어노테이션
- assignableTypes로 적용 대상 컨트롤러를 설정 가능
/**
* ResponseEntityExceptionHandler : Spring에서 예외를 미리 처리해 둔 추상클래스
*/
@Slf4j // 로깅을 위하여 추가
@RestControllerAdvice // 전역에서 발생하는 예외에 대하여 처리
// @ControllerAdvice(assignableTypes = {UserController.class, AdminController.class})
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
}
@ExceptionHandler
- 특정 컨트롤러에서 발생하는 예외에 대한 처리
- 예외 처리 상황이 발생하면 해당 Handler로 처리하겠다고 명시
- 어노테이션 뒤에 괄호를 붙여 어떤 ExceptionClass를 처리할지 설정
Ex. @ExceptionHandler(OOExcpetion.class) - 전역 설정(@ControllerAdvice) 보다 지역 설정(Controller)으로 정의한 핸들러가 우선순위를 가진다.
- @Service, @Repositry등 @Controller(@RestController)가 아닌 Bean에서는 사용이 불가능
@RestController
public class SimpleController {
@ExceptionHandler(ApplicaitonException.class)
public ResponseEntity<String> ApplicationException() {
return new ResponseEntity<>("Custom Exception occurred: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
2️⃣ JAVA에서의 예외 종류
# Unchecked Exception VS Checked Exception
- Unchecked Exception : RuntimeException의 하위 클래스
Checked Exception : RuntimeException의 하위 클래스가 아닌 Exception 클래스의 하위 클래스 - 모든 예외 클래스는 Throwable 클래스를 상속 받고 있다.
Checked Exception | Unchecked Exception | |
처리여부 | 반드시 예외 처리 필요 | 명시적 처리 강제하지 않음 |
확인시점 | 컴파일 단계 | 런타임 단계(프로그램 동작중에 발생) |
대표 예외 | IOException SQLException |
NullPointerException IllegalArgumentException IndexOutOfBoundsException SystemException |
✔️ Checked Exception 종류
예외 종류 | 발생원인 | 예시 |
IOException | 입출력 작업 중 에러 발생 | 파일을 읽는 도중에 파일이 존재하지 않거나 권한이 없는 경우 |
SQLException | 데이터베이스와 관련된 작업 중 에러 발생 | 잘못된 SQL 쿼리를 실행하거나 데이터베이스에 접속이 불가능한 경우 |
ClassNotFoundException | 클래스 로딩 시 에러 발생 | 프로그램이 실행될 때 필요한 클래스 파일을 찾지 못하거나 클래스 패스가 올바르지 않은 경우 |
FileNotFoundException | 파일을 찾을 수 없을 때 발생 | 파일 경로가 올바르지 않은경우 |
✔️ Unchecked Exception 종류
예외 종류 | 발생원인 | 예시 |
RuntimeException | 프로그램 동작 중 에러 발생 | 배열의 범위 밖의 인덱스를 조회 하는 등 프로그램 논리 오류 발생한 경우 |
NullPointerException | null 값인 객체나 필드를 호출 할 때 발생 | 객체를 생성하지 않고 바로 메소드를 호출 하는 경우 |
IllegalArgumentException | 메소드에 전달된 인수가 해당 메소드에서 허용하지 않는 값 또는 범위를 가지고 있는 경우 | 메소드가 특정 범위의 숫자를 요구하는데, 그 범위를 벗어난 값을 전달하는 경우 |
ArrayIndexOutOfBoundsException | 배열에 유효하지 않은 인덱스로 접근 시 에러 발생 | 배열의 길이가 5인데 6번째 인덱스의 요소에 접근하려고 하는 경우 |
ArithmeticException | 산술 연산 중 에러 발생 | 0으로 나누는 연산이나 부정확한 계산이 실행되는 경우 |
HttpRequestMethodNotSupportedException | HTTP 요청 메소드가 지원되지 않는 경우 에러 발생 | GET 요청이 필요한데 POST로 요청한 경우 |
MethodArgumentNotValidException | 메소드의 인수가 유효성 검사에서 실패시 에러 발생 | Spring에서 요청된 데이터의 유효성 검사에서 실패한 경우 (@Valid) |