Global Exception이란?
Global Exception(전역 예외 처리)이란, 애플리케이션 전반에서 발생하는 예외를 한 곳에서 통합적으로 처리할 수 있는 방식입니다.
일반적으로 Spring MVC 기반 웹 애플리케이션에서는 컨트롤러나 서비스 계층에서 다양한 예외가 발생할 수 있습니다. 이를 각각의 코드에서 try-catch로 처리하다 보면
- 중복 코드가 많아지고
- 예외 메시지나 응답 포맷이 제각각이며
- 유지보수 난이도가 올라갑니다.
👉 이 문제를 해결하기 위해 스프링에서는 @ControllerAdvice (또는 @RestControllerAdvice)와 @ExceptionHandler를 활용하여 예외를 전역적으로 처리할 수 있습니다.
어노테이션 | 설명 |
@ControllerAdvice | 모든 컨트롤러의 예외를 가로채 처리하는 클래스임을 명시 |
@RestControllerAdvice | @ControllerAdvice + @ResponseBody. JSON 형태 응답을 자동으로 처리할 때 사용 |
@ExceptionHandler | 특정 예외 클래스를 처리하는 메서드 지정 |
📌 @ControllerAdvice
@ControllerAdvice는 모든 컨트롤러에 적용되는 전역 설정 클래스임을 나타냅니다.
이 애노테이션이 붙은 클래스는 모든 컨트롤러의 예외를 가로채어 처리할 수 있게 해줍니다.
기능
- 전역 예외 처리 (@ExceptionHandler)
- 전역 바인딩 처리 (@InitBinder)
- 전역 모델 속성 추가 (@ModelAttribute)
사용 예
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public String handleException(Exception e) {
return "error"; // 에러 뷰 이름 반환 (템플릿 기반)
}
}
주의
@ControllerAdvice는 기본적으로 뷰(View) 기반의 MVC 처리에 적합합니다.
즉, JSON을 반환하지 않으며, 일반적인 @Controller처럼 뷰 이름을 반환합니다.
📌 @RestControllerAdvice
@RestControllerAdvice는 @ControllerAdvice에 @ResponseBody가 결합된 버전입니다.
즉, 예외 처리 결과를 JSON 또는 XML로 반환할 때 사용합니다.
기능
- @ControllerAdvice와 동일한 전역 기능 제공
- 단, 응답이 @ResponseBody로 처리되어 REST API에 적합
사용 예
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
return ResponseEntity.status(500).body("서버 오류 발생");
}
}
- 프론트엔드와 JSON 기반 통신할 때 사용
- API 서버 또는 React, Vue 등과 통신하는 백엔드 개발 시 사용
📌 @ExceptionHandler
@ExceptionHandler는 특정 예외가 발생했을 때 실행할 메서드를 지정하는 애노테이션입니다.
이 메서드는 지정된 예외가 발생할 경우 자동으로 호출되어 예외를 처리합니다.
특징
- 하나의 컨트롤러 또는 @ControllerAdvice 클래스 안에서 사용 가능
- 메서드 인자로 예외 객체를 받음
- ResponseEntity, DTO, 문자열, 뷰 이름 등 다양한 형식으로 반환 가능
사용 예
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgument(IllegalArgumentException ex) {
return ResponseEntity.badRequest().body("잘못된 요청입니다.");
}
GlobalExceptionHandler.java 예제
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
// IllegalArgumentException 발생 시 처리
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgument(IllegalArgumentException ex) {
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body("잘못된 요청입니다: " + ex.getMessage());
}
// 그 외 모든 예외 처리
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception ex) {
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("서버 내부 오류가 발생했습니다.");
}
}
위 코드에서는 두 가지 예외를 처리합니다
- IllegalArgumentException: 클라이언트가 잘못된 값을 보낸 경우
- Exception: 그 외 모든 예외
정리
상황 | 어노테이션 | 설명 |
API에서 예외를 JSON으로 응답하고 싶을 때 | @RestControllerAdvice + @ExceptionHandler | 가장 일반적인 조합 |
템플릿 뷰 기반 웹에서 예외를 처리하고 싶을 때 | @ControllerAdvice + @ExceptionHandler | ModelAndView, View 이름 반환 |
특정 컨트롤러 내에서만 예외를 처리하고 싶을 때 | 컨트롤러 내부에 @ExceptionHandler | 전역 설정 없이 개별 처리 |
'개발 | 프로젝트 > Java | Spring' 카테고리의 다른 글
[Spring boot] @Transactional 이란? (0) | 2025.04.08 |
---|---|
[Spring Security] UsernamePasswordAuthenticationFilter Authentication Flow (0) | 2025.03.21 |
[Spring] Spring Security CSS 적용 안되는 오류 (0) | 2025.02.27 |
[Spring] Spring Security (0) | 2025.02.26 |
[Spring] 개방-폐쇄 원칙 (OCP, Open Closed Principle) (0) | 2025.02.18 |