[Spring] Bean validation, @Valid vs @Validated

Yujeong·2024년 3월 17일
post-thumbnail

특정 필드에 대한 검증 로직은 보통 크기, 타입, null 체크 등이다. 이러한 로직을 매번 작성하기는 코드가 지저분해지고, 반복적인 검증이 많아진다.
이러한 문제를 해결하기 위해 Bean validation(빈 유효성 검사)을 사용한다.

Bean validation

  • 애플리케이션에서 객체의 유효성을 검사하기 위한 표준 방법
  • Java Bean에 대한 유효성 검사 규칙을 정의하고 이를 적용
  • 객체의 유효성을 검증하는 코드를 반복하지 않고 간편하게 유효성 검사 수행 가능

build.gradle

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

@NotNull, @Size, @NotBlank 등 다양한 검증 애노테이션이 있다.
https://jakarta.ee/specifications/bean-validation/3.0/jakarta-bean-validation-spec-3.0.html

@Valid

1. @Valid가 무엇인가?

  • 주로 request body를 검증하는 데 사용된다.
  • 메서드나 매개변수에 적용되어 해당 객체의 유효성을 검증하는 데 사용된다.
  • valid 애노테이션이 적용된 대상 객체의 내부 필드에 대한 유효성 검사도 자동으로 수행된다.

Company를 추가하는 간단한 request dto가 있고, NotNull, NotBlank의 유효성 검사 애노테이션을 적용했다.

public class CompanyRequestDTO {

	@NotBlank
	private name;
    
    @Notnull
    private Address address;
}

그리고 Address와 Car는 값 객체로 아래와 같이 구성했다.

public class Address {

	@NotBlank
    private String city;
    
    @NotBlank
    private String street;
    
    @NotBlank
    @Size(max = 10)
    private String zipCode;

그리고 Controller 내에 Company 생성 함수 파라미터에 @Valid를 추가하면 정상 작동한다.

@RequiredArgsConstructor
@RestController
@RequestMapping("/companies")
public class CompanyController {
    private final CompanyService companyService;

    @PostMapping
    public ResponseEntity<Object> createCompany(Authentication authentication, @Valid @RequestBody CompanyRequestDTO companyRequestDTO) {
        companyService.createCompany(Long.parseLong(authentication.getName()), companyRequestDTO);
        return ResponseEntity.status(HttpStatus.CREATED).build();

2. nested dto 검증

nested dto를 검증하려면, Address에 @NotNull 대신 @Valid를 붙이면 된다.

public class CompanyRequestDTO {

	@NotBlank
	private name;
    
    @Valid
    private Address address;
}

3. 동작 원리

모든 요청은 dispatcher servlet을 통해 컨트롤러로 전달된다.
이 과정에서 컨트롤러 메서드의 객체를 만들어주는 ArgumentResolver가 동작하는데, @Valid 역시 ArgumentResolver에 의해 처리된다.
또한, 검증에 오류가 생기면 MethodArgumentNotValidException 예외 발생 시켜서 DefaultHandlerExceptionResolber에 의해 400 에러가 발생한다.

@Validated

1. @Validated는 무엇인가?

  • 메서드 파라미터에 대한 유효성 검사하는데 사용되는 애노테이션이다.
  • 유효성 검증은 controller에서 최대한 처리하지만, 불가피하게 service같은 다른 레이어에서 검증할 때 사용된다.
@Validated
@Service
public class CompanyService {

	public void createCompany(@Valid CompanyRequestDTO companyRequestDTO) {
		...
	}
}

2. 동작 원리

AOP(Aspect Oriented Programming) 기반으로, 메서드의 요청을 가로채서 유효성 검증이 진행된다.
@Validated를 클래스 레벨에 선언하면, 해당 클래스에 유효성 검증을 위해 AOP에 등록되고MethodValidationInterceptor 클래스에서 가로채서 실행된다.
그리고 유효성 검증에 실패하면, ConstraintViolationException 예외가 발생한다.


참고

@Valid vs @Validated 정리
[SPRING] @Valid 어떻게 동작할까 - java bean validation
[SPRING] @Valid @Validated 사용하기 - java bean validation

profile
공부 기록

0개의 댓글