본문 바로가기
[Spring]/Spring 기본

@Valid & @Validated 차이점에 대해 알아보자.(JSR 380 정리)

by 황원용 2023. 6. 7.
728x90

@Valid & @Validated

  • 자바 프로그래밍에서 입력값에 대한 유효성 검사를 도와주는 주석이다.
  • 두 주석의 역할이 비슷한 것 같으면서도 분명한 차이점이 있어 이번 기회에 정리해보려고 한다.

 

@Valid

  • JSR 380(Java Bean Validation) 사양의 일부로 주석이 달린 개체의 유효성 검사를 하는 데 사용된다.
  • 클래스 또는 메서드의 파라미터에서 @Valid라고 표시되면 기본 유효성 검증 제공자를 사용하여 미리 정의된 유효성 검증 제한 조건을 기반으로 유효성 검증을 수행하도록 spring에 지시한다.

 

사용 예시

  • Spring boot에서 컨트롤러 단 메서드에 @RequestBody 주석이 달린 파라미터 값에 적용되어 입력받는 값을 검증할 수 있다.
  • 위의 예시로 보면 입력받는 requestBody의 데이터의 유효성을 검사한다.

 

자바 기본 스펙

  • JSR 380은 Jakarta EE 및 JavaSE의 일부인 빈 유효성 검사를 위한 Java API 사양이다.
  • 1.0(JSR303), 1.1(JSR349)를 거쳐 2.0(JSR380)으로 버전이 업데이트되었다.
  • 한마디로 @Valid는 애플리케이션 개발 시 자주 반복되는 유효성 검사 패턴을 정리한 JavaEE 표준의 일부인 것이다.

 

사용 주석 정리

@NotNull

  • 주석이 달린 속성 값이 null 이 아닌지 확인한다.

@AssertTrue

  • 주석이 달린 속성 값이 true인지 확인한다.

@Size(min = X, max = X)

  • 주석 속성 값이 min 속성과 max 속성 사이의 크기를 가지고 있는지 확인한다.
  • String , Collection , Map 및 배열 속성에 적용할 수 있다.

@Min

  • 속성 값이 주석에 적힌 값보다는 크거나 같은지 확인한다.

@Max

  • 속성 값이 주석에 적힌 값보다는 작거나 같은지 확인한다.

@Email

  • 주석 속성이 유효한 이메일 주소인지 확인한다.
  • xxx@xxx.xxx

@NotEmpty

  • 속성이 null이거나, 비어 있지 않은지 확인합니다. 
  • String , Collection , Map 또는 Array에 적용할 수 있다.

@NotBlank

  • 텍스트 값에만 적용할 수 있으며 속성이 null 또는 공백이 아닌지 확인한다.

@Positive 및 @PositiveOrZero

  • 숫자 값에 적용되며 값이 완전히 양수인지 또는 0을 포함하여 양수인지 확인한다.

@Negative 및 @NegativeOrZero

  • 숫자 값에 적용되며 값이 완전히 음수인지 또는 0을 포함하여 음수인지 확인한다.

@Past 및 @PastOrPresent

  • 날짜 값이 과거 또는 현재를 포함한 과거인지 확인한다.
  • Java 8에 추가된 날짜 유형을 포함하여 날짜 유형에 적용할 수 있습니다.

@Future 및 @FutureOrPresent

  • 날짜 값이 미래인지 또는 현재를 포함한 미래인지 확인한다.

 

List<@NotBlank String> testList;
  • 유효성 검사 주석은 컬렉션의 요소에도 적용할 수 있다.
  • 이 경우 기본 설정 목록에 추가된 모든 값이 확인된다.

 

제약 조건 위반 시

  • 유효성 검사 제약 조건을 위반하면 유효성 검사 오류 유형에 따라 "MethodArgumentNotValidException" 또는 ConstraintViolationException"이 발생한다.

 

 

@Validated

  • @Valid의 기능을 향상하고 추가 기능을 제공하는 Spring 전용 애너테이션이다.
  • Spring AOP(Aspect-Oriented Programming) 프레임워크와 통합되어 동작한다.

 

사용예시

@RestController
@RequestMapping("/v1/members")
@Validated 
public class MemberController {
	
    ...
    
    @PatchMapping("/{memberId}")
    public ResponseEntity patchMember(@PathVariable("memberId") @Min(1) long memberId,
                                    @Valid @RequestBody MemberDto.Patch requestBody) {
        
        ...
	}
}
  • @Valid와 마찬가지로 클래스나 메서드 파라미터에 적용할 수 있다. 
  • 클래스 단에 붙으면 해당 클래스의 모든 공용 메서드가 유효성 검사 대상이 된다.(@Valid도 마찬가지)
  • 예를 들어 위 코드에서 메서드 파라미터에 @Valid나 @Validated가 붙지 않은 @PathParameter의 @Min(1)의 경우 클래스 단에 @Validated가 붙지 않으면 유효성 검증을 하지 않는다.

 

그룹 유효성 검사

  • @Validated는 다양한 시나리오를 만들어 유효성 검사 그룹을 나눌 수 있어 특정 제약 조건의 선택적 유효성 검사가 가능하다.

 

제약 조건 위반 시

  • 유효성 검사 제약 조건을 위반하면 유효성 검사 오류 유형에 따라 "MethodArgumentNotValidException" 또는 ConstraintViolationException"이 발생한다.

 

스프링 AOP 활용

  • 스프링 AOP를 활용한다.
  • 간단하게 이야기하면 메서드 호출을 인터셉트하여 MethodValidationInterceptor 측면에서 정의한 유효성 검사를 진행한다.

 

 

결론

  • 단순하게 모든 필드를 검사한다면 @Valid를 특정 필드만 검사하거나 유효성 검사를 그룹으로 나눠 진행하고 싶다면 @Validated를 쓰면 된다. 나는 세분화된 제어가 가능한 @Validated를 쓰련다.

 

 

 

참고

chatGPT

https://www.baeldung.com/javax-validation

https://dejavuhyo.github.io/posts/java-bean-validation-jsr-380/

728x90