본문 바로가기

Spring/Spring

[Spring] @ExceptionHandler를 이용한 API 예외 처리

반응형

API 예외 처리는 매우 복잡하다.

시스템마다 응답, 스펙도 다르고 단순히 오류 하면을 보여주는 것이 아니라 예외에 따라서 각각 다른 데이터를 출력해야 할 수도 있다. 

BasicErrorController, HandlerExceptionResolver를 직접 구현하는 것으로는 API 예외를 다루는 것은 쉽지 않다.

스프링은 @ExceptionHandler라는 애너테이션을 제공하는데 API 예외처리는 이 기능을 많이 사용한다.

 

1. IllegalArgumentException 처리

@Slf4j
@RestController
public class ApiExceptionV2Controller {

    @ExceptionHandler(IllegalArgumentException.class)
    public ErrorResult illegalExHandler(IllegalArgumentException e) {
        log.error("[exceptionHandler] ex", e);
        return new ErrorResult("BAD", e.getMessage());
    }

    @GetMapping("/api2/members/{id}")
    public MemberDto getMember(@PathVariable("id") String id) {
        if (id.equals("ex")) {
            throw new RuntimeException("잘못된 사용자");
        }

        if (id.equals("bad")) {
            throw new IllegalArgumentException("잘못된 입력 값");
        }
        if (id.equals("user-ex")) {
            throw new IllegalArgumentException("사용자 오류");
        }
        return new MemberDto(id, "hello " + id);
    }


    @Data
    @AllArgsConstructor
    static class MemberDto {
        private String memberId;
        private String name;
    }
}

이 코드를 실행하면 아래와 같은 결과가 나온다. code와 message를 보고 잘 실행된 것 아닌가? 할 수 있겠지만 HTTP 상태 코드를 보면 200 OK 라는 정상 처리 코드가 뜬 것을 확인할 수 있다. 

에러가 발생했는데 200이 뜬 이유는 ExceptionResolver가 예외를 처리하고 정상 흐름으로 바꿨기 때문이다.

하지만 우리가 원하는 것은 예외를 정상흐름으로 바꾸는 것이 아니라 400으로 바꾸는 것이기 때문에 @ResponseStatus를 이용해서 원하는 HTTP 상태 코드를 지정할 수 있다.

@ResponseStatus로 상태코드 바꾸기

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(IllegalArgumentException.class)
public ErrorResult illegalExHandler(IllegalArgumentException e) {
    log.error("[exceptionHandler] ex", e);
    return new ErrorResult("BAD", e.getMessage());
}

 

 

2. ResponseEntity 사용

@ExceptionHandler
public ResponseEntity<ErrorResult> userExHandle(UserException e) {
    log.error("[exceptionHandler] ex", e);
    ErrorResult errorResult = new ErrorResult("USER-EX", e.getMessage());
    return new ResponseEntity<>(errorResult, HttpStatus.BAD_REQUEST);
}

ResponseEntity는 HTTP 메시지 바디에 직접 응답을 보낼 때 응답코드와 더불어 상세한 정보들을 같이 보낼 수 있다.

@ExceptionHandler에서 어떤 Exception 클래스를 잡을지 생략하면 메서드의 파라미터 예외를 사용한다.

여기서는 UserException이 사용된다.

 

3. Exception 예외

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler
public ErrorResult exHandle(Exception e) {
    log.error("[exceptionHandle] ex", e);
    return new ErrorResult("EX", "내부 오류");
}

스프링에서 우선순위는 세밀하고 구체적일수록 높다. Exception은 모든 에러의 최상위이기 때문에 1,2번에서 사용한 예외보다는 우선순위가 낮다. 즉, 여기서는 1,2번에서 잡지 못 한 예외들을 처리한다.

 

출처 : 인프런 - 스프링 MVC 2편 (김영한)

반응형

'Spring > Spring' 카테고리의 다른 글

[Spring] 서블릿 예외 처리 - 인터셉터  (0) 2024.12.05
[Spring] 서블릿 예외 처리 - 필터  (0) 2024.12.05
[Spring] 서블릿 예외 처리 -1  (0) 2024.12.04
[Spring] 스프링 인터셉터  (0) 2024.12.03
[Spring] 서블릿 필터  (2) 2024.12.02