주요글: 도커 시작하기
반응형

Bean Validation 2.0(JSR-380)에는 검증과 관련해서 간지러운 점을 긁어주는 애노테이션이 몇 개 추가되었다. 예를 들어 2.0에 추가된 @Email 애노테이션을 사용하면 이메일 형식을 검사하기 위해 정규 표현식을 사용하지 않아도 되고, @Positive 애노테이션을 사용하면 값이 양수인지 검사할 수 있다.


스프링 5에서 Bean Validation 2.0 설정


스프링 5 버전에서 Bean Validation 2.0을 사용하려면 다음과 같이 2.0 API와 관련 프로바이더를 의존에 추가해주면 된다. hibernate-validator 6.0 의존을 추가하면 validationa-api 2.0 의존도 함께 추가되므로 validation-api 의존을 생략해도 된다.


<!-- validation-api는 생략 가능 -->

<dependency>

    <groupId>javax.validation</groupId>

    <artifactId>validation-api</artifactId>

    <version>2.0.1.Final</version>

</dependency>


<dependency>

    <groupId>org.hibernate.validator</groupId>

    <artifactId>hibernate-validator</artifactId>

    <version>6.0.7.Final</version>

</dependency>


스프링 관련 설정


@EnableWebMvc 애노테이션을 사용하면 된다. 이 애노테이션을 사용하면 Bean Validation 애노테이션에 대한 검증 기능을 제공하는 OptionalValidatorFactoryBean를 글로벌 Validator로 등록한다.


@Configuration

@EnableWebMvc

public class SpringConfig implements WebMvcConfigurer {

    ...

}


애노테이션 사용 예


다음은 Bean Validation 애노테이션을 사용한 예이다.


import org.springframework.format.annotation.DateTimeFormat;


import javax.validation.constraints.Email;

import javax.validation.constraints.NotBlank;

import javax.validation.constraints.NotEmpty;

import javax.validation.constraints.PastOrPresent;

import java.time.LocalDate;


public class FormData {

    @NotBlank

    @Email

    private String email;


    @NotBlank

    private String name;


    @NotEmpty

    private String password;


    @DateTimeFormat(pattern = "yyyyMMdd")

    @PastOrPresent

    private LocalDate birthday;


컨트롤러는 다음과 같이 @Valid를 이용해서 검증을 적용할 수 있다.


@PostMapping

public String submit(@ModelAttribute @Valid FormData formData, Errors errors) {

    if (errors.hasErrors()) return "form";

    return "submit";

}


실제 예제 코드는 https://github.com/madvirus/spring5-bv2 리포지토리에서 확인할 수 있다. 리포지토리에서 코드를 clone하고 아래 순서대로 실행한다.

  • git clone https://github.com/madvirus/spring5-bv2.git
  • cd spring5-bv2
  • cd sp5-bv2
  • mvnw jetty:run

이 예제는 JSP를 뷰 기술로 사용했다. 관련 폼을 보여주는 JSP 코드는 다음과 같다.


<%@ page contentType="text/html; charset=utf-8" %>

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<!DOCTYPE html>

<html>

<head>

    <title>가입</title>

</head>

<body>

    <h2>가입</h2>

    <form:form modelAttribute="formData">

    <p>

        <label>이메일:<br>

        <form:input path="email" />

        <form:errors path="email"/>

        </label>

    </p>

    <p>

        <label>이름:<br>

        <form:input path="name" />

        <form:errors path="name"/>

        </label>

    </p>

    <p>

        <label>암호:<br>

        <form:password path="password" />

        <form:errors path="password"/>

        </label>

    </p>

    <p>

        <label>생일:<br>

        <form:input path="birthday" />

        <form:errors path="birthday" />

        </label>

    </p>

    <input type="submit" value="가입">

    </form:form>

</body>

</html>


브라우저에서 http://localhost:8080/register로 연결한 뒤 폼에 아무 값도 입력하지 않고 [가입] 버튼을 누르면 검증 결과를 확인할 수 있다. 실제 결과는 다음과 같다.



에러 메시지를 위한 MessageSource를 설정하지 않았다. 위 결과에서 이메일, 이름, 암호 필드에 출력한 메시지는 hibernate-validator가 제공하는 기본 에러 메시지이다.


스프링 부트 2 사용


스프링 부트 2 버전은 기본적으로 Bean Validation 2.0을 사용하므로 추가 설정이 필요없다. 그냥 스프링 부트 2 프로젝트를 만들어 사용하면 된다. 관련 예제 코드는 같은 리포지토리의 boot2-bv2 폴더에 있다. 아래 순서대로 실행한 뒤 브라우저에서 http://localhost:8080/register 주소로 연결해서 확인할 수 있다.

  • git clone https://github.com/madvirus/spring5-bv2.git
  • cd spring5-bv2
  • cd boot2-bv2
  • mvnw spring-boot:run

부트 예제는 Thymeleaf를 뷰로 사용했다. 폼을 보여주는 Themeleaf 템플릿 코드는 다음과 같다.


<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

<head>

    <meta charset="UTF-8" />

    <title>가입</title>

</head>

<body>

<h2>가입</h2>

<form th:object="${formData}" method="POST">

    <p>

        <label>이메일:<br>

            <input type="text" th:field="*{email}" />

            <span th:each="err : ${#fields.errors('email')}" th:text="${err}" />

        </label>

    </p>

    <p>

        <label>이름:<br>

            <input type="text" th:field="*{name}" />

            <span th:each="err : ${#fields.errors('name')}" th:text="${err}" />

        </label>

    </p>

    <p>

        <label>암호:<br>

            <input type="password" th:field="*{password}" />

            <span th:each="err : ${#fields.errors('password')}" th:text="${err}" />

        </label>

    </p>

    <p>

        <label>생일:<br>

            <input type="text" th:field="*{birthday}" />

            <span th:each="err : ${#fields.errors('birthday')}" th:text="${err}" />

        </label>

    </p>

    <input type="submit" value="가입">

</form>

</body>

</html>


실행 결과는 앞서 본 그림과 동일하다.


Bean Validation 2.0 제공 애노테이션


Bean Validation 2.0이 제공하는 애노테이션 목록은 다음과 같다. 2.0에 추가된 애노테이션에는 (2)를 표시했다. 아래 표의 지원 타입에서 CharSequence는 문자열 관련 인터페이스로 이 인터페이스를 구현한 대표적인 클래스가 String이다.


애노테이션 

주요 속성 

설명 

 지원 타입

@AssertTrue

@AssertFalse

 

값이 true인지 또는 false인지 검사한다. null은 유효하다고 판단한다. 

boolean
Boolean

@DecimalMax

@DecimalMin

String value

- 최댓값 또는 최솟값


boolean inclusive

- 지정값 포함 여부

- 기본 값 true

지정한 값보다 작거나 같은지 또는 크거나 같은지 검사한다.

inclusive가 false면 value로 지정한 값은 포함하지 않는다.

null은 유효하다고 판단한다.

BigDecimal

BigInteger

CharSequence

byte, short, int, long 및 각 래퍼 타입

@Max

@Min

long value

지정한 값보다 작거나 같은지 또는 크거나 같은지 검사한다.

null은 유효하다고 판단한다.

BigDecimal
BigInteger
byte, short, int, long 및 관련 래퍼 타입

@Digits

int integer

- 허용 가능한 정수 자릿수


int fraction

- 허용 가능한 소수점 이하 자릿수

자릿수가 지정한 크기를 넘지 않는지 검사한다.

null은 유효하다고 판단한다.

BigDecimal

BigInteger

CharSequence

byte, short, int, long 및 관련 래퍼 타입

@Size

int min

- 최소 크기

- 기본 값 0


int max

- 최대 크기

- 기본 값 

길이나 크기가 지정한 값 범위에 있는지 검사한다.

null은 유효하다고 판단한다.

CharSequence

Collection

Map

배열

@Null

@NotNull

 

값이 null인지 또는 null이 아닌지 검사한다. 

 

@Pattern

String regexp

- 정규표현식 

값이 정규표현식에 일치하는지 검사한다. 

null은 유효하다고 판단한다.

CharSequence

@NotEmpty (2)

 

문자열나 배열의 경우 null이 아니고 길이가 0이 아닌지 검사한다. 콜렉션의 경우 null이 아니고 크기가 0이 아닌지 검사한다.

CharSequence

Collection

Map

배열

@NotBlank (2)


null이 아니고 최소한 한 개 이상의 공백아닌 문자를 포함하는지 검사한다.

CharSequence

@Positive (2)

@PositiveOrZero (2)

 

양수인지 검사한다.

OrZero가 붙은 것은 0 또는 양수인지 검사한다.

null은 유효하다고 판단한다.

BigDecimal
BigInteger
byte, short, int, long 및 관련 래퍼 타입

@Negative (2)

@NegativeOrZero (2)

 

음수인지 검사한다.
OrZero가 붙은 것은 0 또는 음수인지 검사한다. 

null은 유효하다고 판단한다.

BigDecimal
BigInteger
byte, short, int, long 및 관련 래퍼 타입

@Email (2)

 

이메일 주소가 유효한지 검사한다. 
null은 유효하다고 판단한다.
CharSequence 

@Future (2)

@FutureOrPresent (2)

 

해당 시간이 미래 시간인지 검사한다.

OrPresent가 붙은 것은 현재 또는 미래 시간인지 검사한다.

null은 유효하다고 판단한다.

시간 관련 타입

@Past (2)

@PastOrPresent (2)

 

해당 시간이 과거 시간인지 검사한다.

OrPresent가 붙은 것은 현재 또는 과거 시간인지 검사한다.
null은 유효하다고 판단한다.

시간 관련 타입 

* 애노테이션이 속한 패키지: javax.validation.constraints

* 시간 관련 타입: Date, Calendar, Instant, LocalDate, LocalDateTime, MonthDay, OffsetDateTime, OffsetTime, Year, YearMonth, ZonedDateTime 등



관련 링크

  • 예제 코드: https://github.com/madvirus/spring5-bv2
  • Bean Validation: http://beanvalidation.org/


+ Recent posts