유효성 검사 활용
스프링부트에서 유효성 검사를 하기 위해 사용하는 Validation 어노테이션을 이용하는 방법에 대해 알아보겠습니다.
@Validated 활용
- @Valid : 유효성 검사를 수행하는 어노테이션
- @Validated
- 별도의 어노테이션으로 유효성 검사를 지원하는데, @Valid 어노테이션의 기능을 포함한다.
- 그룹으로 묶어 대상을 특정할 수 있는 기능이 있다.
[예시] DTO 객체에 그룹 설정
@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ValidatedRequestDto {
//.. 중략
@Min(value = 20, groups = ValidationGroup1.class)
@Max(value = 40, groups = ValidationGroup1.class)
int age;
}
- @Min, @Max 어노테이션의 groups 속성을 사용
- 해당 설정을 이용하여 어느 그룹에 맞춰서 유효성 검사를 실시할 것인지 지정한 것이다.
[예시] @Validated Controller 설정
@RestController
@RequestMapping("/validation")
public class ValidationController {
private final Logger LOGGER = LoggerFactory.getLogger(ValidationController.class);
@PostMapping("/validated")
public ResponseEntity<String> checkValidation(
@Validated @RequestBody ValidatedRequestDto validatedRequestDto
) {
LOGGER.info(validatedRequestDto.toString());
return ResponseEntity.status(HttpStatus.OK).body(validatedRequestDto.toString());
}
@PostMapping("/validated/group1")
public ResponseEntity<String> checkValidation1(
@Validated(ValidationGroup1.class)
@RequestBody ValidatedRequestDto validatedRequestDto
) {
LOGGER.info(validatedRequestDto.toString());
return ResponseEntity.status(HttpStatus.OK).body(validatedRequestDto.toString());
}
@PostMapping("/validated/group2")
public ResponseEntity<String> checkValidation2(
@Validated(ValidationGroup2.class)
@RequestBody ValidatedRequestDto validatedRequestDto
) {
LOGGER.info(validatedRequestDto.toString());
return ResponseEntity.status(HttpStatus.OK).body(validatedRequestDto.toString());
}
@PostMapping("/validated/all-group")
public ResponseEntity<String> checkValidation3(
@Validated({ValidationGroup1.class, ValidationGroup2.class})
@RequestBody ValidatedRequestDto validatedRequestDto
) {
LOGGER.info(validatedRequestDto.toString());
return ResponseEntity.status(HttpStatus.OK).body(validatedRequestDto.toString());
}
}
- @Validated 어노테이션에 특정 그룹을 지정하지 않은 경우 groups 속성을 설정하지 않은 필드에 대해서만 유효성 검사를 실시하게 된다.
- @Validated 어노테이션에 특정 그룹을 설정하는 경우에는 지정된 그룹으로 설정된 필드에 대해서만 유효성 검사를 진행한다.
커스텀 Validation 추가
- 자바 또는 스프링의 유효성 검사 어노테이션에서 제공하지 않은 기능을 사용할 경우가 있다.
- 이 경우 ConstraintValidator와 커스텀 어노테이션을 조합해서 별도의 유효성 검사 어노테이션을 생성할 수 있다.
- ex) 동일한 정규식을 계속 쓰는 @Pattern 어노테이션
[예제] 전화번호 형식 일치 확인 어노테이션
public class TelephoneValidator implements ConstraintValidator<Telephone, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
if (value == null) {
return false;
}
return value.matches("^01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$");
}
}
- 인터페이스를 선언할 때는 어떤 어노테이션 인터페이스 타입인지 지정해야한다.
- ConstraintValidator 인터페이스는 inValid( ) 메서드를 정의하고 있다.
- 해당 메서드를 구현하려면 null에 대한 허용 여부 로직 추가하고, 지정한 정규식과 비교해서 알맞은 형식인지 검사한다.
- false 가 리턴되면 MethodArgumentNotValidException 예외가 발생한다.
[예제] 전화번호 어노테이션 인터페이스
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = TelephoneValidator.class)
public @interface Telephone {
String message() default "전화번호 형식이 일치하지 않습니다.";
Class[] groups() default {};
Class[] payload() default {};
}
- @Target 어노테이션
- 이 어노테이션을 어디서 선언할 수 있는지 정의하는 데 사용한다.
- ex) ElementType.PACKAGE, ElementType.FIELD, ElementType.TYPE, ElementType.METHOD ...
- @Retention 어노테이션
- 실제로 적용되고 유지되는 범위를 의미한다.
- @RetentionPolicy.RUNTIME : 컴파일 이후에도 JVM에 의해 계속 참조된다. 리플렉션이나 로깅에 많이 사용되는 정책이다.
- @RetentionPolicy.CLASS : 컴파일러가 클래스를 참조할 때까지 유지한다.
- @RetentionPolicy.SOURCE : 컴파일 전까지만 유지된다. 컴파일 이후에는 사라진다.
- @Constraint 어노테이션
- Validator와 매핑하는 작업을 수행한다.
- message( ) : 유효성 검사가 실패할 경우 반환되는 메시지를 의미
- groups( ) : 유효성 검사를 사용하는 그룹으로 설정
- payload( ) : 사용자가 추가 정보를 위해 전달하는 값
[예제] 전화번호 어노테이션을 이용한 DTO 클래스
@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ValidatedRequestDto {
//.. 중략
@Telephone
String phoneNumber;
}
반응형
'Book > 스프링부트 핵심가이드' 카테고리의 다른 글
스프링부트 예외 처리 (0) | 2023.11.24 |
---|---|
영속성 전이와 고아 객체 (0) | 2023.11.15 |
연관관계 매핑(of. 다대다(N:N) 매핑) (1) | 2023.11.14 |
댓글