Bean Validation
Bean Validation 은, JSR 303 에서 처음으로 제안된 어노테이션 기반의 Java Bean 검증 명세이다.
대표적인 구현체로 Hibernate Validator 가 있다.
spring-boot-starter-validation 의존성을 명시하면, hibernate-validator 의존성이 추가된다.
Bean Validation
Bean Validation 은 JSR 303 에서 처음으로 제안되었다.
최초에 제안된 명세의 내용은 다음과 같다.
1 | Validating data is a common task that is copied in many different layers of an application, from the presentation tier to the persistence layer. |
위 내용을 정리하면 다음과 같다.
- 데이터 검증은, 어플리케이션의 서로 다른 레이어에서 (from the presentation tier to the persistence layer) 반복적으로 수행되는 작업이다.
- 각 계층에서 이러한 데이터 검증이 재구현되는 것을 피하기 위해, 많은 개발자들은 검증 코드를 클래스 안에 포함시킨다.
- 이 검증 코드는 해당 클래스의 meta-data (데이터에 대한 정보를 제공하는 데이터) 이다.
- JSR 303은, JavaBean validation 을 위한 meta-data 모델과 API 를 정의한다.
- 기본적인 meta-data 는 오버라이드 및 확장이 가능한 어노테이션 기반이다.
Hibernate Validator
Bean Validation 스팩은 현재 2.0 까지 제안되었다.
- JSR 303 (Bean Validation)
- JSR 349 (Bean Validation 1.1)
- JSR 380 (Bean Validation 2.0)
그런데 위 JSR 은 스팩일 뿐, 구현체는 아니다.
검증된 구현체로는 Hibernate Validator 가 있다.
각 JSR 에 따라, Hibernate Validator 의 버젼은 다음과 같다.
- JSR 303 (Bean Validation) - 4.3.1.final
- JSR 349 (Bean Validation 1.1) - 5.1.1.final
- JSR 380 (Bean Validation 2.0) - 6.0.1.final
Spring Boot with Hibernate Validator
Spring Boot 에서 bean validation 을 활용하는 간단한 예를 보자.
다음과 같이 spring-boot-starter-validation 의존성을 추가하자.
그러면, 아래처럼 hibernate-validator 가 추가되는 것이 확인된다.
다음과 같이 사용자를 등록하기 위한 end-point 를 작성해보자.
1 | import org.springframework.web.bind.annotation.PostMapping |
다음과 같이 나이를 10000 으로 입력해도, 정상적으로 “success” 가 응답이 된다.
아래와 같이, 최대 나이를 100 살로 제한해보자.
1 | import org.springframework.web.bind.annotation.PostMapping |
여전희 정상적으로 “success” 가 응답이 된다.
“@Max(value = 100)” 를 추가했는데, 왜 validation 이 동작하지 않는걸까 ?
아래 문서에 정의되어 있는 것처럼, bean constraints 는 네 가지 타입이 있다.
https://docs.jboss.org/hibernate/validator/8.0/reference/en-US/html_single/#section-declaring-bean-constraints
- field constraints
- property constraints
- container element constraints
- class constraints
그런데, 위 kotlin 코드의 bytecode 를 decompile 한 결과를 보면 아래와 같이 생성자의 파라미터에 “@Max(value = 100)” 가 추가되어있다.
따라서, field constraints 를 사용하기 위해, kotlin 의 @field 를 사용하자.
1 | data class UserSignUp( |
다시 kotlin 코드의 bytecode 를 decompile 한 결과를 보면 아래와 같이 필드에 “@Max(value = 100)” 가 추가되어있다.
그리고 다시 요청을 하게 되면, 다음과 같이 400 error 를 응답받게 된다.
validation 이 실패했고, age 가 100 이하이어야 한다고 WARN 로깅이 되고 있다.