validation AOP 적용하기 [2]

최준호·2022년 11월 20일
0

Spring

목록 보기
44/47
post-thumbnail

📗 validation AOP 적용하기 [2]

지난 validation AOP 적용하기 글에서는 간단하게 aop를 적용해보았는데. 실제로는 api 요청시에 많은 값들을 빼먹을 수가 있다! 그런데 하나씩만 반환해주면 api를 개발하는 개발자 입장에서는 하나씩 고쳐서 테스트해야된다... 이게 엄청 큰 시간 낭비를 불러올 수 있기 때문에! 유효성을 체크하는 에러 반환 코드는 list로 한번에 뿌려주는게 좋을거 같았다.

그래서 수정해보자!

📄 에러 반환 수정하기

⌨️ ValidationError

@AllArgsConstructor
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class Error {
}
@Builder
@Getter
@AllArgsConstructor
public class ValidationError extends Error{
    private String field;
    private String message;
}

먼저 유효성 검사 후 bindingResult에 담긴 에러들을 담을 ValidationError 구조를 잡았다. 에러가 발생한 field와 message를 담아서 보내려고 한다.

⌨️ 에러 반환

위에서 정보를 담은 ValidationError class를 만들었다. 이래야 반환할 때

{
	"error_code" : "code",
  	"message" : "에러 메세지",
  	"errors" : [{}, {}, {} ...]
    }
}

와 같은 구조로 반환이 가능하다.

@Getter
public class ListException extends RuntimeException{
    private List<Error> errors;

    public ListException(String message, List<Error> errors) {
        super(message);
        this.errors = errors;
    }
}

먼저 list를 담을 Exception이 따로 존재하지 않아서 ListException이라는 이름으로 Exception class를 하나 만들어주었다.

@RestControllerAdvice(basePackages = {"com.molu.molu"})
@Slf4j
public class CommonAdvice {

    @ExceptionHandler
    public ResponseEntity<CommonError> illegalArgumentException(IllegalArgumentException e){
        List<Error> errors = new ArrayList<>();
        errors.add(MessageError.builder()
                        .message(e.getMessage())
                        .build());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(
                CommonError.builder()
                        .errorCode(ErrorCode.BAD_REQUEST.CODE)
                        .message(ErrorCode.BAD_REQUEST.MESSAGE)
                        .errors(errors)
                        .build()
        );
    }

    @ExceptionHandler
    public ResponseEntity<CommonError> listException(ListException e){
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(
                CommonError.builder()
                        .errorCode(ErrorCode.BAD_REQUEST.CODE)
                        .message("잘못된 요청. error field 값은 모두 snake 전략으로 변경하여 요청해주세요.")
                        .errors(e.getErrors())
                        .build()
        );
    }
}

그리고 우선은 2개의 exception을 정의 해두었는데. IllegalArgumentException을 통해서 단일 Exception일지라도 리스트에 담아서 반환하도록 주로르 짰다.

이유는 반환하는 스펙을 계속해서 동일하게 유지하기 위해서이다!

그리고 ListException은 애초에 errors라는 list를 가지고 있기 때문에 errors를 반환 받아서 바로 넘겨주면 된다.

잘못된 요청. error field 값은 모두 snake 전략으로 변경하여 요청해주세요. 해당 메세지는 에러를 반환할 때 BindingResult field 값을 그대로 가져오기 때문에 snake로 변경이 안되어서 다음과 같이 안내 문구를 추가했다.
코드 자체를 바꿀수도 있지만 그러면 어떤 코드는 snake case로 어떤 코드는 camle case로 작성되기 때문이다...
이문제를 해결할 방법이 있다면 댓글로 알려주시면 감사하다 ㅜㅜ

테스트 코드를 실행하면 다음과 같이 에러가 잘 반환되는 것을 확인할 수 있다!

실제로 서버를 올려서 확인해봐도 잘 나오는 것도 확인할 수 있다!

profile
코딩을 깔끔하게 하고 싶어하는 초보 개발자 (편하게 글을 쓰기위해 반말체를 사용하고 있습니다! 양해 부탁드려요!) 현재 KakaoVX 근무중입니다!

0개의 댓글