2023-10-18-TIL
Today I Learned
Custom Error Message with @Size
@Size는 Bean Validation의 제약 애너테이션으로, 값의 크기가 min과 max 사이(양 끝 포함)인지 검사한다. Jakarta Bean Validation Javadoc에 따르면 문자열이면 길이를, 컬렉션과 맵이면 크기를, 배열이면 길이를 본다. null은 유효한 값으로 취급한다. 그래서 필수 값이면서 길이도 제한하려면 @NotNull이나 @NotBlank를 함께 붙여야 한다.
기본 메시지는 {jakarta.validation.constraints.Size.message}라는 템플릿이다. message 속성에 원하는 문구를 넣으면 바꿀 수 있고, 문구 안에서 {min}, {max}처럼 애너테이션 속성 값을 참조할 수 있다.
1
2
3
4
5
public record SignUpRequest(
@NotBlank
@Size(min = 2, max = 20, message = "닉네임은 {min}자 이상 {max}자 이하로 입력해 주세요.")
String nickname
) {}
Hibernate Validator 레퍼런스는 이런 메시지 템플릿을 ValidationMessages.properties 리소스 번들에서 찾아 값을 채운다고 설명한다. 문구를 코드에 직접 쓰는 대신 message = "{nickname.size}"처럼 키만 두고 번들에 문구를 모으면 다국어 처리와 수정이 쉬워진다.
메시지를 정했으면 응답으로 내려 주는 부분도 필요하다. 컨트롤러 메서드의 @Valid @RequestBody 인자가 검증에 실패하면 Spring은 MethodArgumentNotValidException을 던진다(Spring Javadoc). 이 예외는 BindingResult를 담고 있어서 getFieldErrors()로 필드별 오류와 메시지를 꺼낼 수 있다. 링크한 글들처럼 @RestControllerAdvice에서 이 예외를 받아 필드 이름과 메시지를 응답 본문으로 바꾸는 방식이 일반적이다.
1
2
3
4
5
6
7
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handle(MethodArgumentNotValidException e) {
Map<String, String> errors = new HashMap<>();
e.getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage()));
return ResponseEntity.badRequest().body(errors);
}
- https://www.baeldung.com/global-error-handler-in-a-spring-rest-api
- https://salithachathuranga94.medium.com/validation-and-exception-handling-in-spring-boot-51597b580ffd
댓글
아직 댓글이 없습니다