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에 라이브러리 검색

더보기

https://mvnrepository.com/

  • 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을 이용하여 유효성 검사를 통과하지 못할 경우 BindExceptionMethodArgumentNotValidException이 발생할 수 있습니다.
  • 해당 에러가 발생했을 때 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