프로그래밍 노트/SPRING BOOT

Validation 알아보기_1(Hibernate Validator)

깡냉쓰 2021. 1. 9. 15:27
728x90
반응형

Vlidation은 데이터를 검증할 때 사용한다.

validation1

데이터 검증으 여러 계층에 걸쳐서 이루어지게 되는데, 이 과정으로 인해 문제점이 발생할 수 있다.

  1. 코드의 중복
  2. 검증로직 불일치로 인한 오류

validation2

이 문제를 해결하기 위해서 Java에서는 2009년부터 Bean Validation이라는 데이터 유효성 검사 프레임워크를 제공하고 있다. Bean Validation은 다양한 제약을 어노테이션을 사용하여 데이터를 검증할 수 있게 하였다.

Hibernate Validator

Hibernate Validator는 Bean Validation 명세에 대한 구현체이다.

제약조건 작성

어노테이션을 사용하여 제약조건을 작성할 수 있다.

@Builder
@Getter
public class User {
    @Length(max = 65)
    @NotEmpty(message = "이름은 필수 입니다.")
    private String name;
    @PositiveOrZero(message = "나이는 0 이상이어야 합니다.")
    private int age;
}

이런식으로 작성할 수 있겠다.

유효성 검사

제약조건에 대한 유효성 검사는 javax.validation.Validator를 사용해 이루어진다.
ValidatorFacotry를 사용하여, Validator를 가져올 수 있다.

@Test
void test_validation(){
    final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
    // name 이 빈값
    final User user = User.builder().name("").age(30).build();

    final Set<ConstraintViolation<User>> constraintViolations = validator.validate(user);

    // ConstraintViolation 에 실패 정보가 담긴다.
    assertEquals(1, constraintViolations.size());
        // 이름은 필수 입니다.
    log.debug("{}", constraintViolations.iterator().next().getMessage());
}

validate() 를 사용해서 빈의 유효성 검증을 실행한다.
결과 값(제약조건을 위반한 내용)은 ConstraintVolation 인터페이스로 반환된다.

그룹핑된 제약조건

Bean Validation 1.1 부터 포함된 내용으로, 그룹을 사용하여 유효성검증을 수행할 수 있다.
그룹에 해당하는 인터페이스를 생성하고, groups에 해당 그룹을 넣으면 된다.

 public interface UserGroups {
    interface Admin {}
}
@Builder
@Getter
public class User {
    @Length(max = 65)
    @NotBlank(message = "이름은 필수 입니다.")
    private String name;
    @PositiveOrZero(message = "나이는 0 이상이어야 합니다.")
    @Min(value = 25, message = "관리자는 나이가 25세 이상이어야 합니다.", groups = UserGroups.Admin.class)
    private int age;

    @NotBlank(message = "관리자는 관리자 번호가 있어야 합니다.", groups = UserGroups.Admin.class)
    private String adminNumber;
}

groups로 지정되지 않은 제약조건은 기본 그룹세트(javax.validation.groups.Default)에 포함되어 동작하게 된다. validate()에 검사하고 싶은 그룹을 같이 넘기게 되면 해당 그룹에 대한 유효성 검사를 하게 된다.

@Test
void test_groupValidation(){
    final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

    final User user = User.builder().name("").age(30).adminNumber("1234").build();

    final Set<ConstraintViolation<User>> constraintViolations1 = validator.validate(user, UserGroups.Admin.class);
    assertEquals(0, constraintViolations1.size());
    final Set<ConstraintViolation<User>> constraintViolations2 = validator.validate(user, Default.class, UserGroups.Admin.class);
    assertEquals(1, constraintViolations2.size());
}

그 외..

계단식 유효성검사

@Valid를 추가해줘야 User(investor)에 대한 유효성 검사도 하게된다.

@Builder
@Getter
public class Investment {
    @NotBlank(message = "상품번호는 필수 입니다.")
    private String productNo;
    @NotNull(message = "투자자가 있어야 합니다.")
    @Valid
    private User investor;
}

컨테이너 요소 유효성 검사

Iterable, Map ...

@Builder
@Getter
public class Investment {
    @NotBlank(message = "상품번호는 필수 입니다.")
    private String productNo;
    @NotEmpty(message = "운영자는 한명 이상이어야 합니다.")
    private List<
            @NotNull(message = "운영자는 null 이 아니여야 합니다.")
            @ConvertGroup(to = UserGroups.Admin.class)
            @Valid User> operatorList;
}

참고) https://medium.com/@gaemi/java-%EC%99%80-spring-%EC%9D%98-validation-b5191a113f5c

728x90
반응형