Vlidation은 데이터를 검증할 때 사용한다.
데이터 검증으 여러 계층에 걸쳐서 이루어지게 되는데, 이 과정으로 인해 문제점이 발생할 수 있다.
- 코드의 중복
- 검증로직 불일치로 인한 오류
이 문제를 해결하기 위해서 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
'프로그래밍 노트 > SPRING BOOT' 카테고리의 다른 글
[Spring Boot] RedisCluster 연동 & RedisTemplate 적용 (feat. AutoConfiguration) (0) | 2024.10.22 |
---|---|
Validation 알아보기_2(Spring Validation) (0) | 2021.01.09 |
[Spring Boot] 외부설정하기 (externalized configuration) (2) | 2019.11.18 |
@Conditional, @ConditionalOnXXX (0) | 2019.11.18 |
[Spring Boot] Custom한 배너를 만들어보자! (0) | 2019.11.05 |