Web Programming/Spring Boot

[Spring Boot] 유효성 검사(Validation)

solitude12 2024. 7. 4. 02:04

특정 애플리케이션의 비즈니스 로직이 정상적으로 동작하기 위해서 여러가지 요건이 필요하겠지만, 그 중 하나는 올바른 입력값을 위한 유효성 검증이 필요하다. 제대로 된 입력값을 검증하지 않고 입력받게 된다면 의도치 않은 에러나 버그가 발생할 수 있고 데이터의 정확성인 일관성을 보장하기 어렵다.

1. Spring Boot에서의 Validation

자바에서는 javax.validation(혹은 jakarta.validation) 패키지에 정의된 Bean Validation API를 기반으로 하며 다양한 어노테이션 기반으로 필드 수준의 검증을 쉽게 수행할 수 있다. Spring Boot 에서는 이 Bean Validation의 구체적인 구현체로 Hibernate Validator를 검사 표준으로 채택해 사용하고 있다. spring boot에서 사용하기 위해서는 아래와 같은 의존성을 추가해야 하며, spring boot initializer를 활용한다면 validation이라는 이름으로 추가할 수 있다.

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

주로 엔티티나 DTO 같은 도메인 모델에 적용 후 컨트롤러에서 그 검증을 일반적으로 수행한다. 아래는 그 예시이다.

import javax.validation.constraints.Email;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

public class User {
    @NotBlank(message = "이름은 필수 입력 항목입니다.")
    private String name;

    @NotNull(message = "나이는 필수 입력 항목입니다.")
    @Min(value = 18, message = "나이는 18세 이상이어야 합니다.")
    private Integer age;

    @Email(message = "유효한 이메일 형식이어야 합니다.")
    private String email;

    // Getter 및 Setter 생략
}
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    public String createUser(@Valid @RequestBody User user, BindingResult result) {
        if (result.hasErrors()) {
            return result.getAllErrors().stream()
                         .map(ObjectError::getDefaultMessage)
                         .collect(Collectors.joining(", "));
        }
        // 실제 사용자 생성 로직 (생략)
        return "사용자가 성공적으로 생성되었습니다.";
    }
}

 

 

컨트롤러와 엔티티에서 정의해 주로 사용하며 계층 간(Controller, Service 등) 데이터 전송 시에도 활용 가능하다. 다만 검증을 하기 위해서는 컨트롤러의 @Valid 어노테이션을 지정해야 그 객체에 대한 검사를 수행하므로 이 점을 유의해야한다.

 

2. Validation의 주요 어노테이션

유효성 검증 시 사용하는 주된 어노테이션들은 다음과 같다. 상황에 맞게 적절하게 필드에 적용해 사용하면 된다.

문자열 검증

  • @Null : null 값만 허용한다.
  • @NotNull : null을 허용하지 않는다. “”, “ “는 허용한다.
  • @NotEmpty : null, ““을 허용하지 않는다. “ “는 허용한다.
  • @NotBlank : null, “”, “ “을 허용하지 않는다.

최댓값 / 최솟값 검증

  • BigDecimal, BigInteger, int, long 등의 타입을 지원한다.
  • @DemicalMax(value = "$numberString") : $numberString 보다 작은 값을 허용한다.
  • @DemicalMin(value = "$numberString") : $numberString 보다 큰 값을 허용한다.
  • @Min(value = $number) : $number 이상의 값을 허용한다.
  • @Max(value = $number) : $number 이하의 값을 허용한다

값의 범위 검증

  • BigDecimal, BigInteger, int, long 등의 타입을 지원한다.
  • @Positive : 양수를 허용한다.
  • @PositiveOrZero : 0을 포함한 양수를 허용한다.
  • @Nagative : 음수를 허용한다.
  • @NagetiveOrZero : 0을 포함한 음수를 허용한다.

시간에 대한 검증

  • Date, LocalDate, LocalDateTime등의 타입을 지원한다.
  • @Future : 현재보다 미래의 날짜를 허용한다.
  • @FutureOrPresent : 현재를 포함한 미래의 날짜를 허용한다
  • @Past : 현재보다 과거의 날짜를 허용한다.
  • @PastOrPresent : 현재를 포함한 과거의 날짜를 허용한다.

이메일 검증

  • @Email : 이메일 형식을 검사한다. ““는 허용한다.

자릿수 범위 검증

  • BigDecimal, BigInteger, int, long 등의 타입을 지원한다.
  • @Digits(integer = $number1, fraction = $number2) : $number1의 정수 자릿수와 $number2의 소수 자릿수를 허용한다.

Boolean 검증

  • @AssertTrue : true인지 체크한다. null값은 체크하지 않는다.
  • @AssertFalse : false인지 체크한다. null값은 체크하지 않는다.

문자열 길이 검증

  • @Size(min = $number1, max = $number2) : $number1 이상 $number2 이하의 범위를 허용한다.

정규식 검증

  • @Pattern(regexp = "$expression") : 정규식을 검사한다 정규식은 자바의 java.util.regex.Pattern 패키지의 컨벤션을 따른다.

지금까지 기초적인 Validation에 대해서 확인했다. 이외에도 Boolean 검증과 커스텀 validation을 통해서 필요한 상황에 좀 더 유연하게 적용하는 방식도 있는데 이는 다음에 알아보자.


참고 자료

 

스프링 부트 핵심 가이드 6주차: 10장

@BindingResult , @Valid , @Validate , @RestControllerAdvice , @ExceptionHandler , ConstraintValidator

velog.io