프론트엔드에서 회원가입 시 사용자는 ID, 비밀번호, 이메일, 생년월일 등 다양한 항목을 입력합니다. 대부분의 프로젝트에서는 프론트엔드에서 1차 유효성 검사를 하고, 백엔드에서 2차 검증을 수행한 뒤 회원가입 로직을 진행한다.
처음에는 아래와 같이 직접 유효성 검사 클래스를 만들어 Controller에서 Service 호출 전에 명시적으로 검증하려고 했다.
public class SignUpValidator {
public String checkId(String target) {
}
public String checkLoginId(String target) {
}
public String checkPassword(String target) {
}
public String checkEmail(String target) {
}
public String checkGender(String target) {
}
public LocalDate checkBirthday(LocalDate target) {
}
}
초기 설계 방안으로 utils 패키지에 SignUpValidator 클래스를 만들어 controller에서 service로 회원가입 사이클을 시작하기 전에 SignUpValidator를 수행하려고 했다. 하지만 vaild 로직은 어떤 프로젝트에서도 사용되므로 관련 애노테이션이 있다고 생각하고 찾아보았다.
Spring에서는 이미 이를 위해 표준화된 @Valid, @Validate, @GroupSequence등 여러 애노테이션을 제공하고 있었다.
@Valid는 JSR-303 표준 스펙으로써 빈 검증기(Bean Validator)를 이용해 객체의 제약 조건을 검증하도록 지시하는 어노테이션이다.
JSR 표준의 빈 검증 기술의 특징은 DTO나 VO 객체의 필드에 달린 어노테이션으로 편리하게 검증을 한다는 것이다.
@PostMapping
public String checkId(@RequestBody @Valid SignUpDto signUpDto,
Errors errors) {}
public class SignUpDto {
@NotBlank
private String name;
@NotBlank
private String loginId;
@Pattern(regexp = "(?=.*[0-9])(?=.*[a-zA-Z])(?=.*\\\\W)(?=\\\\S+$).{8,16}\n")
private String password;
}
이렇게 유효성 검사가 필요한 Request 객체에 @Valid 어노테이션을 사용해 유효성 검사를 적용할 수 있다.
| 애노테이션 | 설명 | 적용 대상 |
|---|---|---|
@Null | 값이 null이어야 함 | 모든 타입 |
@NotNull | null이 아니어야 함 | 모든 타입 |
@NotEmpty | null이 아니고, 길이가 0보다 커야 함 (문자열, 컬렉션 등) | 문자열, 컬렉션, 배열 |
@NotBlank | null, 빈 문자열, 공백이 아니어야 함 | 문자열 |
@AssertTrue | 값이 true여야 함 | boolean, Boolean |
@AssertFalse | 값이 false여야 함 | boolean, Boolean |
@Min(value) | 지정된 최소값 이상이어야 함 | 숫자 |
@Max(value) | 지정된 최대값 이하여야 함 | 숫자 |
@DecimalMin(value) | 지정된 실수 최소값 이상 | 실수, 문자열 |
@DecimalMax(value) | 지정된 실수 최대값 이하 | 실수, 문자열 |
@Size(min, max) | 문자열, 배열 등의 길이나 크기가 지정된 범위 내에 있어야 함 | 문자열, 컬렉션, 배열, Map |
@Email | 이메일 형식이어야 함 | 문자열 |
@Pattern(regexp) | 정규식과 일치해야 함 | 문자열 |
@Past | 과거 날짜여야 함 | 날짜 타입 |
@PastOrPresent | 과거나 현재 날짜여야 함 | 날짜 타입 |
@Future | 미래 날짜여야 함 | 날짜 타입 |
@FutureOrPresent | 현재 또는 미래 날짜여야 함 | 날짜 타입 |
@Validated 어노테이션은 org.springframework.validation 안에 있는 어노테이션이다.
공식문서의 내용에 따르면 "Variant of JSR-303's Valid, supporting the specification of validation groups","but also optionally specifying the validation groups for method-level validation in the annotated class."라고 한다. 즉, @Validated 어노테이션은 @Valid의 확장이며, "Validation Group"을 지원한다는 사실을 알 수 있다.
즉, @Validated는 @Valid와 비슷하지만 검증 그룹(Validation Group)을 사용할 수 있는 기능이 추가된 Spring 고유의 애노테이션이다.
public class ValidationGroups {
public interface SignUpGroup { }
public interface UserUpdateGroup { }
}
public class SignUpDto {
// 닉네임: 한글, 영문, 숫자 2~15자
@NotBlank(groups = {ValidationGroups.SignUpGroup.class, ValidationGroups.UserUpdateGroup.class})
@Pattern(
regexp = "^[가-힣a-zA-Z0-9]{2,15}$",
message = "닉네임은 한글, 영문, 숫자 조합 2~15자여야 합니다.",
groups = {ValidationGroups.SignUpGroup.class, ValidationGroups.UserUpdateGroup.class}
)
}
@PostMapping
public String checkId(@RequestBody @Validated(ValidationGroups.SignUpGroup.class) SignUpDto signUpDto, Errors errors)
