1. 유효성 검사
- 사용자에게 입력받은 데이터가 기준에 부합한지 검사하는 과정임
- 오류나 보안 문제 예방 가능
⇒ 데이터 무결성 보장, 시스템 안정성 확보, 보안 유지 가능!
- 스프링에서 주된 유효성 검사 방법
- Spring Validation + Bean Validation
- Spring Validation : 유효성 검사 기능 (Bean Validation을 기반으로 작동)
- Bean Validation : 유효성 검사 API
- Spring Validation + Bean Validation
2. Spring Validation
- 스프링 프레임워크에서 제공하는 유효성 검사 기능
- Java Bean Validation API를 기반으로 유효성 검사!
- 스프링 MVC와 통합되어 사용
- @Valid, @Validated 사용
- @Valid
- 자바에서 지원 (JSR-303 자바 표준)
- 메서드 인자 또는 클래스에 적용 ⇒ 해당 객체의 유효성 검사
- 스프링 MVC에서 컨트롤러에서 DTO의 유효성 검사 시 주로 사용
@PostMapping("/user") public ResponseEntity<String> createUser(@RequestBody @Valid UserDto userDto) { // 유효성이 검사된 userDto 사용 return ResponseEntity.ok("사용자가 생성되었습니다."); }
- @Validated
- 스프링에서 지원
- @Valid 어노테이션의 기능 포함
- 클래스 레벨에서 사용됨
- 그룹화된 유효성 검사 지원!
@PostMapping("/user") public ResponseEntity<String> createUser(@RequestBody @Validated(UserCreationGroup.class) UserDto userDto) { // UserCreationGroup에 해당하는 유효성 검사가 수행된 userDto 사용 return ResponseEntity.ok("사용자가 생성되었습니다."); } @PostMapping("/user/v2") public ResponseEntity<String> createUserV2(@RequestBody @Validated({UserCreationGroup1.class, UserCreationGroup2.class} UserDto userDto) { // 2개의 그룹에 해당하는 유효성 검사가 수행된 userDto 사용 return ResponseEntity.ok("사용자가 생성되었습니다. (v2)"); }
- @Valid
- 커스텀 유효성 검사 로직 구현 가능한 Validator 인터페이스도 제공
⇒ Spring Validation의 기본 기능 외의 사용자 정의 검증 로직 추가 가능!- Validator 인터페이스 구현 예제 코드
1. 사용자 정의 Validator 클래스 (구현체)
public class UserValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return UserDto.class.equalss(clazz);
}
@Override
public void validate(Object target, Errors errors) {
UserDto user = (UserDto) target;
// name -> 유효성 검사
if(StringUtils.isBlank(user.getName()) {
errors.rejectValue("name", "name.blank", "이름은 필수로 입력해야 합니다!");
}
// email -> 유효성 검사
if(user.getEmail() == null || user.getEmail.matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
errors.rejectValue("email", "email.inValid", "유효한 이메일 주소가 아닙니다!");
}
if(user.getPassword() == null || user.getPassword.length() < 8) {
errors.rejectValue("password", "password.invalid", "유효한 비밀번호가 아닙니다!");
}
}
}
- Supports(Class<?> clazz)
- 주어진 클래스 검사 가능 여부 반환
- validate(Object target, Errors errors)
- target 객체에 대한 유효성 검사 진행
- 오류는 Errors 객체에 추가함
- rejectValue(필드명, 오류코드, 오류메시지에 포함될 인자(배열 형태), 기본 오류메시지)
- 스프링의 Errors 인터페이스에서 제공하는 메서드
- 특정 필드의 유효성 검사 실패 시 해당 필드에 대한 오류 등록하는 기능
2. 컨트롤러
@RestController
public class UserController {
private final UserValidator userValidator;
// 사용자 정의 Validator 의존 주입
@Autowired
public UserController(UserValidator userValidator) {
this.userValidator = userValidator;
}
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addValidators(productValidator);
}
@PostMapping("/user/register")
public String register(@RequestBody UserDto userDto, BindingResult bindingResult) {
userValidator.validate(userDto, result); // 유효성 검사 수행!!
if(result.hasErrors) {
StringBuilder errors = new StringBuilder("에러 발생 : ");
result.getFieldErrors().forEach(error -> {
errors.append(error.getDefaultMessage()).append("; ");
});
return errors.toString();
}
return "유저 등록 성공";
}
}
- @InitBinder
- WebDataBinder에 사용자 정의 Validator 클래스를 등록함
- BindingResult
- 유효성 검사를 수행하고 발생한 오류들은 BindingResult 객체에 담김
3. Bean Validation
- Java EE (Enterprise Edition) 에서 제공하는 표준 유효성 검사 API
- 어노테이션 기반으로 객체의 속성이 유효한지를 검증함
- Hibernate Validator 가 Bean Validation 의 구현체로 가장 많이 사용됨
- 어노테이션 (대표적 : @NotNull, @Min 등) 을 클래스(DTO) 의 필드에 직접 적용
3-1. 유효성 검사 어노테이션 정리
Hibernate Validator 8.0.1.Final - Jakarta Bean Validation Reference Implementation: Reference Guide
3-1-1. 문자열
- @Null : null 값만 허용
- @NotNull : null 값 허용 x
- @NotEmpty : 공백 허용 x, “ “는 허용
- @NotBlank : 공백, “ “ 모두 허용 x
3-1-2. 최대, 최소 → BigDecimal, BigInteger, int, long 등의 타입 지원
- @Min(value = 최솟값) : 최솟값 이상의 값만 허용
- @Max(value = 최댓값) : 최댓값 이하의 값만 허용
3-1-3. 값 범위
- @Positive : 양수만 허용
- @PositiveOrZero : 양수와 0 만 허용
- @Negative : 음수만 허용
- @NegativeOrZero : 음수와 0 만 허용
3-1-4. 시간 → Date, LocalDate, LocalDateTime 등의 타입 지원
- @Future : 현재보다 미래만 허용
- @FutureOrPresent : 현재와 미래만 허용
- @Past : 현재보다 과거만 허용
- @PastOrPresent : 현재와 과거만 허용
3-1-5. 이메일
- @Email : 이메일 형식만 허용 (공백 허용)
3-1-6. true, false
- @AssertTrue : true만 허용, null 체크 x
- @AssertFalse : false만 허용, null 체크 x
3-1-7. 길이 (문자열, 배열, 컬렉션의 길이나 크기)
- @Size(min = 최솟값, max = 최댓값) : 최솟값 이상 최댓값 이하의 범위만 허용
3-1-8. 정규식
- @Pattern(regexp = 정규식) : 정규식 검사
3-2. 예제 코드
@Getter @Setter
public class UserDto {
@NotBlank(message = "이름은 필수로 입력해야 합니다")
private String name;
@Email(message = "이메일 주소가 유효하지 않습니다")
@NotBlank(message = "이메일은 필수로 입력해야 합니다")
private String email;
@Size(min = 6, max = 12, message = "아이디는 6~12자리여야 합니다")
private String id;
@Size(min=8, message = "비밀번호는 8자리 이상이어야 합니다")
private String password;
}
- message = 메시지
- 에러 메시지 설정 가능
4. 통합 예제 (@Valid 사용)
- Spring Validation : Bean Validation API 활용하여 유효성 검사를 수행하는 스프링의 기능임
- 즉, 스프링은 Bean Validation의 규칙 사용하여 유효성 검증함
⇒ 보통 Bean Validation + Spring Validation으로 유효성 검증 (validation) 함 !
4-1. build.gradle에 라이브러리 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
}
- 해당 라이브러리에 Hibernate Validator 포함됨 → Bean Validation API 사용 가능함!
4-2. UserDto
@Getter @Setter
public class UserDto {
@NotBlank(message = "이름은 필수로 입력해야 합니다")
private String name;
@Email(message = "이메일 주소가 유효하지 않습니다")
@NotBlank(message = "이메일은 필수로 입력해야 합니다")
private String email;
@Size(min = 6, max = 12, message = "아이디는 6~12자리여야 합니다")
private String id;
@Size(min=8, message = "비밀번호는 8자리 이상이어야 합니다")
private String password;
}
4-3. 컨트롤러
@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {
@PostMapping
public ResponseEntity<String> createUser(@RequestBody @Valid UserDto userDto) {
// 유효성 검사를 통과한 경우 Created 응답 코드 보냄
return ResponseEntity.status(HttpStatus.CREATED).body("사용자가 생성되었습니다.");
}
}
4-4. 실행 결과
- localhost:8080/api/users 에 POST 방식으로 아래의 요청 본문 (JSON 형태) 포함하여 요청 보냄
{
"name": "",
"email": "invalid-email",
"id": "id123"
"password": "123"
}
- 응답 (JSON)
{
"timestamp": "2024-08-13T12:34:56.789+00:00",
"status": 400,
"error": "Bad Request",
"message": "이름은 필수로 입력해야 합니다, 이메일 주소가 유효하지 않습니다, 아이디는 6~12자리여야 합니다, 비밀번호는 8자리 이상이어야 합니다",
"path": "/api/users"
}
5. 에러 메시지 설정 방법
- Bean Validation → 어노테이션에 message 속성 추가하여 에러 메시지를 추가함
- 동적인 에러 메시지 혹은 더 구체적인 에러 메시지 설정 방법
- 혹은 위의 Spring Validation → 사용자 정의 Validator 클래스에서 정의한 사용자 정의 오류에 대한 구체적인 메시지 설정 방법
1. 프로젝트의 main/resources 폴더 안에 errors.properties 파일 생성
2. errors.properties 에 에러메시지 설정
2-1. 에러코드=에러메시지
password.invalid=잘못된 비밀번호 입니다.
2-2. (rejectValue(필드명, 오류코드, 오류메시지에 포함될 인자(배열 형태), 기본 오류메시지) → 에러메시지에 포함될 인자 사용)
age.min=나이는 {0}세 이상이어야 합니다.