프레임워크/스프링

[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 전역에서 예외 처리 전용 예외 핸들러 클래스 생성