@Validated

코딩냥이·2024년 9월 10일

Annotation

목록 보기
28/34

@Validated

@Validated는 스프링 프레임워크에서 제공하는 어노테이션으로, 그룹 검증 기능과 메소드 레벨의 검증을 가능하게 합니다. 이는 @Valid의 기능을 확장한 스프링 특화 어노테이션입니다.

기능

  • 그룹 검증을 지원합니다.
  • 메소드 파라미터와 반환값에 대한 검증이 가능합니다.
  • 클래스 레벨에서 사용하여 해당 클래스의 모든 메소드에 대해 검증을 활성화할 수 있습니다.

사용 방법

기본적인 사용 방법은 다음과 같습니다:

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Validated
public class UserController {

    @PostMapping("/users")
    public User createUser(@Validated(CreateUser.class) @RequestBody User user) {
        return userService.createUser(user);
    }

    @PostMapping("/users/update")
    public User updateUser(@Validated(UpdateUser.class) @RequestBody User user) {
        return userService.updateUser(user);
    }
}

public class User {
    @NotNull(groups = {CreateUser.class, UpdateUser.class})
    private String username;

    @NotNull(groups = CreateUser.class)
    @Email(groups = {CreateUser.class, UpdateUser.class})
    private String email;

    // getters and setters
}

public interface CreateUser {}
public interface UpdateUser {}

주요 특징

  1. 그룹 검증: 동일한 객체에 대해 상황에 따라 다른 검증 규칙을 적용할 수 있습니다.
  2. 메소드 레벨 검증: 메소드의 파라미터와 반환값에 대해 검증을 수행할 수 있습니다.
  3. 스프링 AOP 기반: 검증 로직이 AOP를 통해 적용되므로 비즈니스 로직과 분리됩니다.
  4. @Valid 포함: @Validated@Valid의 모든 기능을 포함하며, 추가 기능을 제공합니다.

고급 사용법

1. 메소드 파라미터 검증

@Service
@Validated
public class UserService {

    public User createUser(@NotNull @Size(min = 2, max = 30) String username, 
                           @Email String email) {
        // 메소드 구현
    }
}

2. 반환값 검증

@Service
@Validated
public class ProductService {

    @NotNull
    @Size(min = 1)
    public List<Product> getProducts() {
        // 메소드 구현
    }
}

3. 중첩된 객체의 그룹 검증

public class Order {
    @Valid
    @NotNull(groups = {CreateOrder.class, UpdateOrder.class})
    private List<@Validated(CreateOrderItem.class) OrderItem> items;

    // other fields, getters and setters
}

4. 커스텀 검증기와 함께 사용

@Target({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = OrderValidator.class)
public @interface ValidOrder {
    String message() default "Invalid order";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

@Service
@Validated
public class OrderService {

    public void processOrder(@ValidOrder Order order) {
        // 메소드 구현
    }
}

예외 처리

@Validated로 인한 검증 실패 시 ConstraintViolationException이 발생합니다. 이를 처리하는 방법:

@RestControllerAdvice
public class ValidationExceptionHandler {

    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<Map<String, List<String>>> handleValidationErrors(ConstraintViolationException ex) {
        List<String> errors = ex.getConstraintViolations()
                .stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.toList());
        return new ResponseEntity<>(getErrorsMap(errors), new HttpHeaders(), HttpStatus.BAD_REQUEST);
    }

    private Map<String, List<String>> getErrorsMap(List<String> errors) {
        Map<String, List<String>> errorResponse = new HashMap<>();
        errorResponse.put("errors", errors);
        return errorResponse;
    }
}

테스트

@Validated가 적용된 서비스나 컨트롤러를 테스트할 때:

@SpringBootTest
class UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    void whenInvalidUsername_thenThrowsException() {
        assertThrows(ConstraintViolationException.class, () -> {
            userService.createUser("a", "user@example.com");
        });
    }
}

주의사항

  1. 프록시 기반: @Validated는 스프링 AOP 프록시를 통해 동작하므로, 같은 클래스 내의 메소드 호출에는 적용되지 않습니다.
  2. 성능 영향: 과도한 검증은 성능에 영향을 줄 수 있으므로 필요한 곳에만 적용해야 합니다.
  3. 검증 순서: 그룹 검증 시 검증 순서를 고려해야 할 수 있습니다.

베스트 프랙티스

  1. 명확한 그룹 정의: 검증 그룹의 의미와 용도를 명확히 정의하세요.
  2. 계층별 검증: 표현 계층과 서비스 계층에서 각각 적절한 검증을 수행하세요.
  3. 오류 메시지 관리: 검증 오류 메시지를 중앙에서 관리하여 일관성을 유지하세요.
  4. 복잡한 검증 분리: 매우 복잡한 검증 로직은 별도의 Validator 클래스로 분리하세요.
  5. 문서화: API 문서에 각 엔드포인트나 메소드의 검증 규칙을 명확히 기술하세요.

결론

@Validated는 스프링에서 제공하는 강력한 검증 도구입니다. @Valid의 기능을 확장하여 그룹 검증과 메소드 레벨 검증을 가능하게 함으로써, 더욱 세밀하고 상황에 맞는 데이터 검증을 수행할 수 있게 해줍니다. 특히 복잡한 비즈니스 규칙이나 다양한 검증 시나리오가 필요한 엔터프라이즈 애플리케이션에서 유용하게 사용될 수 있습니다. 다만, 과도한 사용은 애플리케이션의 복잡성을 증가시킬 수 있으므로, 적절한 균형을 유지하는 것이 중요합니다.

연관 포스팅

@Valid
@ControllerAdvice
@RestController
@Service
@ExceptionHandler

profile
HelloMeow~!

0개의 댓글