프레임워크/스프링
[Spring] 예외처리 @ExceptionHandler, @ControllerAdvice
believekim
2025. 3. 25. 12:59
Spring에서 예외처리를 깔끔하게 도와주는 어노테이션인
@ExceptionHandler와 @ControllerAdvice에 대해 짧게 정리해본다
1. 예외처리
- 프로그램 실행 도중 예상치 못한 상황이나 오류가 발생했을 때 비정상적으로 종료되지 않고 문제를 처리할 수 있도록 해주는 기법
- 예시: 0으로 나누기를 할 때
int a = 10;
int b = 0;
int result = a / b; // 실행 중 오류 발생 → 프로그램 강제 종료
- 예외 처리를 하면
try {
int result = a / b;
} catch (ArithmeticException e) {
System.out.println("0으로 나눌 수 없습니다!");
}
- 종류는 크게 Checked Exception과 Unchecked Exception으로 나뉜다.
구분 | Checked Exception | Unchecked Exception (Runtime) |
예외 처리 | 반드시 해야 함 (try-catch or throws) | 선택 (안 해도 됨) |
발생 시점 | 컴파일 시 검사 | 실행 도중 발생 (런타임) |
주로 발생하는 상황 | 외부 환경, IO, DB | 프로그래밍 실수 (null 접근, 0 나누기 등) |
대표 예시 | IOException, SQLException | NullPointerException, ArithmeticException |
스프링에서는 Unchecked Exception을 많이 사용하며
대부분 RuntimeException을 상속해서 커스텀 예외 만들고
@ExceptionHandler, @ControllerAdvice로 잡아서 처리
2. @ExceptionHandler
- 특정 컨트롤러나 메서드에서 발생한 예외(Exception)를 처리
- 반환값으로 에러 메시지, 뷰, 응답 코드 등을 자유롭게 작성
- 반환 타입은 자유 (ResponseEntity, String, JSON 등)
// 기본구조
@ExceptionHandler(예외클래스.class)
public 반환타입 메서드명(예외클래스 e) {
// 예외 처리 로직
}
// 사용 예시
@RestController
public class SampleController {
@GetMapping("/test")
public String test() {
if (true) {
throw new IllegalArgumentException("잘못된 요청입니다!");
}
return "OK";
}
// 컨트롤러 내부에서 처리
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgument(IllegalArgumentException e) {
return ResponseEntity.badRequest().body("에러 발생: " + e.getMessage());
}
}
3. @ControllerAdvice
- 전역(Global) 예외 처리 -> 모든 컨트롤러에서 발생하는 예외를 한 곳에서 모아서 처리
- @ExceptionHandler와 함께 사용
- @RestControllerAdvice로 쓰면 @ResponseBody까지 적용돼서 JSON 응답하기 좋음
// 기본 구조
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(예외클래스.class)
public 반환타입 메서드명(예외클래스 e) {
// 공통 예외 처리
}
}
// 사용 예시
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgument(IllegalArgumentException e) {
return ResponseEntity.badRequest().body("전역 처리: " + e.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
return ResponseEntity.internalServerError().body("서버 에러 발생: " + e.getMessage());
}
}
▶ 사용하는 이유
1. 예외 발생 시 중복된 try-catch 필요 없음
2. API 응답 포맷 통일
구분 | 특징 | 사용 위치 |
@ExceptionHandler | 해당 컨트롤러에서만 작동 | 컨트롤러 내부 |
@ControllerAdvice | 전역에서 예외 처리 | 전용 예외 핸들러 클래스 생성 |