Spring Boot (18) 유효성 검사 실습

넙데데맨·2022년 9월 28일
0
post-custom-banner

유효성 검사 실습

기본 유효성 검사

의존성 추가

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>

ValidRequestDto 추가

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class ValidRequestDto {
    @NotBlank
    String name;

    @Email
    String email;

    @Pattern(regexp = "01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$")
    String phoneNumber;

    @Min(value = 20) @Max(value = 40)
    int age;

    @Size(min=0, max=40)
    String description;

    @Positive
    int count;

    @AssertTrue
    boolean booleanCheck;
    
}

유효성을 검증할 필드에 어노테이션으로 조건을 설정해준다.
유효성 검증 어노테이션

ValidationController 추가

@RestController
@RequestMapping("/validation")
public class ValidationController {

    @PostMapping("/valid")
    public ResponseEntity<String> checkValidationByValid(
            @Valid @RequestBody ValidRequestDto validRequestDto){
        return ResponseEntity.status(HttpStatus.OK).body(validRequestDto.toString());
    }
}

다음과 같이 phoneNumber에 유효하지 않은 값을 넣을 시 400 오류가 발생한다.


로그 라이브러리를 추가하지 않아서 확인해보지 못했지만 로그 라이브러리 사용 시 실패한 개수 및 실패한 지점을 확인할 수 있다.

Validated를 사용한 검사

1. ValidationGroup1, ValidationGroup2 인터페이스 생성

2. ValidatedDto 생성

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class ValidatedRequestDto {
    @NotBlank
    String name;

    @Email
    String email;

    @Pattern(regexp = "01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$")
    String phoneNumber;

    @Min(value = 20,groups = ValidationGroup1.class)
    @Max(value = 40,groups = ValidationGroup1.class)
    int age;

    @Size(min=0, max=40)
    String description;

    @Positive(groups = ValidationGroup2.class)
    int count;

    @AssertTrue
    boolean booleanCheck;
}

groups 속성을 사용해 어느 그룹에 맞춰 유효성 검사를 실시할 것인지 지정한다.

@RestController
@RequestMapping("/validation")
public class ValidationController {
    private final Logger LOGGER = LoggerFactory.getLogger(ValidationController.class);

//    @PostMapping("/valid")
//    public ResponseEntity<String> checkValidationByValid(
//            @Valid @RequestBody ValidRequestDto validRequestDto){
//        return ResponseEntity.status(HttpStatus.OK).body(validRequestDto.toString());
//    }

    @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/gruop2")
    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 어노테이션에 해당 그룹을 지정하면 해당 그룹에 맞게 유효성 검사를 실시한다.

커스텀 Validation 추가

ConstraintValidator 인터페이스 구현 클래스 생성

public class TelephoneValidator implements ConstraintValidator<Telephone, String> {
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context){
        if(value==null) {
            return false;
        }
        return value.matches("01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$");
    }
}

ContraintValidator 인터페이스에서 정의한 인터페이스 작성

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = TelephoneValidator.class)
public @interface Telephone {
    String message() default "전화번호 형식이 일치하지 않음";
    Class[] groups() default {};
    Class[] payload() default {};

}

정의한 유효성 검사 어노테이션 테스트

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class ValidatedRequestDto {
    @NotBlank
    String name;

    @Email
    String email;

    @Telephone
    String phoneNumber;

    @Min(value = 20)
    @Max(value = 40)
    int age;

    @Size(min=0, max=40)
    String description;

    @Positive
    int count;

    @AssertTrue
    boolean booleanCheck;
}

책에 groups를 지정하지 않아 오류가 뜨는 것이 당연하다고 하는데 그 해결방법은 알려주지 않았다 다음파트에서 알려준다는데 그 파트가 책에 없음ㅡ.ㅡ
그래서 groups에 처음에 만들어서 적용했던 ValidationGroup1.class도 넣어보고 이것저것 해봤지만 해결이 안되길래 답답한 상태로 남겨둔 채 일단 패스

profile
차근차근
post-custom-banner

0개의 댓글