Exceptions

2024. 10. 9. 17:44Spring Framework/Web on Servlet Stack

 

@ExceptionHandler는 스프링 MVC에서 발생하는 예외를 처리하는 메서드를 정의할 수 있도록 해줍니다. 이 어노테이션을 사용하면 특정 예외가 발생했을 때 해당 예외를 처리하는 메서드를 지정할 수 있으며, 예외를 처리한 후 적절한 HTTP 응답을 반환할 수 있습니다.

@Controller 또는 @ControllerAdvice 클래스에서 사용되며, 예외가 발생하면 지정된 메서드가 호출됩니다.

기본 개념

  1. 예외 처리: @ExceptionHandler 가 적용된 메서드는 컨트롤러에서 발생한 예외를 처리할 수 있습니다. 이 메서드는 발생한 예외 타입을 아규먼트로 받아 처리할 수 있으며, HTTP 응답을 리턴할 수 있습니다.
  2. 예외 매칭: 예외 처리는 발생한 예외의 상위 클래스나, 중첩된 원인 예외(cause exception)에도 매칭될 수 있습니다.
  3. 우선 순위: 여러 @ExceptionHandler 메서드가 있을 때, 더 구체적인 예외가 먼저 처리됩니다. 기본적으로 최상위 예외가 아닌 구체적인 예외- 예외 클래스의 상속 계층에서 더 하위에 있는 예외가 먼저 처리된다는 의미 -가 우선적으로 처리됩니다.
  4. 전역 예외 처리: @ControllerAdvice는 여러 컨트롤러에 걸쳐 전역적으로 예외를 처리할 수 있도록 도와줍니다.

예시 1: 기본 예외 처리

다음 예시는 IOException이 발생했을 때 이를 처리하는 방법을 보여줍니다.

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.Controller;
import java.io.IOException;

@Controller
public class SimpleController {

    @ExceptionHandler(IOException.class)
    public ResponseEntity<String> handleIOException(IOException ex) {
        // 예외 처리 로직
        return ResponseEntity.status(500).body("IOException occurred: " + ex.getMessage());
    }
}

코드 설명:

  • @ExceptionHandler(IOException.class): IOException이 발생했을 때 이 메서드가 호출됩니다.
  • ResponseEntity: HTTP 응답을 리턴하는 객체로, 여기서는 500 Internal Server Error 상태 코드와 함께 오류 메시지를 리턴합니다.

예시 2: 여러 예외 처리

여러 예외 타입을 한 번에 처리하고 싶을 때, 예외 타입을 배열로 지정할 수 있습니다.

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import java.io.IOException;
import java.rmi.RemoteException;
import java.nio.file.FileSystemException;

@Controller
public class MultiExceptionController {

    @ExceptionHandler({FileSystemException.class, RemoteException.class})
    public ResponseEntity<String> handleFileAndRemoteExceptions(IOException ex) {
        // 여러 예외 처리
        return ResponseEntity.status(500).body("Error: " + ex.getMessage());
    }
}

코드 설명:

  • @ExceptionHandler({FileSystemException.class, RemoteException.class}): 두 가지 예외인 FileSystemExceptionRemoteException을 한 번에 처리합니다.
  • 예외가 발생하면 IOException을 인자로 받아 처리하며, 예외 타입에 맞는 오류 메시지를 반환합니다.

예시 3: 상위 예외 처리

모든 예외를 처리하고 싶을 때, Exception을 아규먼트로 받아 처리할 수 있습니다. 이 경우, 모든 예외가 처리되며, 보다 구체적인 예외보다 낮은 우선순위를 가집니다.

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;

@Controller
public class GlobalExceptionController {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleAllExceptions(Exception ex) {
        return ResponseEntity.status(500).body("An error occurred: " + ex.getMessage());
    }
}

코드 설명:

  • @ExceptionHandler(Exception.class): 모든 예외를 처리하는 메서드입니다. 구체적인 예외가 없다면, 이 메서드가 호출됩니다.

예시 4: 전역 예외 처리 (ControllerAdvice)

@ControllerAdvice는 전역적으로 예외를 처리하는 데 사용됩니다. 이를 사용하면 여러 컨트롤러에 걸쳐 동일한 방식으로 예외를 처리할 수 있습니다.

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ControllerAdvice;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(IOException.class)
    public ResponseEntity<String> handleIOException(IOException ex) {
        return ResponseEntity.status(500).body("Global IOException: " + ex.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleGeneralException(Exception ex) {
        return ResponseEntity.status(500).body("General error occurred: " + ex.getMessage());
    }
}

코드 설명:

  • @ControllerAdvice: 이 클래스는 모든 컨트롤러에 적용되어 전역적으로 예외를 처리합니다.
  • 두 가지 @ExceptionHandler 메서드가 각각 IOException과 모든 Exception을 처리합니다.

추가 기능: 메서드 아규먼트

@ExceptionHandler 메서드는 다양한 추가 아규먼트를 받을 수 있습니다. 이러한 인자들은 예외 처리 시 더 많은 정보를 제공합니다.

사용할 수 있는 아규먼트:

  • Exception: 발생한 예외 객체를 인자로 받아 처리할 수 있습니다.
  • HandlerMethod: 예외가 발생한 컨트롤러 메서드에 접근할 수 있습니다.
  • WebRequest 또는 NativeWebRequest: 요청 파라미터나 세션 속성 등에 접근할 수 있습니다.
  • HttpServletRequest, HttpServletResponse: 직접적인 서블릿 요청 또는 응답 객체를 사용할 수 있습니다.
  • Principal: 현재 인증된 사용자에 접근할 수 있습니다.

예시 5: 추가  아규먼트 사용

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import jakarta.servlet.http.HttpServletRequest;

@Controller
public class CustomExceptionHandler {

    @ExceptionHandler(IOException.class)
    public ResponseEntity<String> handleIOException(IOException ex, WebRequest request, HttpServletRequest servletRequest) {
        String requestUrl = servletRequest.getRequestURL().toString();
        String message = "IOException at " + requestUrl + ": " + ex.getMessage();
        return ResponseEntity.status(500).body(message);
    }
}

코드 설명:

  • WebRequest: 요청 파라미터나 세션에 접근할 수 있습니다.
  • HttpServletRequest: 요청 URL 같은 서블릿 관련 데이터를 가져올 수 있습니다.

리턴값 처리

@ExceptionHandler 메서드는 다양한 형태의 리턴값을 가질 수 있습니다.

  • ResponseEntity: HTTP 상태 코드와 함께 응답을 리턴합니다.
  • String: 뷰 이름을 리턴할 수 있으며, ViewResolver에 의해 해석됩니다.
  • ModelAndView: 뷰와 모델을 함께 리턴할 수 있습니다.
  • void: 리턴값이 없을 경우, 메서드가 응답을 처리했다고 간주됩니다.

요약

  • @ExceptionHandler는 특정 예외가 발생했을 때 이를 처리하는 메서드를 정의할 수 있습니다.
  • 여러 예외를 처리할 수 있으며, 구체적인 예외가 우선적으로 처리됩니다.
  • 전역 예외 처리는 @ControllerAdvice를 통해 모든 컨트롤러에 적용될 수 있습니다.
  • 다양한 인자를 사용하여 예외 처리 시 추가 정보를 받을 수 있으며, 리턴값로 다양한 형태의 응답을 생성할 수 있습니다.

이 방식은 애플리케이션에서 발생하는 예외를 효과적으로 관리하고, 사용자에게 적절한 오류 응답을 제공하는 데 매우 유용합니다.

참고 : [https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-exceptionhandler.html]

'Spring Framework > Web on Servlet Stack' 카테고리의 다른 글

@RequestParam  (0) 2024.10.09
Controller Advice  (0) 2024.10.09
Validation  (0) 2024.10.09
@InitBinder  (0) 2024.10.09
Model  (0) 2024.10.09