Log
[Validation] Validation 라이브러리 Spring Boot와 Spring Framework 적용
wol mido
2024. 2. 23. 11:00
728x90
- Spring에서는 Client의 요청이 유효한지 확인하기 위해 Java-Validation을 사용한다.
더보기
Spring Boot 3부터는 javax.* 패키지에서 jarkarta.* 패키지로 변경되었습니다.
- 오늘은 Validation 라이브러리에 대한 사용 방법과 Spring Boot와 Spring Framework에서의 적용 방법에 대해서 남길 생각입니다.
Validation 라이브러리
- 애플리케이션에서 데이터의 유효성 검증을 수행하는데 사용되는 툴
- 가장 널리 사용되는 validation 라이브러리는 Bean Validation(Hibernate Validator)과 Spring Validation입니다.
- validation 라이브러리를 사용하면 if문을 각 필드마다 달면서 기재하는 코드들을 간결하게 유지하는데 도움을 줄 수 있습니다.
Bean Validation(Jakarte Bean Validation)
- Bean Validation은 Java 객체의 필드에 대한 제약 조건을 선언적으로 정의할 수 있는 API를 제공합니다.
- 이 라이브러리를 사용하여 애플리케이션의 다양한 계층에 동일한 검증 로직을 사용할 수 있습니다.
- 구현
- Hiberbate Validator는 Bean Validation 사양의 참조 구현으로 가장 널리 사용됩니다.
- 특징
- 어노테이션을 기반으로 한 선언적 검증
- 그룹화된 검증
종류
1. 날짜 및 시간
@Past
- 날짜 및 시간 필드가 과거여야 함.
@PastOrPresent
- 날짜 및 시간 필드가 과거이거나 현재와 같아야 함.
@Futur
- 날짜 및 시간 필드가 미래여야 함.
@FuturOrPresent
- 날짜 및 시간 필드가 미래이거나 현재와 같아야 함.
2. 숫자(int, long, doublel, float, BigDecimal ...)
@Min(value)
- 숫자 필드가 지정된 값 이상이여야 함.
@Max(value)
- 숫자 필드가 지정된 값 이하여야 함.
@Positive
- 숫자 필드가 양수여야 함.
@PosiitiveOrZero
- 숫자 필드가 양수 또는 0이여야 함.
@Negative
- 숫자 필드가 음수여야 함.
@NegativeOrZero
- 숫자 필드가 음수 또는 0이여야 함.
@Digits(integer=, fraction=)
- 숫자 필드가 지정된 정수와, 지정된 소수 잘릿수를 가져야 함.
@DecimalMin(value="")
- 숫자 필드가 지정된 최소값 이상이어야 함을 지정
- 소수를 포함하는 숫자에도 사용이 되므로 정밀할 때 사용
@DecimalMax(value="")
- 숫자 필드가 지정된 최대값 이하이어야 함을 지정
- 소수를 포함하는 숫자에도 사용이 되므로 정밀할 때 사용
3. 문자열
@Pattern(regexp="")
- 문자열 필드가 지정된 정규 표현식과 일치해야 함.
4. 공통
@NotNull
- 필드가 Null이 아니여야 함.
@NotEmpty
- 문자열, 컬렉션, 배열 필드가 비어 있지 않아야 함.
@Null
- 필드가 Null이여야 함.
Spring Boot Validation 적용
1. Maven Centeral에 라이브러리 검색
더보기
- Spring 진영에서 라이브러리를 찾는 사이트
2. 각 의존성 관리 도구 Tool에 따라 적용
Maven
- pom.xml의 dependencies 내부에 추가
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.2.2</version>
</dependency>
Gradle
- build.gradle의 dependencies 내부에 추가
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation
implementation 'org.springframework.boot:spring-boot-starter-validation:3.2.2'
3. DTO에 적용
@Data
@AllArgsConstructor
public class User {
private Integer id;
@Size(min = 2, message = "Name은 2글자 이상 입력해주세요.")
private String name;
@Past(message = "등록일은 현재 또는 과거 날짜를 입력해주세요.")
private Date joinDate;
}
4. Controller의 핸들러에 적용
@PostMapping(path = "/users")
public ResponseEntity<User> createUsers(@Valid @RequestBody User user) {
...
}
5. Exception Handling
- Validation을 이용하여 유효성 검사를 통과하지 못할 경우 BindException과 MethodArgumentNotValidException이 발생할 수 있습니다.
- 해당 에러가 발생했을 때 Client에 서버의 로그를 그대로 노출하게 되면 문제가 발생하기 때문에 에러를 핸들링해야 합니다.
@ControllerAdvice
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
/**
* Validation Error 처리
* @param ex 에러
* @param headers HTTP Header
* @param status HTTP Status Code
* @param request HttpServletRequest
* @return ExceptionResponse
*/
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex,
HttpHeaders headers,
HttpStatusCode status,
WebRequest request
) {
List<String> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.toList();
ExceptionResponse exceptionResponse =
new ExceptionResponse(new Date(), "Validation failed", String.join(", ", errors));
return new ResponseEntity<>(exceptionResponse, HttpStatus.BAD_REQUEST);
}
}
- 여기서 ExceptionResponse는 내가 임의로 만든 화면에 반환하기 위해 사용한 DTO 클래스이다.
- 여기서의 핵심은 유효성 검사를 충족하지 못했기 때문에 BAD_REQUEST를 사용자에게 전달해준다.
6. 결과 확인
Spring Framework Validation 적용
- 사용하는 방법은 동일하나 설정 방법에 대해서만 말씀드리겠습니다.
1. 의존성 추가
더보기
라이브러리의 버전은 임의로 변경해도 됩니다.
Maven
- pom.xml의 dependencies에 추가
<!-- hibernate validation-->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.2.0.Final</version>
</dependency>
<!-- validation api-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
Gradle
- build.gradle의 dependencies에 추가
// https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator
implementation 'org.hibernate.validator:hibernate-validator:6.2.0.Final'
// https://mvnrepository.com/artifact/javax.validation/validation-api
implementation 'javax.validation:validation-api:2.0.1.Final'
2. spring-servlet.xml Validator Bean 생성
- spring-servlet.xml 파일 최상단에 해당 내용을 기재하도록 하자.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<mvc:annotation-driven validator="validator"/>
<!-- Validator -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
<!-- MethodValidationPostProcessor -->
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
...
</beans>
728x90