Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 백엔드공부
- MariaDB
- 유효성검사
- validated
- DAO 연동 컨트롤러 서비스 설계
- ORM
- 제로베이스 #백엔드 #Java #Spring #개발자 #백엔드공부 #백엔드 스쿨
- Swagger
- auditing
- 개발자
- 스프링 부트 핵심 가이드
- 데이터베이스 연동
- 백엔드
- 인텔리제이
- spring
- 스프링부트실전가이드
- #devops #terraform #state
- 백엔드스쿨
- 제로베이스
- Java
- 리포지토리 인터페이스
- DAO 설계
- JPA
- 엔티티 설계
- 프로젝트 생성
Archives
- Today
- Total
JeongJin's Blog
10. 유효성 검사와 예외 처리 (2) 본문
10.3 스프링 부트에서 유효성 검사
10.3.4 @Validated 활용
- 유효성 검사를 수행하기 위해 @Valid 어노테이션을 선언하였습니다. @Valid 어노테이션은 자바에서 지원하는 어노테이션이며, 스프링도 @Validated 라는 별도의 어노테이션으로 유효성 검사를 지원한다.
- @Validated는 @Valid 어노테이션의 기능을 포함하고 있기 때문에 @Validated 로 변경이 가능하다
- @Validated는 유효성 검사를 그룹으로 묶어 대상을 특정할 수 있는 기능이 있다.
public interface ValidationGroup1 {
}
- ValidationGroup1 인터페이스
public interface ValidationGroup2 {
}
- ValidationGroup2
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class ValidatedRequestDto {
...
@Min(value = 20, groups = ValidationGroup1.class)
@Max(value = 40, groups = ValidationGroup1.class)
//@Min(value = 20)
//@Max(value = 40)
private int age;
@Positive(groups = ValidationGroup2.class)
//@Positive
private int count;
...
}
- @Min, @Max 어노테이션의 groups 속성을 사용해 ValidationGroup1 그룹을 설정하고 @Positive 어노테이션에 ValidationGroup2를 설정을 통해 어느 그룹에 맞춰 유효성 검사를 실시할 것인지 지정
- 실제로 그룹을 어떻게 설정해서 유효성 검사를 실시할지 결정하는 것은 @Validated 어노테이션에서 한다.
@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());
}
- 첫번째 PostMapping에서는 @Validated 어노테이션에 속성을 지정하지 않음
- 두번째 PostMapping에서는 @Validated 어노테이션에 ValidationGroup1 속성 지정
- 세번째 PostMapping에서는 @Validated 어노테이션에 ValidationGroup2 속성 지정
- 네번째 PostMapping에서는 @Validated 어노테이션에 ValidationGroup1, ValidationGroup2 속성 지정
- 요청 데이터를 보면 age와 count는 변수에 대한 유효성 검사를 통과하지 못하는 데이터 입니다. 하지만 첫번째 메서드를 호출 했을 경우 정상적으로 통과하는 것을 확인할 수 있다.
- @Validated 어노테이션에 특정 그룹을 지정하지 않는 경우에는 groups 속성을 설정하지 않은 필드에 대해서만 유효성 검사를 실시한다.
- ValidationGroup1 으로 지정된 age에 대한 에러가 발생
-
- ValidationGroup2 으로 지정된 count에 대한 에러가 발생
- ValidationGroup1, ValidationGroup2 으로 지정된 age, count에 대한 에러 발생
- 위 데이터는 age와 count는 검사를 통과하고 booleanCheck 변수에서 검사를 실패하는 데이터 이지만 정상적으로 응답이 온다
- 정리
- @Validated 어노테이션에 특정 그룹을 설정하지 않은 경우에는 groups가 설정되지 않은 필드에 대해 유효성 검사를 수행
- @Validated 어노테이션에 특정 그룹을 설정하는 경우에는 지정된 그룹으로 설정된 필드에 대해서만 유효성 검사를 수행
10.3.5 커스텀 Validation 추가
- 실무에서는 유효성 검사를 실시할 때 자바 또는 스프링의 유효성 검사 어노테이션에서 제공하지 않는 기능을 써야할 경우도 있다. 이 경우 ConstraintValidator 와 커스텀 어노테이션을 조합해서 별도의 유효성 검사 어노테이션을 생성할 수 있다.
- 동일한 정규식을 계속 쓰는 @Pattern 어노테이션의 경우가 가장 흔한 사례
▶ 전화번호 형식이 일치하는 확인하는 유효성 검사 어노테이션
public class TelephoneValidator implements ConstraintValidator {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return false;
}
return value.matches("01(?:0|1|[6-9][,-]?(\\d{4})[.-]?(\\d{4})$");
}
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validateBy=TelephoneValidator.class)
public @interface Telephone {
String message() default "전화번호 형식이 일치하지 않습니다.";
Class[] groups() default {};
Class[] payload() default {};
}
- @Target : 어디서선언할 수 있는 정의
- @Retention : 해당 어노테이션이 실제로 적용되고 유지되는 범위를 의미
- Retention 적용 범위는 RetentionPolicy를 통해 지정가능
- RetentionPolicy.RUNTIME : 컴파일 이후에도 JVM에 의해 계속 참조합니다. 리플렉션이나로깅에 많이 사용하는 정책
- RetentionPolicy.CLASS : 컴파일러가 클래스를 참조할 때까지 유지합니다.
- RetentionPolicy.SOURCE : 컴파일 전까지만 유지됩니다. 컴파일 이후에는 사라집니다.
- Retention 적용 범위는 RetentionPolicy를 통해 지정가능
- @Constraint : TelephoneValidator와 매핑하는 작업 수행
- Telephone 인터페이스 내부
- message() : 유효성 검사를 실패할 경우 반환되는 메세지
- groups() : 유효성 검사를 사용하는 그룹으로 설정
- payload() : 사용자가 추가 정보를 위해 전달하는 값
// @Pattern(regexp = "01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$")
@Telephone
private String phoneNumber;
- @Pattern 에서 @Telephone 으로 변경 후 테스트를 하면 아래와 같이 출력된다.
'Book Study > 스프링 부트 핵심 가이드' 카테고리의 다른 글
11. 액추에이터 활용하기 (0) | 2023.12.04 |
---|---|
10. 유효성 검사와 예외처리(3) (0) | 2023.11.27 |
10. 유효성 검사와 예외 처리 (1) (0) | 2023.11.20 |
09. 연관관계 매핑 (0) | 2023.11.15 |
08. Spring Data JPA 활용 (4) (2) | 2023.11.08 |