Validation/Data Binding
Validation
-
유효성 검사
-
사용자 또는 타 서버의 요청(http request) 내용에서 잘못된 내용이 있는지 확인하는 행위
Validation의 종류
- 데이터 검증
- 필수 데이터의 존재 유무
- 문자열의 길이나 숫자형 데이터의 경우 값의 범위
- email, 신용카드 번호 등 특정 형식에 맞춘 데이터
- 비즈니스 검증
- 서비스 정책에 따라 데이터를 확인하여 검증
- 배달앱인 경우 배달 요청을 할 때 해당 주문건이 결제 완료 상태인지 확인 등
- 경우에 따라 외부 API를 호출하거나 DB의 데이터까지 조회하여 검증하는 경우도 존재
- 서비스 정책에 따라 데이터를 확인하여 검증
Spring의 Validation
- 스프링은 웹 레이어에 종속적이지 않은 방법으로 밸리데이션을 하려고 의도하고 있다
- 주로 아 래 두가지 방법을 활용하여 밸리데이션 진행(둘다 데이터 검증에 가까움)
1. Java Bean Validation
- JavaBean 기반으로 간편하게 개별 데이터를 검증
- 요즘에 가장 많이 활용되는 방법 중 하나이며, JavaBean 내에 어노테이션으로 검증방법을 명시함
1
2
3
4
5
6
7
8
9
10
11
public class MemberCreationRequest {
@NotBlank(message="이름을 입력해주세요.")
@Size(max=64, message="이름의 최대 길이는 64자 입니다.")
private String name;
@Min(0, "나이는 0보다 커야 합니다.")
private int age;
@Email("이메일 형식이 잘못되었습니다.")
private int email;
// the usual getters and setters...
}
위처럼 요청 dto에 어노테이션으로 명시 후 아래처럼 @Valid 어노테이션을 해당 @RequestBody에 달게 되면, Java Bean Validation을 수행한 후 문제가 없을 때만 메서드 내 부로 진입이 된다.
- 검증 중 실패가 발생하면? : MethodArgumentNotValidException이 발생
1
2
3
4
5
@PostMapping(value = "/member")
public MemeberCreationResponse createMember(
@Valid @RequestBody final MemeberCreationRequest memeberCreationRequest) {
// member creation logics here...
}
2. Spring validator 인터페이스 구현을 통한 validation
- supports(): 이 validator가 동작할 조건을 정의, 주로 class의 타입을 비교
- validate(): 원하는 검증을 진행한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Person {
private String name;
private int age;
// the usual getters and setters...
}
public class PersonValidator implements Validator {
/**
* This Validator validates only Person instances
*/
public boolean supports(Class clazz) {
return Person.class.equals(clazz);
}
public void validate(Object obj, Errors e) {
ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
Person p = (Person) obj;
if (p.getAge() < 0) {
e.rejectValue("age", "negativevalue");
} else if (p.getAge() > 110) {
e.rejectValue("age", "too.darn.old");
}
}
}
Data Binding
- 사용자나 외부 서버의 요청 데이터를 특정 도메인 객체에 저장해서 우리 프로그램에 Request에 담아주는 것
Converter<S,T> Interface
- S(Source)라는 타입을 받아서 T(Target)이라는 타입으로 변환해주는 Interface
1
2
3
4
5
package org.springframework.core.convert.converter;
public interface Converter<S, T> {
T convert(S source);
}
Formatter
- 특정 객체와 String 간의 변환을 담당
- Formatter도 Converter와 마찬가지로 Spring Bean으로 등록하면 자동으로 ConversionService에 등록시켜주기 때문에 필요(요청/응답 시 해당 데이터 타입이 있는 경우) 에 따라 자동으로 동작하게 된다.
- Formatter예제
- print: API 요청에 대한 응답을 줄 때, Date형식으로 된 데이터를 특정 locale에 맞춘 String으로 변환
- parse: API 요청을 받아올 때, String으로 된 “2021-01-01 13:15:00” 같은 날짜 형식의 데 이터를 Date로 변환하도록 함
1
2
3
4
5
6
7
8
9
10
11
12
13
package org.springframework.format.datetime;
@Component
public final class DateFormatter implements Formatter<Date> {
public String print(Date date, Locale locale) {
return getDateFormat(locale).format(date);
}
public Date parse(String formatted, Locale locale) throws ParseException {
return getDateFormat(locale).parse(formatted);
}
// getDateFormat 등 일부 구현은 핵심에 집중하기 위해 생략...
}
댓글남기기