Spring에서 Validation

MINI·2023년 2월 16일
0

spring

목록 보기
2/3

Validation


서버를 개발 할 때 클라이언트의 입력 값에 따른 유효성 검사는 필수적으로 일어난다.

코드로 유효성 검사를 해도 좋지만 API를 새로 만들 때 마다. 비슷한 유효성 검사 코드를 추가하는건 너무 비효율 적이다.

이런 문제점을 해결하기 위해 Java는 데이터 유효성 검사 표준 기술인 Java Bean Validation을 제공한다.

Java Bean Validation


Java Bean Validation는 Java 클래스의 필드, 또는 메서드에 적용할 수 있는 어노테이션들을 제공 한다. 해당 어노테이션들은 필드 또는 속성의 값으로 충족해야 하는 조건을 정의한다.

자주 사용하는 어노테이션들은 다음과 같다.

  • @Notnull: 해당 어노테이션이 선언된 필드는 null을 허용하지 않는다.
  • @NotEmpty: 해당 어노테이션이 선언된 필드는 null과 ””를 허용하지 않는다.
  • @NotBlank: 해당 어노테이션이 선언된 필드는 null과 ””,” “를 허용하지 않는다.
  • @Size: 해당 어노테이션이 선언된 필드의 허용할 최대 값, 최소 값을 지정한다.
  • @Min: 해당 어노테이션이 선언된 필드의 허용할 최소 값을 지정한다.
  • @Max: 해당 어노테이션이 선언된 필드의 허용할 최대 값을 지정한다.
  • @Email: 해당 어노테이션이 선언된 필드는 이메일 형식이어야 한다.

Spring boot에서 Validation


Constraint 적용

유저 생성 API를 만든다고 가정하고 Request DTO에 Java Bean Validation에서 제공하는 기본 constraint 어노테이션을 적용하였다.

public class CreateUserRequest {
    @NotBlank(message = "닉네임에 공백이 포함될 수 없습니다.")
    private String nickname;
    @NotBlank(message = "이메일이 공백일 수 없습니다.")
    @Email
    private String email;
    @NotNull(message = "생년월일이 공백일 수 없습니다.")
    @PastOrPresent
    private LocalDate birthday;
    @NotBlank(message = "비밀번호가 공백일 수 없습니다.")
    private String password;
}

위 코드를 간단히 설명 하자면 nickname은 null,””,” “ 허용하지 않고,email은 이메일 형식만 허용하고

birthday는 null과 현재시간 보다 전의 시간대만 가능하다.

@Valid 적용

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/user")
public class UserController {
    private final UserService userService;

    @PostMapping
    public CreateUserResponse createUser(@RequestBody @Valid CreateUserRequest request) throws Exception {
        return userService.createUser(request);
    }

}

Dto에 constraint 어노테이션만 붙히면 validation이 발생하지 않는다. 유효성 검사가 필요한 Controller나 Service단에 @Valid 어노테이션을 사용해야 한다.

@Valid가 붙은 객체에 있는 constraint 어노테이션으로 유효성 검사를 한다.

CustomValidation

custom validation으로 닉네임에 특수문자를 허용하지 않는 어노테이션을 만들어 보자.

1. 어노테이션 생성

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = NicknameValidator.class)
public @interface Nickname {
    String message() default "닉네임엔 특수문자를 사용할수 없습니다.";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

우선 @interface로 생성할 어노테이션을 정의합니다. @Constraint 어노테이션을 명시해줘 해당 생성할 어노테이션이 validation 어노테이션이라는것을 명시해줍니다. @Constraint 안에 validatedBy속성으로는 vaidation로직이 들어갈 클래스 명을 정의합니다.

2. Validation 클래스 생성

public class NicknameValidator implements ConstraintValidator<Nickname,String> {
	@Override
	public booleanisValid(String value, ConstraintValidatorContext context) {
		if(value ==null) {
			return false;
		 }
    Pattern pattern = Pattern.compile("!\"#[$]%&\\(\\)\\{\\}@`[*]:[+];-.<>,\\^~|'\\[\\]");
		return !pattern.matcher(value).find();
	 }
}

위의 코드에서 NicknameValidator 클래스는 ConstraintValidator<Nickname , String> 인터페이스를 구현합니다. 이때 첫 번째 제네릭 타입은 유효성 검사 어노테이션 클래스를, 두 번째 제네릭 타입은 검사할 값의 타입을 지정합니다. 이 예제에서는 String 타입의 값을 검사합니다.

pattern에 특수문자를 찾는 정규식을 설정한다음 특수문자가 있으면 false 없으면 true를 반환하게

정의 하였다.

3. 어노테이션 선언

public class CreateUserRequest {
    @NotBlank(message = "닉네임에 공백이 포함될 수 없습니다.")
		@NickName
    private String nickname;
    @NotBlank(message = "이메일이 공백일 수 없습니다.")
    @Email
    private String email;
    @NotNull(message = "생년월일이 공백일 수 없습니다.")
    @PastOrPresent
    private LocalDate birthday;
    @NotBlank(message = "비밀번호가 공백일 수 없습니다.")
    private String password;
}

Request DTO의 nickname필드에 @NickName 어노테이션을 선언 하여 특수문자를 허용하지 않게 하였다.

profile
느리지만 꾸준히

0개의 댓글