Post

@RestControllerAdvice - 1

@RestControllerAdvice - 1


에러는 어떻게 조금 더 편하게 처리할 수 있을까


프로젝트를 진행하면서 제일 큰 고심과 역경은 애플리케이션을 실행하였을 때 IDE 로그에 빨간 글씨와 여러 코드줄이 줄줄히 등장하면 두통이 엄청 올 것이다.
그리고 이러한 문제들을 처리하기 위해서는 로그들을 읽어보고 여러 코드를 지우고 바꿔보거나 검색을 하는 등 최악의 상황이면 해결이 하지 못해 상심이 크기도 하다.
이러한 문제점을 조금이나마 해결할 수 있게 방법을 찾을 수 있게끔 개발자들은 다양한 예외처리를 설정해둔다.
그래서 이번에는 @RestControllerAdvice에 대해서 학습을 해보자

@RestControllerAdvice

Json 형태로 객체 데이터를 반환할 수 있으며, Spring MVC의 컨트롤러 @ControllerRestuful 웹서비스의 컨트롤러의 @RestController그리고 이 컨트롤러에 발생할 수 있는 예외를 처리하는 어노테이션이 @RestControllerAdvice 이다.
그렇다면 클래스를 만들어서 RestControllerAdvice선언하면 끝인가?


@ExceptionHandler

이 어노테이션은 RestControllerAdvice를 정의한 메서드에 선언하여 자신이 지정한 해당 예외가 발생하였을 때, 본인이 지정한 로직으로 처리할 수 있다.

  • 예시 advice_before

Swagger UI에 파라미터에 없는 값을 전송하였을 때, 출력되는 에러 코드이다.
어디서에서 어떤 에러가 발생하였는지 한눈에 보기 불편하고 가독성도 좋지 않다. 그렇다면 이러한 에러를 처리하기 편하게 @RestControllerAdvice를 설계해보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@RestControllerAdvice
@Log4j2
public class CustomRestAdvice {

    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.EXPECTATION_FAILED)
    public ResponseEntity<Map<String,String>>addBindHandler(BindException e){

        Map<String, String> errorMap = new HashMap<>();

        if(e.hasErrors()){

            BindingResult bindingResult = e.getBindingResult();
            bindingResult.getFieldErrors().forEach(fieldError -> {
                errorMap.put(fieldError.getField(), fieldError.getCode());
            });
        }
        return ResponseEntity.badRequest().body(errorMap);
    }



실제로 동작 여부를 확인하기 위해서 Controller의 코드들을 수정해보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Operation(summary = "Reply 등록", description = "POST 방식으로 등록")
    @PostMapping(value = "/", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Map<String, Long>> register(@Valid @RequestBody ReplyDTO replyDTO,
                                                      BindingResult bindingResult)throws BindException{

        Map<String, Long> resultMap = new HashMap<>();

        if(bindingResult.hasErrors()){
            throw new BindException(bindingResult);
        }

        resultMap.put("rno",111L);

        return ResponseEntity.ok(resultMap);
    }


@RestControllerAdvice 제대로 설계하였다면 컨트롤러에서 발생하는 예외에 대해 JSON과 같은 응답 메세지를 생성해서 보낼 수 있다.
handleBindException()은 컨트롤러에서 BindException이 던져지는 경우 이를 이용해 JSON 메시지와 400에러를 전송하게 된다.
다시 빈 혹은 잘못된 값을 전송하게 되면 내가 지정한 에러 메세지를 전송 받을 수 있다.

advice_after




이런식으로 @ExceptionHandler뿐만 아니라 여러 예외 처리를 할 수 있는 기술들이 많으니 활용하면 유지보수하기 편리하지 않을까 생각하면서 더욱 전진해보자

This post is licensed under CC BY 4.0 by the author.