Spring Boot 예외처리

kangking·2024년 7월 4일
0

Spring Boot

목록 보기
9/10

예외(Exception) 처리

기존 자바의 방식대로 예외를 처리하는 방법은 아래의 2가지 방법이 있다.

  • throws로 메소드 호출자에게 처리를 위임

  • try-catch문으로 최종처리

문제점

전체 코드에서 예외가 발생하는 부분마다 예외처리 코드가 작성되어있어 가독성을 해칠 뿐만 아니라 유지 관리 및 수정도 힘들어진다.

Advice가 처리하는 예외는 Spring에서 throws를 진행하다가 Dispatcher Servlet호출 이후(Spring Context)에서 처리된다. 그렇다면 Security와 같이 Dispatcher Servlet호출 전(Filter) 단계에서 예외가 발생하면 어떻게 해야할까?

  • Filter는 직접 예외처리 클래스를 만들어 호출해서 사용하던지 try-catch로 처리해야한다.

Spring에서의 예외처리

클래스를 하나 만들고 @ControllerAdvice와 같은 어노테이션을 사용해서 @Controller에서 발생한 모든 예외를 해당 클래스로 모아 한꺼번에 처리한다.

이 때 하나의 처리 클래스만 사용하면 한 클래스에서 과도하게 많은 예외를 처리해야 할 수도 있기 때문에 기능이나 예외 종류별로 만들어서 모아 처리한다.

  • Validation도 예외를 발생시켜 처리하는 메커니즘으로 동작하기 때문에

예시 코드

내가 작업하는 서비스나 코드의 상황에 맞게 구조와 처리를 커스텀 해야한다.
아래의 예시는 간단한 개념에 대한 예시로 실제로 사용하려면 더 디테일하게 사용해야 한다.

  • 컨트롤러에서 발생한 모든종류의 예외를 동일하게 글로벌 처리하는 Handler

    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler(Exception.class)
        public ResponseEntity<String> handleException(Exception e){
            System.out.println("글로벌 처리");
            e.printStackTrace();
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
  • 0으로 나눴을 때 처리하는 메소드

    	@ExceptionHandler(ArithmeticException.class)
        public ResponseEntity<String> handleArithmeticException(ArithmeticException e){
            System.out.println("0으로 나눌 수 없습니다.");
            e.printStackTrace();
            return ResponseEntity.badRequest().body(e.getMessage());
        }
  • 규칙에 맞지 않게 들어온 데이터를 처리하는 메소드

        @ExceptionHandler(MethodArgumentNotValidException.class)
        public ResponseEntity<Map<String,String>> handleMethodException(MethodArgumentNotValidException e){
            System.out.println("입력값이 잘못 되었습니다");
            Map<String,String> errors = new HashMap<>();
            e.getBindingResult().getAllErrors().forEach((error)
            -> {
                String filedName = ((FieldError)error).getField();
                String errorMessage = error.getDefaultMessage();
                errors.put(filedName, errorMessage);
            });
    
            return ResponseEntity.badRequest().body(errors);
        }

    validation이 위의 예외처리를 자동으로 생성한 것이기 때문에 직접 커스텀해서 만들 수도 있다. 동작은 아래와 같이 동일하다.

profile
하루하루 의미있게

0개의 댓글