개발 공부/Spring
[SpringBoot] Validation 사용하기
journey
2022. 2. 27. 03:27
728x90
01. Spring Boot Validation
- Validation이란 프로그래밍에 있어서 가장 필요한 부분이다.
- 특히 Java에서는 null 값에 대해서 접근하려고 할 때 null pointer exception발생 함으로, 이러한 부분을 방지하기 위해서 미리 검증을 하는 과정을 Validation이라고 한다.
단순한 코드
public void run(String account, String pw, int age) {
if (account == null || pw == null) {
return
}
if (age == 0) {
return
}
// 정상 Logic
}
문제점
- 검증해야 할 값이 많은 경우 코드의 길이가 길어진다.
- 구현에 따라서 달라 질 수 있지만 Service Logic과의 분리가 필요하다.
- 흩어져 있는 경우 어디에서 검증을 하는지 알기 어려우며, 재사용의 한계가 있다.
- 구현에 따라 달라질 수 있지만, 검증 Logic이 변경되는 경우 테스트 코드 등 참조하는 클래스에서 Logic이 변경되어야 하는 부분이 발생할 수 있다.
Annotations
Annotation | 의미 | 기타 |
@Size | 문자 길이 측정 | Int Type 불가 |
@Notnull | null 불가 | |
@NotEmpty | null, “” 불가 | |
@NotBlank | null, “”, “ “ 불가 | |
@Past | 과거 날짜 | |
@PastOrPresent | 오늘이거나 과거 날짜 | |
@Future | 미래 날짜 | |
@FutureOrPresent | 오늘이거나 미래 날짜 | |
@Pattern | 정규식 적용 | |
@Max | 최대값 | |
@Min | 최소값 | |
@AssertTrue / False | 별도 Logic 적용 | |
@Valid | 해당 object validation 실행 |
Validation 사용하기
- Gradle dependencies
implementation 'org.springframework.boot:spring-boot-starter-validation'
- bean validation spec
- 핸드폰번호 정규식
- ^\d{2,3}-\d{3,4}-\d{4}$
예제 코드
- User
public class User {
private String name;
private int age;
private String email;
private String phoneNumber;
... getter / setter ....
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
", phoneNumber=" + phoneNumber + '\'' +
'}';
}
}
- Controller
@RestController
@RequestMapping("/api")
public class ApiController {
@PostMapping("/user")
public User user(@RequestBody User user) {
System.out.println(user);
return user;
}
}
- Result
Validation
- Controller
import com.example.validation.dto.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
@RequestMapping("/api")
public class ApiController {
@PostMapping("/user")
// Validation에 대한 결과가 바로 에러가 터지지 않고 bindingResult로 값이 들어온다.
public ResponseEntity user(@Valid @RequestBody User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
StringBuilder sb = new StringBuilder();
bindingResult.getAllErrors().forEach(objectError -> {
// 어떤 필드에서 어떤 에러가 났는지 값 가져오기.
FieldError field = (FieldError) objectError;
// 메세지 가져오기
String message = objectError.getDefaultMessage();
System.out.println("field : " + field.getField());
System.out.println("message : " + message);
sb.append("field : " + field.getField());
sb.append("message : " + message);
});
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(sb.toString());
}
// logic
return ResponseEntity.ok(user);
}
}
Validation 에러 보기
- Console 창 결과
-
- 이메일 형식이 ‘asdf@hjkl’이 아닐 때
WARN 1334 --- [nio-9090-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.example.validation.controller.ApiController.user(com.example.validation.dto.User): [Field error in object 'user' on field 'email': rejected value [zzanggu]; codes [Email.user.email,Email.email,Email.java.lang.String,Email]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.email,email]; arguments []; default message [email],[Ljavax.validation.constraints.Pattern$Flag;@35bf8bdf,.*]; default message [올바른 형식의 이메일 주소여야 합니다]] ]
-
- 핸드폰번호 형식이 ‘xxx-xxxx-xxxx’이 아닐 때
WARN 1405 --- [nio-9090-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.example.validation.controller.ApiController.user(com.example.validation.dto.User): [Field error in object 'user' on field 'phoneNumber': rejected value [01012345678]; codes [Pattern.user.phoneNumber,Pattern.phoneNumber,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.phoneNumber,phoneNumber]; arguments []; default message [phoneNumber],[Ljavax.validation.constraints.Pattern$Flag;@34f826d2,^\d{2,3}-\d{3,4}-\d{4}$]; default message ["^\d{2,3}-\d{3,4}-\d{4}$"와 일치해야 합니다]] ]
- API 결과