Spring Framework에서 데이터 유효성 검사는 사용자 입력의 무결성과 신뢰성을 보장하는 데 중요한 역할을 합니다.
유효성 검사 프로세스를 단순화하기 위해 Spring은 @Valid 및 @Validated라는 두 가지 어노테이션을 제공합니다. 이를 통해 Spring 애플리케이션의 데이터 유효성을 검사하고 특정 요구 사항 및 제약 조건을 충족하는지 확인하는 데 도움이 됩니다. 이 블로그 게시물에서는 @Valid와 @Validated의 차이점과 각 어노테이션을 사용하는 경우를 살펴보겠습니다.
@Valid와 @Validated를 사용하기 위해서는 다음과 같은 의존성을 추가해야 합니다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
}
@Valid
는 JSR-303 표준 스펙으로, 빈 검증기를 이용해 객체의 제약 조건을 검증하도록 지시하는 어노테이션입니다.
예를 들어, @NotNull은 필드의 값이 null이 아님을 확인하고, @Email은 필드의 값이 이메일 형식임을 확인합니다.
@Valid는 컨트롤러의 메소드 파라미터에 적용할 수 있으며, 유효성 검사에 실패하면 MethodArgumentNotValidException
예외가 발생합니다.
@Valid
는 Controller
에서 직접적으로 유효성 검증을 처리합니다. @Valid
어노테이션을 붙여 검증을 수행합니다. 검증 결과는 BindingResult
객체에 담겨 반환됩니다.@Validated
는 Spring에서 제공하는 어노테이션으로, @Valid의 기능을 포함하고 추가적으로 그룹화된 유효성 검증을 지원합니다. 그룹화된 유효성 검증
이란, 객체의 필드에 그룹을 지정하고, 컨트롤러의 메소드에서 해당 그룹만 유효성 검사를 수행하도록 하는 기능입니다.
예를 들어, 회원가입과 로그인에서 사용하는 UserDto 클래스가 있다면, 회원가입 시에는 모든 필드를 검증해야 하지만, 로그인 시에는 아이디와 비밀번호만 검증하면 됩니다. 이런 경우에 그룹화된 유효성 검증을 사용할 수 있습니다.
@Validated
는 @Valid와 유사하지만, 빈으로 등록되어 있는 클래스에 붙어 검증을 수행합니다.Errors
객체에 담겨 반환됩니다.@Valid
는 컨트롤러에서 직접적으로 유효성 검증을 처리하고, @Validated
는 빈으로 등록된 클래스에서 유효성 검증을 처리합니다.
@Valid
는 검증 결과를 BindingResult에 담고, @Validated
는 Errors에 담습니다.
@Valid
는 검증 그룹을 사용할 수 없지만, @Validated
는 검증 그룹을 사용할 수 있습니다.
@Valid와 @Validated의 사용 방법은 다음과 같습니다.
@Valid
는 메소드 파라미터에 붙여 사용합니다.
@Getter
@Setter
public class ArticleRequestDto {
private Long articleId;
@Max(15)
@Min(1)
private String title;
@Max(1000)
@Min(1)
private String contents;
private String author;
@PostMapping("/articles")
public ResponseEntity<?> createArticle(@Valid @RequestBody ArticleDto articleDto) {
// ...
}
@Validated
는 빈으로 등록된 클래스에 붙여 사용합니다.
@Service
@Validated
public class UserService {
public void createUser(@Valid UserDto userDto) {
// ...
}
}
다른 방법으로는
검증 그룹을 지정하기 위해 마커 인터페이스(내용 없이 중괄호({})만 있는)
를 간단히 정의한다.
public interface AnonymousValidationGroup {}
public interface AuthorValidationGroup {}
그리고 해당 제약 조건이 적용될 그룹을 groups
로 지정해준다.
제약 조건이 적용될 그룹이 여러 개라면 {}를 이용해 그룹의 이름을 모두 넣어주면 된다.
예를 들어 다음과 같이 DTO에 그룹 속성을 지정해줄 수 있다.
@NotEmpty(groups = {AnonymousValidationGroup.class, AuthorValidationGroup.class} )
private String author;
@NotEmpty(groups = AnonymousValidationGroup.class)
private String anonymousId;
@NotEmpty(groups = AuthorValidationGroup.class)
private String authorId;
Controller에서는 아래와 같이 사용한다.
@PostMapping("/articles")
public ResponseEntity<Void> createArticle(
@RequestBody @Validated(AnonymousValidationGroup.class) ArticleRequestDto articleRequestDto) {
...
}
만약 위와 같이 AnonymousValidationGroup을 @Validated
의 파라미터로 넣어주었다면 AnonymousValidationGroup에 해당하는 제약 조건만 검증이 된다.
@Validated에 특정 마커를 지정해주지 않았거나, groups가 지정되어 있는데 @Valid를 이용하면 다음과 같이 처리된다.