Validation

2024. 10. 14. 21:26Spring Framework/Web on Servlet Stack

Spring MVC에서 validation(검증)은 컨트롤러에서 데이터를 처리하기 전에 데이터의 정확성을 보장하는 데 중요한 역할을 합니다. 기본적으로 Spring MVC는 Bean Validation(JSR-303/JSR-380)을 통합하여 사용하며, Hibernate Validator가 기본 제공자로 사용됩니다. Bean Validation이 클래스패스에 존재하는 경우, Spring은 자동으로 LocalValidatorFactoryBean을 글로벌 Validator로 등록하여 컨트롤러 메서드에서 @Valid@Validated 애노테이션을 사용할 수 있게 해줍니다.

디폴트 Validation 설정

Spring MVC에서 @Valid 또는 @Validated를 사용하면, 해당 메서드 아규먼트에 대해 자동으로 검증이 수행됩니다. 예를 들어:

@PostMapping("/submitForm")
public String handleForm(@Valid @ModelAttribute MyForm form, BindingResult result) {
    if (result.hasErrors()) {
        // 검증 오류 처리
        return "errorPage";
    }
    // 폼 처리
    return "successPage";
}

이 예시에서:

  • @ValidMyForm 객체에 대한 검증을 트리거하며, 컨트롤러가 요청을 처리하기 전에 데이터가 유효한지 확인합니다.
  • BindingResult는 검증 오류를 캡처하며, 오류가 있는 경우 이를 확인하여 처리할 수 있습니다.

Spring은 기본적으로 LocalValidatorFactoryBean을 글로벌 Validator로 사용하여 검증 작업을 수행합니다.

Java Configuration에서 글로벌 Validator 커스터마이징

애플리케이션에 맞게 글로벌 Validator 인스턴스를 커스터마이징해야 할 경우가 있습니다. 예를 들어, 커스텀 검증 제공자를 설정하거나, 기본 Validator에 추가 기능을 확장하고자 할 수 있습니다.

글로벌 Validator를 커스터마이징하려면, WebMvcConfigurer 인터페이스의 getValidator() 메서드를 오버라이드합니다. 다음은 그 예시입니다:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public Validator getValidator() {
        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
        // Validator에 대한 커스텀 설정을 추가할 수 있습니다.
        return validator;
    }
}

이 예시에서:

  • LocalValidatorFactoryBean을 사용해 새로운 Validator 인스턴스를 생성합니다.
  • Validator 인스턴스에 원하는 대로 커스텀 동작을 추가할 수 있습니다. 예를 들어, 메시지 인터폴레이터나 검증 팩토리를 설정할 수 있습니다.

컨트롤러에서 로컬 Validator 구현 등록

글로벌 Validator 외에도 특정 컨트롤러에서만 검증 논리를 적용하고 싶을 때 로컬 Validator를 등록할 수 있습니다. 이를 위해 WebDataBinder를 사용하여 개별 컨트롤러 수준에서 검증기를 설정할 수 있습니다.

다음은 컨트롤러에 로컬 Validator를 등록하는 방법입니다:

@Controller
public class MyController {

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.addValidators(new FooValidator());
    }
}

이 예시에서:

  • @InitBinder는 특정 컨트롤러 메서드에 대한 데이터 바인딩 과정을 커스터마이징할 때 사용됩니다.
  • WebDataBinderFooValidator와 같은 로컬 검증기를 추가하여, 이 컨트롤러의 메서드에서만 적용되도록 할 수 있습니다.

LocalValidatorFactoryBean@Primary 사용

애플리케이션의 다른 곳에서 LocalValidatorFactoryBean을 주입할 필요가 있는 경우(예: 서비스 클래스에서), 해당 빈을 정의하고 @Primary로 마킹해야 합니다. 이렇게 하면 MVC 설정에서 자동으로 선언된 Validator와 충돌을 피할 수 있습니다.

다음은 @PrimaryLocalValidatorFactoryBean을 정의하는 예시입니다:

@Configuration
public class AppConfig {

    @Bean
    @Primary
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }
}
  • @Primary: 이 애노테이션은 여러 Validator 빈이 정의되어 있을 때, 이 validator() 빈이 기본적으로 사용되도록 보장합니다. 이를 통해 Spring MVC에서 자동으로 등록되는 글로벌 Validator와 커스텀 Validator 간의 충돌을 방지할 수 있습니다.

Reactive 스택(Spring WebFlux)에서의 Validation

Spring WebFlux(reactive 스택)에서도 검증은 Spring MVC와 유사하게 작동합니다. @Valid@Validated 애노테이션을 사용하여 컨트롤러 메서드 아규먼트에 대한 검증을 수행할 수 있으며, 비동기식 논블로킹 환경에 맞춰 실행됩니다.

다음은 reactive WebFlux 컨트롤러에서 검증을 수행하는 예시입니다:

@PostMapping("/submitForm")
public Mono<ResponseEntity<String>> handleForm(@Valid @RequestBody MyForm form, Errors errors) {
    if (errors.hasErrors()) {
        return Mono.just(ResponseEntity.badRequest().body("Validation error"));
    }
    // 폼 처리
    return Mono.just(ResponseEntity.ok("Success"));
}

이 예시에서:

  • @ValidMyForm 객체에 대한 검증을 트리거합니다.
  • Errors는 검증 오류를 캡처합니다.
  • reactive 타입은 비동기식 프로그래밍에 맞춰 Mono<ResponseEntity>로 설정됩니다.

WebFlux에서의 글로벌 Validator

WebFlux에서도 글로벌 Validator를 커스터마이징할 수 있으며, 이는 Spring MVC와 매우 유사합니다. WebFluxConfigurer 인터페이스를 구현하고 getValidator() 메서드를 오버라이드하여 글로벌 Validator를 설정할 수 있습니다.

@Configuration
@EnableWebFlux
public class WebFluxConfig implements WebFluxConfigurer {

    @Override
    public Validator getValidator() {
        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
        return validator;
    }
}

이 방식은 MVC 설정과 동일하지만, 논블로킹 비동기 환경에서 작동합니다.

WebFlux에서의 로컬 Validator

Spring MVC와 마찬가지로, WebFlux에서도 컨트롤러 수준에서 로컬 검증기를 등록할 수 있습니다. @InitBinder 애노테이션을 사용해 로컬 검증 로직을 특정 컨트롤러 메서드에만 적용할 수 있습니다.

@RestController
public class MyController {

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.addValidators(new FooValidator());
    }
}

@InitBinder 애노테이션을 통해 WebFlux에서도 커스텀 검증 논리를 적용할 수 있습니다.

요약

  • 글로벌 검증: Spring MVC에서는 Bean Validation(JSR-303/JSR-380)이 클래스패스에 있는 경우 자동으로 LocalValidatorFactoryBean이 글로벌 Validator로 등록됩니다.
  • 글로벌 Validator 커스터마이징: WebMvcConfigurer 또는 WebFluxConfigurergetValidator() 메서드를 오버라이드하여 글로벌 Validator를 커스터마이징할 수 있습니다.
  • 로컬 Validator: WebDataBinder@InitBinder를 사용하여 컨트롤러 내에서 로컬 검증기를 등록할 수 있습니다.
  • WebFlux: reactive 스택(Spring WebFlux)에서도 유사한 검증 지원이 제공되며, @Valid@Validated 애노테이션을 사용해 로컬 및 글로벌 검증기를 설정할 수 있습니다.

Spring MVC와 WebFlux에서 검증을 설정하고 커스터마이징함으로써, 동기식 및 비동기식 환경에서 애플리케이션 데이터의 정확성을 보장할 수 있습니다.

'Spring Framework > Web on Servlet Stack' 카테고리의 다른 글

Content Types  (0) 2024.10.15
Interceptors  (1) 2024.10.14
Type Conversion  (0) 2024.10.14
MVC Config API  (0) 2024.10.14
Enable MVC Configuration  (0) 2024.10.14