부자 되기 위한 블로그, 머니킹

스프링 오류 종류

Error

시스템에 비정상적인 상황이 발생했을 경우에 사용한다. 주로 자바 VM에서 발생하는 것이다. OutOfMemoeryError나 ThreadDeath 같은 것들이 대표적인 예이다.

 

 

Exception

  • CheckedException
    • RuntimeException class를 상속하지 않음
    • Transaction으로 Rollback이 진행 안됨
    • 프로그램 상 의도한 예외가 아니기 때문에 반드시 예외를 처리하는 코드를 함께 작성해야한다.
    • IOException이나 SQLException 등과 같은 예외가 있다.
  • Uncehcked Exception
    • RuntimeException class를 상속받음
    • Transaction으로 Rollback이 진행됨
    • 반드시 예외를 체크하지 않아도 되는 경우에 사용함
    • NullPoinsterException(오브젝트 할당 x), IllegalArgumentException(허용되지 않는 값을 사용해서 메소드를 호출할 때 )
    • 예외가 생겨도 시스템 레벨에서 알아서 처리해 줄 것이여서 엄청 신경쓰지는 않는다.
  • Application Exception
    • 시스템 또는 외부 예외상황이 원인이 아니라 애플리케이션 자체 로직으로 의도적인으로 발생시킨 예외
    • 이럴 경우 반드시 catch를 사용하여 조치를 취하도록 요구한다.
    • 해당 예외는 시스템 레벨로 가지 않고 비지니스 메소드에서 예외를 사용하여 클라이언트에 알림 ( 시스템에서는 정상적인 흐름 처리 )

 

Transaction

Transaction의 Rollback이 uncheckedException에서만 Rollback 되는 이유는 checkedException은 반드시 처리되어야 하는 예외이기 때문이다.

 

 

Exception 처리 방법

  • 예외 복구 : 예외 상황을 파악하고 문제를 해결해서 정상 상태로 돌려놓는 것
    • 사용자에게 상황 알려주고 다른 경로로 이용하게 하는 것
  • 예외처리 회피 : 예외 처리를 자신을 호출한 쪽으로 던지는 것
    • throw를 던져서 catch문에서 처리하도록 하는 것
  • 예외 전환 : 예외를 적절한 예외로 전환해서 메소드 밖으로 던지는 것
    • 예외를 적절한 다른 예외로 전환하여 throw 하는 것

 

 

스프링 View Controller 오류 처리

Normal Controller ( View )

  1. WAS(/error-ex, dispatchType=REQUEST) -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러
  2. WAS(여기까지 전파) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러(예외발생)
  3. WAS 오류 페이지 확인
  4. WAS(/error-page/500, dispatchType=ERROR) -> 필터(x) -> 서블릿 -> 인터셉터(x) ->
    컨트롤러(/error-page/500) -> View

 

 

View Error Page 등록

resources/templates/error/4xx.html resources/templates/error/404.html resources/templates/error/500.html

에러 발생시 가장 우선순위가 높은 경로이며 만약 해당 경로에 view 파일이 없을시에는 정적리소스(static,public), 또는 error.html 파일을 찾는다.

 

 

스프링 Rest Controller 오류 처리

@ExceptionHandler

Controller 내 메소드로 정의도며 해당 Controller에서 발생하는 에러를 받아 처리한다.

@RestController
public class ExceptionTestController {

    @ExceptionHandler
    public Object handlerException(Exception e) {
        System.out.println("ExceptionTestController.handlerException");
        return "error";
    }

    // HandlerExceptionResolver에 의해 등록한 형태로 매핑하여 처리
    @ExceptionHandler(value = {IOException.class, FileNotFoundException.class})
    public Object notFoundHandler(Exception e) {
        return "notfound";
    }

    @ExceptionHandler(value = TimeoutException.class)
    public Object timeoutExceptionHandler(Exception e) {
        System.out.println("ExceptionTestController.timeoutExceptionHandler");
        return "error";
    }

}

value 값 지정을 통해 특정 예외를 지정할 수 도 있다. 해당 컨트롤러안에서의 예외만을 처리한다.

 

 

 

@ControllerAdvice

모든 Controller에서 발생할 수 있는 예외를 잡아 처리한다. DispatcherServlet에서 실행하다가 에러가 발생하면 handlerExceptionResolvers가 실행되는 구조이다.

@RestControllerAdvice
public class GlobalExceptionHandler {

    //@ControllerAdvice로 정의된 빈이 주입된 handlerExceptionResolvers가 실행되는 구조입니다.

    @ExceptionHandler(java.lang.IllegalArgumentException.class)
    public ResponseEntity IllegalArgumentException(IllegalArgumentException illegalArgumentException) {
        return new ResponseEntity(HttpStatus.OK);
    }
}

 

 

사용자 설정 Exception

상위 Exception을 상속받는 형식으로 사용하면 된다.

public class NoDeliveryException extends DataAccessException {

    public NoDeliveryException(String msg) {
        super(msg);
    }
    public NoDeliveryException(String msg, Throwable cause) {
        super(msg, cause);
    }
}

 

Controller

@Controller
@RequestMapping("/exception")
public class ExceptionViewController {

    @ExceptionHandler(NoDeliveryException.class)
    public String noDelivery(NoDeliveryException e, Model model) {
        model.addAttribute("exception", e);
        return "deliver";
    }

    @GetMapping("/deliver")
    public String exceptionTest() {
        throw new NoDeliveryException("티켓 모두 소진됨");
    }

}

 

 

html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>티켓 에러</title>
</head>
<body>

    <h1>티켓관련 에러</h1>
    <p class="alert alert-danger" th:text="${exception.message}"></p>
</body>
</html>

 

결과