앞서, @Valid 어노테이션과 @Validated 어노테이션을 활용하여 유효성 검사를 수행하는 내용에 대해 포스팅을 작성하였다.
해당 내용에 이어, 유효성 검사에 실패했을 경우 Exception 처리를 하는 방법에 대해 알아보자.
관련 포스팅
[Spring Boot] Validation - 1. @Valid 어노테이션 사용방법
1. 유효성 검사2. @Valid 어노테이션 테스트3. 유효성 검사 어노테이션 [유효성 검사]애플리케이션의 비즈니스 로직이 올바르게 동작하기 위해, 데이터를 사전 검증하는 유효성 검사 작업이 필요
jh4dev.tistory.com
[Spring Boot] Validation - 2. @Validated 어노테이션 사용방법
1. @Valid vs @Validated2. @Validated 검증 그룹 지정하기 이전 포스팅에서, JAVA 에서 지원하는 @Valid 어노테이션에 대해 알아보았으며, 이번 포스팅에서는 스프링에서 지원하는 @Validated 어노테이션 사용
jh4dev.tistory.com
[예외 처리]
@Valid 의 경우, 일반적으로 JSR-303/JSR-380 Bean Validation을 수행할 때 사용되며, 클래스 / 메서드 파라미터 / 또는 메서드 반환 값에 적용될 수 있으며, "javax.validation.ConstraintViolationException"이 발생한다.
@Validated 는, Spring의 유효성 검사 메커니즘을 사용하며, 그룹 기반의 유효성 검사를 지원하며, 주로 서비스 계층에서 메서드 유효성 검사를 수행할 때 사용된다. 또한, 유효성 검사가 실패하면 케이스에 따라 "org.springframework.validation.BindException" 또는 "javax.validation.ConstraintViolationException"이 발생한다.
그러나, @Valid 어노테이션과 @Validated 어노테이션 둘 다 컨트롤러에서 사용되는 경우, 유효성 검사에 실패하면 "org.springframework.web.bind.MethodArgumentNotValidException" 이 발생한다.
따라서, 컨트롤러 단계의 유효성 검사에서 발생하는 예외는, 별도의 Advice 클래스나 컨트롤러 내, 아래와 같은 Exception Handler 를 작성하여 처리할 수 있다.
<ExceptionHandler Sample>
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> validationExceptionHandler(MethodArgumentNotValidException e, HttpServletRequest request){
HttpHeaders responseHeaders = new HttpHeaders();
HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
log.error("Advice 내 validAnnoExceptionHandler() 호출, {}, {}", request.getRequestURI(), e.getMessage());
String message = "Validation failed";
//유효성 검사에서 노출되는 DefaultMessage 가져오기
FieldError fieldError = e.getBindingResult().getFieldError();
if(fieldError != null) {
message = fieldError.getDefaultMessage();
}
Map<String, String> responseMap = new HashMap<>();
responseMap.put("error_type", httpStatus.getReasonPhrase());
responseMap.put("code", "400");
responseMap.put("message", message);
return ResponseEntity.status(httpStatus).body(responseMap);
}
자세히 볼 부분은 11번 라인부터이다.
Exception 인스턴스의 getMessage() 를 확인해보면, 아래와 같이 긴 Exception 메시지가 생성되어 있다.
Validation failed for argument [0] in public org.springframework.http.ResponseEntity<com.springboot.valid.data.dto.ValidatedRequestDto> com.springboot.valid.controller.ValidatedController.checkValidationByValidatedAnnoGroup1(com.springboot.valid.data.dto.ValidatedRequestDto): [Field error in object 'validatedRequestDto' on field 'phoneNumber': rejected value [string]; codes [Telephone.validatedRequestDto.phoneNumber,Telephone.phoneNumber,Telephone.java.lang.String,Telephone]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [validatedRequestDto.phoneNumber,phoneNumber]; arguments []; default message [phoneNumber]]; default message [전화번호 형식이 올바르지 않습니다.]]
[전화번호 형식이 올바르지 않습니다.] 라는 메시지가 클라이언트로 전달되면 좋을 것이다.
따라서, 해당 default message 값을 추출하는 부분이 11번 라인 ~ 15번 라인 내용이다.
스웨거를 통해 테스트해보면, 일목요연하게 필요한 메시지만 Response 로 리턴되는 것을 확인할 수 있다.
'Spring & Spring boot' 카테고리의 다른 글
[Spring Boot] 예외 처리 - 3. CustomException 사용하기 (0) | 2024.08.16 |
---|---|
[Spring Boot] 예외 처리 - 1. ExceptionHandler 사용하기 (0) | 2024.08.15 |
[Spring Boot] Validation - 4. 커스텀 Validation 설정하기 (0) | 2024.08.15 |
[Spring Boot] Validation - 2. @Validated 어노테이션 사용방법 (0) | 2024.08.14 |
[Spring Boot] Validation - 1. @Valid 어노테이션 사용방법 (0) | 2024.08.14 |