개발 | 프로젝트/Java | Spring

[Spring Boot] GlobalExceptionHandler 예외 처리

seulll 2025. 4. 6. 15:08

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 전역 설정 없이 개별 처리