Bean Validation 2

사나이장대산·2024년 11월 14일

Spring

목록 보기
24/26

에러 메세지

Spring의 Bean Validation은 Default로 제공하는 Message들이 존재하고 임의로 수정할 수 있다.

  • Error Message
    1. Bean Validation을 적용하고 BindingResult에 등록된 검증 오류를 확인해보면 오류가 Annotation 이름으로 등록되어 있다.
    • 예시코드
@Data
public class TestDto {

    @NotBlank
    private String stringField;

    @NotNull
    @Range(min = 1, max = 9999)
    private Integer integerField;

}

@Slf4j
@RestController
public class BeanValidationController {

    @PostMapping("/error-message")
    public String beanValidation(
            @Validated @ModelAttribute TestDto dto,
            BindingResult bindingResult
    ) {
				// bindingResult Field Error 출력
        if (bindingResult.hasErrors()) {
            return String.valueOf(bindingResult.getFieldError());
        }

        // 성공시 문자열 반환
        return "회원가입 성공";
    }

}
  • Postman

  1. integerField 는 비워두고 stringField 만 값(”문자열”) 입력
  • 출력결과
     Field error in object 'testDto' on field 'integerField': rejected value [null]; codes [NotNull.testDto.integerField,NotNull.integerField,NotNull.java.lang.Integer,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [testDto.integerField,integerField]; arguments []; default message [integerField]]; default message [널이어서는 안됩니다] ```
    
                   
  • NotNull 오류 코드를 기반으로 MessageCodesResolver 를 통해 메세지 코드 생성

Spring 에서는 오류 메시지 코드관리를 위해 MessageCodesResolver 인터페이스의
구현체인 DefaultMessageCodesResolver를 기본으로 사용한다.

  • 에러 메세지 수정하기
    1. NotNull.Object.fieldName
      • Annotation의 message 속성 사용
        @Data
        public class TestDto {
        
        	@NotBlank(message = "메세지 수정 가능")
        	private String stringField;
        
        }
  • Postman

  1. NotNull.fieldName(MessageSource)
    - 필드명에 맞춘 사용자 정의 Message
  2. NotNull.FieldType(MessageSource)
    - 필드 타입에 맞춘 사용자 정의 Message
  3. NotNull
  • Annotation 자체에 포함된 Default Message
  • 네가지 방법중 Annotation의 message 속성을 사용하여 에러 메세지를 수정하면 된다.

MessageSource란 Spring에서 지원하는 인터페이스로 메세지의 국제화를 위해 사용된다.

Object Error

필드 단위가 아닌 객체 전체에 대한 오류를 나타낸다. 예를들어 두 필드 간의 관계를 검증할 때 ObjectError를 통해 해당 오류를 BindingResult에 기록할 수 있다.

  • @ScriptAssert

    • 코드예시
      • 비밀번호와 비밀번호 확인 필드가 동일한지 검증

        @Data
        @ScriptAssert(lang = "javascript", script = "_this.password === _this.confirmPassword", message = "Passwords do not match")
        public class UserRegistrationDto {
        
            @NotBlank(message = "Password is required")
            private String password;
        
            @NotBlank(message = "Confirm password is required")
            private String confirmPassword;
        }
      • 실제로 @ScriptAssert는 제약사항 때문에 사용하지 않는다.

      • 실무에서는 훨씬 복잡한 Validation들이 필요하지만 대응이 불가능하다.

        ex) 다른 객체끼리의 비교 혹은 DB조회 결과와 비교

      • Object Error의 경우 Java 코드로 직접 Validation 한다.

  • Java 코드로 구현하기

    • 요구사항 : 총 구매 가격이 10000원 이상이여야 한다.
      • price * count ≥ 10000

        @Getter
        @AllArgsConstructor
        public class OrderRequestDto {
        
            @NotNull
            @Range(min = 1000)
            private Integer price;
        
            @NotNull
            @Range(min = 1)
            private Integer count;
        
        }
        
        @Slf4j
        @RestController
        public class BeanValidationController {
        
            @PostMapping("/object-error")
            public String objectError(
                    @Validated @ModelAttribute OrderRequestDto requestDto,
                    BindingResult bindingResult
            ) {
        
                // 합이 10000원 이상인지 확인
                int result = requestDto.getPrice() * requestDto.getCount();
                if (result < 10000) {
                    // Object Error
                    bindingResult.reject("totalMin", new Object[]{10000, result}, "총 합이 10000 이상이어야 합니다.");
                }
                // Error가 있으면 출력
                if (bindingResult.hasErrors()) {
                    log.info("errors={}", bindingResult);
                    return bindingResult.getAllErrors().get(0).getDefaultMessage();
                }
        
                // 성공로직 ...
                return "성공";
            }
            
        }
  • Object Error는 로직으로 구현하면 된다.

  • Postman

@ModelAttribute는 기본 생성자만 있을 때는 setter를 통해 파라미터를 바인딩하고 다른 매개변수를 가진 생성자가 있다면 그 생성자를 이용해서 파라미터 바인딩을 수행한다.

profile
사나이 張大山 포기란 없다.

0개의 댓글