9/1~1/26일까지 현장실습을 마치고 이제 열심히 공부할 시간만 남았다. 나는 끈기 있게 열심히 공부를 할생각이다.
Validation in Spring
Validation이란?
유효성 검증
주로 사용자 또는 (다른) 서버의 요청(http request)내용에서 잘못된 내용이 있는 지 확인하는 단계를 뜻한다.
Validation 종류
여러 세부적인 단계가 있지만 개발자가 챙겨야하는 검증은 크게 두가지라고 하셨다.
데이터 검증
- 단순하게 데이터 하나하나를 살피는 검증 즉, 필수 데이터의 존재유무
- 문자열의 길이나 숫자형 데이터의 경우 값의 범위
- email,신용카드 번호 등 특정 형식에 맞춘 데이터
비지니스 검증
- 서비스에 정책에 따라 데이터를 확인하여 검증하는 것들이다
- ex) 배달앱경우 배달요청할때 해당 주문건이 결제완료상태인지 확인
- 경우에 따라 외부 API를 호출하거나 DB의 데이터까지 조회하여 검증하는 경우까지도 존재한다.
Spring의 Validation
스프링은 웹 레이어에 종속적이지 않은 방법으로 벨리데이션을 하려고 의도하고 있으며 주로 아래 두가지 방법을 활용하여 벨리데이션을 진행(둘다 데이터 검증에 가까움)
Java Bean Validation
JavaBean이란? 주로 데이터를 쉽게 저장했다가 꺼낼수있게 프로퍼티와 getter&setter로 단순한 구조로 이뤄진 클래스라고 볼수 있다
JavaBean 기반으로 간편하게 개별 데이터를 검증
요즘 가장많이 활용되는 방법 중 하나, JavaBean내 애노테이션으로 검증방법을 명시
(@NotBlank,@Size,@Min,@Email 처럼간단하게 애노테이션을 붙여서 사용할 수 있다.)

위에 코드처럼 요청 dto에 애노테이션으로 명시 후 아래처럼 @Valid 애노테이션을 해당 @RequestBody에 달게 되면, Java Bean Validation을 수행한 후 문제가 없을 때만 메서드 내부로 진입이 된다
검증 중 실패가 발생하면 : MethodArgumentNotValidException이 발생

Spring validator 인터페이스 구현을 통한 validation

Person이라는 javaBen 객체가 있을때, 아래는 해당 인스턴스에서만 활용되는 validator이다.
인터페이스에 있는 두개의 메서드는 아래와 같은 역할은한다.
- supports: 이 validator가 동작할 조건을 정의, 주로 class 타입을 비교
- validate: 원하는 검증을 진행

강사님도 초반에는 Spring validator를 사용했는데 JavaBean Validation을 요즘은 주로 사용하신다고 함
Validation 수행 시 주의사항 및 패턴
주의사항
- validation 이 너무 여러 군데 흩어져있으면 테스트 및 유지보수성이 떨어짐
- 중복된 검증: 정책 변경 시 모든 중복 코드를 수정해야함
- 다른 검증: 여러 군데서 다른 정책을 따르는 검증이 수행될 수 있다.
- 가능한 validation은 로직 초기에 수행 후 실패시에는 exception을 던져 빨리 처리하는것이 편리하다
실무 활용패턴
- 강사님 주 사용 패턴
- 요청 dto에서 Java Bean Validation으로 단순데이터(유무,범위,형식 등)를 1차 검증
- 로직 초기에 2차로 비지니스 검증 수행 후 실패 시에는 Custom Exception(ErrorCode,ErrorMessage 를 입력)해서 예외를 던지도록 하고 예외처리하여 응답 생성
- Spring Validator의 (강사님이 생각하는)장단점
- 장점: Java Bean Validation에 비해 조금 더 복잡한 검증이 가능
- 단점
- Validation을 수행하는 코드를 찾기가 (상대적으로) 어렵다
- 완전히 데이터만 검증하는 것이 아니기 떄문에 일부 비지니스적인 검증이 들어가는 경우가 있음
- 이 경우 비지니스 검증 로직이 여러군데로 흩어지기 떄문에 잘못된검증(중복검증, 다른 정책을 따르는 검증)을 수행할 가능성이 높아짐
Data Binding
사용자나 외부 서버의 요청 데이터를 특정 도메인 객체에 저장해서 우리 프로그램에 Request에 담아주는것을 뜻한다.
Validation이 잘되어서 데이터가 Request dto에 들어오게된 데이터를 내부 원리를 알 수 있게되는 시간이 된다고한다.
Converter<S,T> Interface
데이터 바인딩은 실제로 처리할때 주로 쓰는 방식이 Converter Interface를 활용한다고 하셨다.(두개의 타입을 받아서 하는 인터페이스)
S(Source)라는 타입을 받아서 T(Target)이라는 타입으로 변환해주는 Interface

강사님이 활용한 Converter<S,T> Interface
파라미터에 json형식 문자열이 담겨오는 경우 해당 문자열을 곧바로 특정 dto에 담고 싶을 때 사용

@Component애노테이션을 붙여서 Bean으로 등록함
이와 비슷하게 PathhParameter나 기타 특수한 경우의 데이터를 특정 객체에 담고 싶은 경우
- Converter를 만들어서 Spring에 Bean으로 등록
- 스프링 내 ConversionService라는 내장된 서비스에서 Converter구현체 Bean들을 리스트에 등록
- 외부데이터가 들어오고, Source Class Type-> Target Class Type이 Converter에 등록된 형식과 일치하면 해당 Converter가 동작하는 원리
@RequestBody도 등록된 Converter를 통해서 특정 객체로 바꿔준다는것을 알 수 있었다.
특정 객체와 String간의 변환을 담당(컨버터의 일종이라고 생각할 수 있따)
아래 샘플 코드는 Date <-> String간의 변환을 수행하는 Formatter이다.
- print: API 요청에 대한 응답을 줄 때, Date형식으로 된 데이터를 특정 locale에 맞춘 String으로 변환
- parse : API 요청을 받아올 때, String으로 된 "2021-01-01 13:15:00"같은 날짜 형식의 데이터를 Date로 변환하도록 함

Formatter도 Converter와 마찬가지로 Spring Bean으로 등록하면 자동으로 ConversionService에 등록시켜 주기 때문에 필요(요청/응답 시 해당 데이터 타입이 있는 경우)에 따라 자동으로 동작하게 된다.