본문 바로가기
Spring

전역예외처리

by 혀눅짱 2023. 10. 5.

SpringBoot를 사용하여 공부하면서 생각해보니 예외처리에 대한 로직을 따로 찾아보거나 한적이 없어서 한번 찾아보려고 한다.

유튜브에 예외처리 강의가 있어 참고하였다.

 

스프링 부트의 예외처리 방식은 크게 2가지가 존재한다.

  1. @ControllerAdvice(@RestControllerAdvice)를 통한 모든 Controller에서 발생할 수 있는 예외처리
  2. @ExceptionHandler를 통한 특정 Controller의 예외처리

근데 각컨트롤러 마다 예외처리 메소드를 따로두면.. 딱히 효율적일 것 같진 않다는 생각이 든다. 

 

다음은 예시다.

 

1번케이스에 대한 예시이다.

 

@RestControllerAdvice
@Slf4j
public class ExceptionController {

    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<Map<String,String>> ExcetionHandler(Exception e){
        log.info("전역 컨트롤러에서 예외처리");
        HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
        Map<String,String> resultMap = new HashMap<>();
        resultMap.put("error type", httpStatus.getReasonPhrase());
        resultMap.put("code","400");
        resultMap.put("message","에러발생");

        return ResponseEntity.status(httpStatus).body(resultMap);
    }

    @ExceptionHandler(value = NullPointerException.class)
    public String nullHandler(Exception e){
        return "null";
    }
}

 

@PostMapping("/exception")
public void exceptionTest() throws Exception {
    throw new Exception();
}

post방식으로 예외를 발생시키는 요청을 하나 추가한 후 포스트맨으로 요청을 날려보았다.

 

{
"code": "400",
"error type": "Bad Request",
"message": "에러발생"
}
 
오류가 나지 않고 포스트맨에 해당 json형태의 오류 속성들이 리턴되었다.
 
그렇다면 해당 오류를 처리하는 ExceptionHandler를 요청하는컨트롤러 내부 메소드에도 작성한다면 어떻게될까 테스트해본다.
 
 
@ExceptionHandler(value = Exception.class)
public ResponseEntity<Map<String,String>> ExcetionHandler(Exception e){
    log.info("지역 컨트롤러에서 예외처리");
    HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
    Map<String,String> resultMap = new HashMap<>();
    resultMap.put("error type", httpStatus.getReasonPhrase());
    resultMap.put("code","400");
    resultMap.put("message","에러발생");

    return ResponseEntity.status(httpStatus).body(resultMap);
}

콘솔에 찍힌 로그에서 지역 컨트롤러에서 선언된 핸들러를 탄것을 확인 할 수 있다.

즉 동일 예외(예제에선 Exception.class)에선 컨트롤러 내부에서 선언된 핸들러가 우선순위를 갖는다.

 

 

여기서 @ControllerAdvice는 빈으로 관리되기도 한다고 한다. 또한 주의할 점은, 프로젝트에 하나의 @ControllerAdvice만 관리하는 것을 권장한다고 한다. 여러 개를 사용하려면, basePackageClasses 및 basePackages와 같은 Selector를 사용해야하기 때문인데 이렇게 되면, OR연산을 통해 올바른 Selector를 찾아야한다. 해당 과정은 런타임 시점에 수행되므로, 많아질 수록 성능에 영향을 미치고 복잡성이 올라갈 수 있다.

 

'Spring' 카테고리의 다른 글

Redis와 SpringBoot 연동  (1) 2023.11.20
@Conditional과 @AutoConfiguration  (0) 2023.11.06
SpringBoot AutoConfiguration  (0) 2023.11.06
SpringBoot와 웹서버  (0) 2023.10.31
인터셉터 설정  (0) 2023.10.05