본문 바로가기
Back/Spring Boot

[SpringBoot] @Valid 어노테이션으로 validation 유효성 검사하기

by 은z 2022. 2. 8.

서론

애플리케이션 개발 진행 할 때, validation 체크는 매우 중요하다.

클라이언트에서도, 서버에서도 각각 검증을 거치는 것이 좋다.

클라이언트에서 데이터가 제대로 왔는지,

db에 데이터가 들어가기 전에 제대로 된 데이터가 맞는지 등.

놓쳐서는 안되는 중요한 작업이다.

 

@Valid 어노테이션을 사용하여 검증 과정을 거칠수 있다.

 

테스트 환경

  • IntelliJ 2021.3 (community 버전)
  • Maven
  • SpringBoot 2.6.1

본론

@Valid 란?

JSR 303부터 현재 JSR 380 버전으로, 자바 표준 스펙으로 지정되어 있는 Bean Validation 기능.

 

Jakarta Bean Validation 2.0 - Java 8 이상

Jakarta Bean Validation 3.0 - Java 11 이상

 

 

사용법

1. 의존성 추가 

Spring boot 사용시 아래 의존성을 추가한다.

 

●Grdle

implementation 'org.springframework.boot:spring-boot-starter-validation'

●Maven

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

 

@Valid 어노테이션이 작동이 안 한다면?

spring boot 2.3 version 이상부터는 spring-boot-starter-web 의존성 내부에 있던 validation이 사라졌다.

때문에 사용하는 spring boot version이 2.3 이상이라면 validation 의존성을 따로 추가해야 사용 가능.

 

2. Annotation 적용

  • 검증할 객체Dto에 검증할 어노테이션을 붙여준다.
  • 컨트롤러에 Dto 옆에 @Valid 를 붙여준다.

단, @Valid 은 Dispatcher Servlet 에서 @Valid어노테이션을 찾아 검증을 진행하는 동작원리때문에,

@Valid 은 Controller단에서만 사용 가능하다.

import com.kiosk.coffee.entity.Menu;
import com.kiosk.coffee.entity.MenuOption;
import lombok.*;

import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class OrderRequest {

    private Long menuSeq;

    @Pattern(regexp = "^[1-8]*$", message = "1부터 8까지의 정수만 입력 가능합니다.")
    private String orderTemp;

    @Pattern(regexp = "^[1-8]*$", message = "1부터 8까지의 정수만 입력 가능합니다.")
    private String orderMilk;

    @Pattern(regexp = "^[1-8]*$", message = "1부터 8까지의 정수만 입력 가능합니다.")
    private String orderShot;

    @Pattern(regexp = "^[0-9]*$", message = "정수만 가능")
    @Size(min = 10, max = 11, message = "전화번호 길이에 부합해야함.")
    private String phoneNum;
}

<Controller>

@PostMapping("")
    public Map doOrder(@RequestBody @Valid OrderRequestDto order, Errors errors)  {
        return errors.hasErrors() ? orderService.handleValidate(errors) : orderService.doOrder(order);
    }

위 예시에서 보이듯이, 검증 객체 옆에 Errors 인터페이스를 붙여준다.

근데 다른 블로그들을 보다보니, Errors 대신에 BindingResult도 많이 쓰이는 것을 찾을 수 있었다.

둘의 차이점은 아래와 같다고 한다.

더보기

BindingResult는 인터페이스고, Errors 인터페이스를 상속받고 있다.
실제 넘어오는 구현체는 BeanPropertyBindingResult 인데 BindingResult대신 Errors를 사용해도 된다.

Errors 인터페이스는 단순한 오류 저장과 조회 기능을 제공한다.
BindingResult는 여기에 더해서 추가적인 기능들을 제공한다. (ex. addError())

 

 

👀만약 검증하고자 하는 객체가 Collection이라면? 

아래 포스팅을 참고!

2023.01.30 - [Programming/Spring Boot] - [SpringBoot] @Valid 어노테이션으로 collection 객체 검증

 

<Service>

@Override
    public Map handleValidate(Errors errors) {
        Map<String, String> validResult = new HashMap<>();

        errors.getFieldErrors().forEach(er -> {
            validResult.put(er.getField(), er.getDefaultMessage());
        });

        return validResult;
    }

 

 

@Valid 어노테이션 종류

API 공식문서 - 링크

●Annotaion 종류와 뜻

Annotation 제약조건
@NotNull Null 불가
@Null Null만 입력 가능
@NotEmpty Null, 빈 문자열 불가, " "이건 됨.
@NotBlank Null, 빈 문자열, 스페이스만 있는 문자열 불가("" 이것도 안됨)
@Size(min=,max=) 문자열, 배열등의 크기가 만족하는가?
@Pattern(regex=) 정규식을 만족하는가?
@Max(숫자) 지정 값 이하인가?
@Min(숫자) 지정 값 이상인가
@Future 현재 보다 미래인가?
@Past 현재 보다 과거인가?
@Positive 양수만 가능
@PositiveOrZero 양수와 0만 가능
@Negative 음수만 가능
@NegativeOrZero 음수와 0만 가능
@Email 이메일 형식만 가능
@Digits(integer=, fraction = ) 대상 수가 지정된 정수와 소수 자리 수 보다 작은가?
@DecimalMax(value=)  지정된 값(실수) 이하인가?
@DecimalMin(value=) 지정된 값(실수) 이상인가?
@AssertFalse false 인가?
@AssertTrue true 인가?

++ 참고!

 

댓글