Validate List of Values in Spring
1. 개요
소프트웨어 개발에서 다양한 값을 검증하는 과정은 매우 중요합니다. 이는 애플리케이션에 들어오는 데이터가 올바르고 일관되도록 보장합니다. 검증은 다양한 요소에 기반하여 모든 데이터 유형에 적용될 수 있습니다.
Spring에서는 검증이 내장 도구 및 주석을 통해 간소화 되어, 강력한 검증 논리를 쉽게 구현할 수 있게 합니다.
이 튜토리얼에서는 Spring에서 값의 목록을 검증하는 방법을 배우고, 특정 값만 허용되는 경우도 살펴보겠습니다. 표준 및 맞춤형 검증 접근 방식을 활용함으로써 데이터 무결성을 유지하고 애플리케이션의 원활한 기능성을 보장할 수 있습니다.
2. Spring에서 검증 설정하기
검증을 활성화하려면 pom.xml 파일에 다음의 종속성을 포함해야 합니다:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
이 종속성은 Hibernate Validator를 Spring 애플리케이션에 통합해줍니다.
3. 값의 List 검증하기
직원 역할 목록을 검증해야 한다고 가정해 보겠습니다. 각 역할은 ROLE_로 시작해야 합니다.
우선, Employee DTO 클래스에 역할을 위한 변수를 추가합니다:
@NotEmpty(message = "Roles list cannot be empty")
@Valid
private List<@Pattern(regexp = "ROLE_[A-Z]+", message = "Each role must start with 'ROLE_' and contain uppercase letters only") String> roles;
@NotEmpty 주석은 리스트가 비어 있지 않도록 보장하고, @Pattern 주석은 각 역할이 지정된 형식과 일치하는지 검증합니다.
다음 단계는 검증을 트리거할 수 있도록 컨트롤러 클래스에 메소드를 추가하는 것입니다:
@PostMapping("/validateListAtService")
public ResponseEntity<String> validateRoles(@RequestBody @Validated Employee request) {
return ResponseEntity.ok("Roles are valid!");
}
여기서 @Validated 주석은 Spring이 Employee 객체에 대해 검증을 수행하도록 보장합니다.
마지막으로, 검증 오류를 처리하기 위한 글로벌 예외 처리기 클래스를 작성할 수 있습니다:
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public String handleValidationException(MethodArgumentNotValidException ex) {
return ex.getBindingResult()
.getFieldErrors()
.stream()
.map(e -> e.getDefaultMessage())
.collect(Collectors.joining(","));
}
이제 어떤 상황에서 검증 오류가 발생할 수 있는지 논의해 보겠습니다.
예를 들어, 클라이언트가 유효하지 않은 데이터를 포함한 요청을 보냈다고 가정해 보겠습니다:
{
"roles": ["admin", "ROLE_ADMIN,", ""]
}
검증 규칙에 따르면 역할은 ROLE_로 시작해야 하며 비어 있으면 안 되기 때문에, 응답은 다음과 같습니다:
Each role must start with 'ROLE_' and contain uppercase letters only
글로벌 예외 처리기를 두는 주요 이점은 모든 검증 오류가 일관되게 처리된다는 것입니다. 클라이언트에게 사용자 친화적인 피드백을 제공하고, 개별 컨트롤러에서 오류 처리 로직을 없애면서 코드 중복을 줄여줍니다.
4. 사전에 정의된 목록으로 값 제한하기
지금까지 리스트를 검증하는 한 가지 방법을 살펴보았습니다. 이제 특정 직원의 다양한 부서를 입력하고 싶다고 가정해보겠습니다. 이 기능을 구현하기 위해 입력된 부서 목록이 유효한지 검증하는 맞춤형 주석을 생성할 것입니다.
먼저, 사용자 정의 검증자 주석을 생성합니다:
@Constraint(validatedBy = AllowedValuesValidator.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface AllowedValues {
String message() default "Invalid value";
String[] values();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
이 코드를 이해해 보겠습니다:
- @Constraint: 주석의 논리를 검증할 책임이 있는 클래스 (AllowedValuesValidator)를 지정합니다.
- @Target: 이 주석이 적용될 수 있는 위치를 제한합니다(예: 필드 또는 메소드 매개변수).
- @Retention: 검증을 위해 런타임에 주석이 사용 가능하도록 보장합니다.
- values: 검증을 위한 사전 정의된 허용 값 집합을 수용합니다.
- message: 검증 실패 시 사용자 정의 오류 메시지입니다.
- groups 및 payload: 제약 그룹 및 사용자 정의 메타데이터를 위한 선택적 속성입니다.
다음 단계는 농업 검증기를 구현하는 것입니다:
public class AllowedValuesValidator implements ConstraintValidator<AllowedValues, List<String>> {
private List<String> allowedValues;
@Override
public void initialize(AllowedValues constraintAnnotation) {
allowedValues = Arrays.asList(constraintAnnotation.values());
}
@Override
public boolean isValid(List<String> values, ConstraintValidatorContext context) {
return values != null && values.stream()
.allMatch(allowedValues::contains);
}
}
initialize() 메소드는 @AllowedValues 주석에서 지정된 허용 값을 검색하여 리스트에 저장하고, isValid() 메소드는 값 목록의 모든 요소가 허용 값 목록에 있을 경우 true를 반환합니다. 또한 null 입력을 정상적으로 처리하여 false를 반환합니다.
마지막 단계는 사전 정의된 부서를 나타내는 List
@NotEmpty(message = "Departments list cannot be empty")
@AllowedValues(values = {"Management", "Software Development", "DevOps", "Architect"}, message = "Invalid department provided")
private List<String> department;
@NotEmpty 주석은 리스트가 비어 있지 않도록 보장합니다. 우리의 사용자 정의 주석 @AllowedValues는 Management, Software Development, DevOps, 및 Architect와 같은 유효한 역할을 지정하며, 검증이 실패할 경우 Invalid role provided라는 사용자 정의 오류 메시지를 반환합니다.
5. 결론
이 기사에서는 Spring에서 목록을 검증하는 방법, 특정 값만 허용되는 시나리오를 다루었습니다. @Pattern과 같은 내장 주석 및 사용자 정의 주석을 사용하여 최소한의 노력으로 애플리케이션의 데이터 무결성을 보장할 수 있습니다. @Pattern의 유연성 덕분에 다양한 컨텍스트에서 개별 필드를 검증하는 데도 유용합니다.
항상 그랬듯이 이 기사에 제시된 코드는 GitHub에서 확인할 수 있습니다.