본문 바로가기
Spring/10. rest-api

RestControllerAdvice란?

by 989898 2025. 3. 17.

📌 RestControllerAdvice란?

@RestControllerAdvice는 Spring에서 제공하는 어노테이션으로, 전역적으로 예외를 처리하기 위해 사용됩니다. 이는 @ControllerAdvice와 @ResponseBody를 결합한 형태로, 모든 컨트롤러에서 발생하는 예외를 JSON 형태로 응답하도록 설계되었습니다. 🌟

 

간단히 말하면:

  • @ControllerAdvice + @ResponseBody의 조합입니다.
  • 서버에서 발생한 예외를 전역적으로 감지하고, 그 결과를 JSON과 같은 형태로 클라이언트에게 반환할 때 사용합니다.

📌 @RestControllerAdvice의 특징

  • 전역 예외 처리: 애플리케이션 전체에서 발생하는 예외를 한 곳에서 관리할 수 있습니다.
  • REST API 전용: 반환값이 자동으로 JSON 또는 XML 형태로 변환됩니다. (별도의 @ResponseBody 어노테이션이 필요 없음)
  • REST API 환경에서 주로 사용되며, 클라이언트가 API 호출 시 발생한 예외를 JSON 형태로 명확하게 전달받을 수 있습니다.

📌 주요 특징

  1. 🌍 전역 예외 처리: 특정 컨트롤러 또는 애플리케이션 전체에서 발생하는 예외를 한 곳에서 처리할 수 있습니다.
  2. 📜 JSON 응답 지원: @ResponseBody가 포함되어 있어 예외 처리 결과를 JSON 형태로 반환합니다.
  3. ⚙️ AOP 기반: 공통 관심사(cross-cutting concerns)를 분리하여 코드 중복을 줄이고 유지보수성을 높입니다.

📌 코드 해석

public class CommonException {
    private final String message;
    private final int statusCode;
    private final String uri;

    public CommonException(String message, int statusCode, String uri) {
        this.message = message;
        this.statusCode = statusCode;
        this.uri = uri;
    }

    public String getMessage() {
        return message;
    }

    public int getStatusCode() {
        return statusCode;
    }

    public String getUri() {
        return uri;
    }
}
@RestControllerAdvice(basePackageClasses = {BlogController.class})
public class BlogAdvice {

    @ExceptionHandler(BlogNotFoundException.class)
    public ResponseEntity<CommonException> blogNotFoundExceptionHandler(
            BlogNotFoundException blogNotFoundException,
            HttpServletRequest request
    ){

        CommonException commonException = new CommonException(
                blogNotFoundException.getMessage(),
                HttpStatus.NOT_FOUND.value(),
                request.getRequestURI()
        );

        return  ResponseEntity
                .status(HttpStatus.NOT_FOUND)
                .body(commonException);
    }

    @ExceptionHandler(AlreadyExistBlogFidException.class)
    public ResponseEntity<CommonException> AlreadyExistBlogFidExceptionHandler(
            AlreadyExistBlogFidException alreadyExistBlogFidException,
            HttpRequest request
    ){

        CommonException commonException = new CommonException(
                alreadyExistBlogFidException.getMessage(),
                HttpStatus.CONFLICT.value(),
                request.getURI().toString()
        );

        return ResponseEntity
                .status(HttpStatus.CONFLICT)
                .body(commonException);
    }


}

1️⃣ 클래스 정의

@RestControllerAdvice(basePackageClasses = {BlogController.class})
public class BlogAdvice {
 
  • @RestControllerAdvice: 이 클래스는 전역적으로 예외를 처리하며, JSON 응답을 반환합니다.
  • basePackageClasses: BlogController 클래스만 대상으로 설정하여 해당 컨트롤러에서 발생하는 예외를 처리합니다.

2️⃣ BlogNotFoundException 처리

 
  • @ExceptionHandler(BlogNotFoundException.class): BlogNotFoundException이 발생했을 때 이 메서드가 호출됩니다.
  • 매개변수 설명:
    • BlogNotFoundException: 발생한 예외 객체.
    • HttpServletRequest: 요청 정보를 가져오기 위해 사용됩니다 (예: 요청 URI).
  • 응답 구성:
    • 예외 메시지, 상태 코드(404), 요청 URI를 포함한 CommonException 객체를 생성.
    • ResponseEntity.status(HttpStatus.NOT_FOUND).body(commonException)를 통해 상태 코드와 본문을 반환.

3️⃣ AlreadyExistBlogFidException 처리

 
  • @ExceptionHandler(AlreadyExistBlogFidException.class): AlreadyExistBlogFidException이 발생했을 때 호출됩니다.
  • 매개변수 설명:
    • AlreadyExistBlogFidException: 발생한 예외 객체.
    • HttpRequest: 요청 정보를 가져오기 위해 사용됩니다 (예: 요청 URI).
  • 응답 구성:
    • 예외 메시지, 상태 코드(409), 요청 URI를 포함한 CommonException 객체 생성.
    • ResponseEntity.status(HttpStatus.CONFLICT).body(commonException)를 통해 상태 코드와 본문을 반환.

📌 RestControllerAdvice의 장점

  1. ✅ 일관성 있는 에러 응답: 모든 컨트롤러에서 동일한 형식의 에러 응답을 반환할 수 있습니다.
  2. 🌍 전역 관리: 개별 컨트롤러에 중복된 예외 처리 코드를 작성하지 않아도 됩니다.
  3. 📜 JSON 응답 자동화: 별도의 변환 작업 없이 JSON 형태로 에러 정보를 클라이언트에 전달합니다.

📌 사용 예시

✅ 1. 기본적인 사용법

@RestControllerAdvice
public class GlobalRestExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Map<String, Object>> handleException(Exception e) {
        Map<String, Object> response = new HashMap<>();
        response.put("error", e.getMessage());
        response.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
    }
}
 
 
  • 위 코드는 모든 타입의 예외(Exception)가 발생했을 때 JSON 형태로 에러 메시지와 상태 코드를 클라이언트에게 반환합니다.

 예외가 발생했을 때 반환되는 JSON 형태

{
  "error": "예외 메시지 내용",
  "status": 500
}
 
 

 설명

  • "error": 예외 객체(Exception)의 메시지(e.getMessage())가 들어갑니다.
  • "status": HTTP 상태 코드로, 여기서는 500 (Internal Server Error)를 의미합니다.

 실제 예시

예를 들어, 서버에서 다음과 같은 예외가 발생했다고 가정해봅시다:

throw new RuntimeException("서버에서 에러가 발생했습니다.");
 
 

이 경우 클라이언트가 받게 되는 JSON 응답은 다음과 같습니다:

{
  "error": "서버에서 에러가 발생했습니다.",
  "status": 500
}
 
 

✅ 2. 특정 예외 처리 (예: 유효성 검증 실패)

@RestControllerAdvice
public class ValidationExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, Object>> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, Object> errors = new HashMap<>();

        ex.getBindingResult().getFieldErrors().forEach(error ->
            errors.put(error.getField(), error.getDefaultMessage())
        );

        return ResponseEntity.badRequest().body(errors);
    }
}
 
 
  • 유효성 검증 실패 시 각 필드의 오류 메시지를 JSON 형태로 반환합니다.

 유효성 검증 실패 시 반환되는 JSON 형태

{
  "username": "사용자 이름은 필수입니다.",
  "email": "올바른 이메일 형식을 입력해주세요."
}
 
 

 설명

  • JSON의 각 키(key)는 유효성 검증에 실패한 필드의 이름입니다.
  • 각 값(value)은 해당 필드에 대한 유효성 검증 실패 메시지입니다.

 실제 예시

예를 들어, 다음과 같은 DTO 클래스가 있다고 가정해봅시다:

public class UserRequest {

    @NotBlank(message = "사용자 이름은 필수입니다.")
    private String username;

    @Email(message = "올바른 이메일 형식을 입력해주세요.")
    private String email;

    // getters, setters 생략
}
 
 

클라이언트가 잘못된 데이터를 전송한 경우:

{
  "username": "",
  "email": "invalid-email-format"
}
 
 

이 경우 클라이언트가 받게 되는 JSON 응답은 다음과 같습니다:

{
  "username": "사용자 이름은 필수입니다.",
  "email": "올바른 이메일 형식을 입력해주세요."
}
 
 

📌 @ControllerAdvice와의 차이점

특징 @ControllerAdvice @RestControllerAdvice
반환 형식 주로 HTML 뷰 반환 JSON/XML 데이터 반환
용도 MVC 웹 애플리케이션 REST API 전용
추가 어노테이션 필요 여부 @ResponseBody 필요 (JSON 반환 시) 자동으로 JSON/XML 변환
 
  • 즉, REST API 환경에서는 일반적으로 @RestControllerAdvice를 사용하는 것이 더 편리합니다.

📌 결론

  • @RestControllerAdvice는 REST API 환경에서 전역적인 예외 처리를 위해 사용됩니다.
  • 서버에서 발생한 예외를 감지하고, 이를 JSON이나 XML 형태로 클라이언트에게 명확하게 전달할 수 있습니다.
  • RESTful 서비스를 개발할 때 매우 유용한 어노테이션입니다.