# @Validated

Spring에서의 Validation
Spring BindingResult Spring에서는 BindingResult 객체를 이용해서 검증 오류를 보관하는 기능을 제공한다. 즉, Controller에서 특정 객체에 대해서 검증 오류가 발생하면 BindingResult객체에 담기게 된다. BindingResult의 간단한 사용 예시는 아래와 같다. BindingResult는 위 코드에서 Item 객체에 대한 검증 오류 결과가 저장된다. 다만, 주의해야할점이 있는데, BindingResult는 ModelAttribute 바로 뒤에 위치해야한다고 한다. 그렇다면 굳이 BindingResult를 써야하는 이유가 뭘까? 별도의 Map 컬렉션을 사용해도되지 않을까? BindingResult를 사용함으로써 아래와 같은 이점을 얻을 수 있다. > ModelAttribute 애노테이션을 이용해서 객체를 바인딩할때, 타입 오류에 대한 처리를 자동으로 해준다. **BindingResult를 사용하는
Validation failed for object - Form 전달 객체 null 오류
✏️ 발단 타임리프를 사용해 웹 페이지를 만들던중 폼을 만들 때 페이지에 접속하면 400 오류가 발생하는 현상이 나타났다. web 에 나타난 에러 메시지 intellij 콘솔에서 나타난 경고 로그 메시지를 차근차근 살펴보니 form 전달용 객체의 attractiveCode 필드에서 Null 이 발생되고있다는 의미 같았다. 전달용 Form 객체 ✏️ 원인 폼객체 자체엔 문제가 없어보였다. 참고로 attractiveCode 는 라디오 버튼에서 값을 받아올 필드이다. 처음에는 attractive 라는 필드명을 사용했는데 이 필드명이 사용 불가능한 필드명인가? 라고 생각해 attractiveCode 로 필드명을 바꿨는데도 해결되지 않았다. 알고보니 원인은 데이터타입에 있었다. attractiveCode 의 타입은 Int 로 선언되어있는데 int 는 nu
UnexpectedTypeException
Unexpected / Type / Exception 예상하지 못한 / 타입 / 예외 직역해보면 타입이 맞지않아서 발생한 오류라고 짐작할 수 있다. ✏️ 발단 Post 요청을 매핑하는 method 를 만들어 실행해보니 아래와 같은 message 가 출력되었다. 내가 만든 form 객체가 제대로 작동하지 않았다는 이야기 같다. ✏️ 원인 메시지를 살펴보면 Integet 타입이 문제라는것같은데 아무리 살펴봐도 안될 이유가 없어보였다. 구글링을 통해 확인해본결과 @NotBlank 는 String 타입에만 사용하는 어노테이션이라고 한다. ✏️ 문제 해결 @NotBlank 에서 @NotNull 로 바꿔주니 문제가 해결되었다. ⚠️ 참고로 @Size 도 String 타입에만 사용되는 어노테이션이다. 숫자타입에 사용할 땐 @Range 를 사용하면 된다.
V2.8 WebDataBinder 와 Validated
✏️ Controller 전체에 검증 로직 작동시키기 📍 WebDataBinder (검증기) 적용 @InitBinder 해당 Controller 로 url 이 매핑되면 어노테이션이 선언된 method 가 실행된다. Spring 내부적으로 생성된 WebDataBinder 를 매개변수로 받아서 Controller 의 매핑 method 가 실행되기전 검증을 수행 해준다. 📍 Validated 적용 🔗 Validator 객체에 @Validated 어노테이션을 붙여주면 V2.7 에서 사용한 ItemValidator.validate 를 호출해주지 않아도 된다. 위에서 생성한 @InitBinder method 에서 ItemValidator.supports 로 검증할 수 있는 객체를 판별하고 검증
검증 - Bean Validation
Bean Validation이란, JSR-380에 등재된 Bean Validation 2.0 이라는 표준 기술이다. 즉, 검증을 위한 애노테이션과 여러 인터페이스를 어떻게 구현해야하는지 가이드가 기술되어 있다. Bean Validation을 구현한 구현체중 일반적으로 Hibernate Validator를 사용한다. @Valid, @Validated @Valid 자바 표준 스팩인 JSR-303에 등장한 검증용 애노테이션이다. javax.validation 패키지에 속해 있다. ValidationAutoConfiguration의 LocalValidatorFactoryBean 메서드를 통해 Bean으로 등록된다. ArgumentResolver 단계에서 Controller에 넘어가기전 검증을 진행한다. Argu
Bean Validation - 한계
수정시 검증 요구사항 데이터를 등록할 때와 수정할 때는 요구사항이 다를 수 있다. 등록시 기존 요구사항 타입 검증 가격, 수량에 문자가 들어가면 검증 오류 처리 필드 검증 상품명: 필수, 공백X 가격: 1000원 이상, 1백만원 이하 수량: 최대 9999 특정 필드의 범위를 넘어서는 검증 가격 * 수량의 합은 10,000원 이상 수정시 요구사항 등록시에는 quantity 수량을 최대 9999까지 등록할 수 있지만 수정시에는 수량을 무제한으로 변경할 수 있다. 등록시에는 id 에 값이 없어도 되지만, 수정시에는 id 값이 필수이다. 수정 요구사항 적용 수정시에는 Item 에서 id 값이 필수이고, quantity 도 무제한으로 적용할 수 있다. 수정 요구사항을 적용하기 위해 다음을 적용했다. id : @NotNull 추가 quantity : @Max(9999) 제거 🤞 참고 현
Bean Validation - 스프링 적용
ValidationItemControllerV3 코드 수정 코드 제거 기존에 등록한 ItemValidator를 제거해두자! 오류 검증기가 중복 적용된다. 스프링 MVC는 어떻게 Bean Validator를 사용? 스프링 부트가 spring-boot-starter-validation 라이브러리를 넣으면 자동으로 Bean Validator 를 인지하고 스프링에 통합한다. 스프링 부트는 자동으로 글로벌 Validator로 등록한다. LocalValidatorFactoryBean 을 글로벌 Validator로 등록한다. 이 Validator는 @NotNull 같은 애노테이션을 보고 검증을 수행한다. 이렇게 글로벌 Validator 가 적용되어 있기 때문에, @Valid , @Validated 만 적용하면 된다. 검증 오류가 발생하면, FieldError , ObjectError 를 생성해서 `BindingResult
Bean Validation - 시작
Bean Validation 기능을 어떻게 사용하는지 코드로 알아보자. 먼저 스프링과 통합하지 않고, 순수한 Bean Validation 사용법 부터 테스트 코드로 알아보자. Bean Validation 의존 관계 추가 의존관계 추가 Bean Validation을 사용하려면 다음 의존관계를 추가해야 한다. build.gradle spring-boot-starter-validation의존관계를 추가하면 라이브러리가 추가 된다. Jakarta Bean Validation jakarta.validation-api : Bean Validation 인터페이스 hibernate-validator : 구현체 테스트 코드 작성 item - Bean Validation 애노테이션 적용 검증 애노테이션 @NotBlank : 빈값 + 공백만 있는 경우를 허용하지 않는다. @NotNull : null 을 허용하지 않는다
Bean Validation
검증 기능을 지금처럼 매번 코드로 작성하느 것은 상당히 번거롭다. 특히 특정 필드에 대한 검증 로직은 대부분이 빈 값인지 아닌지, 특정 크기를 넘는지 아닌지와 같이 매우 일반적인 로직이다. 이런 검증 로직을 모든 프로젝트에 적용할 수 있게 공통화하고, 표준화 한것이 바로 Bean Validation 이다. Bean Validation을 잘 활용하면, 애노테이션 하나로 검증 로직을 매우 편리하게 적용할 수 있다. Bean Validation 먼저 Bean Validation은 특정한 구현체가 아니라 Bean Validation 2.0(JSR-380)이라는 기술 표준이다. 쉽게 이야기해서 검증 애노테이션과 여러 인터페이스의 모음이다. 마치 JPA가 표준 기술이고 그 구현체로 하이버네이트가 있는것과 같다. Bean Validation을 구현한 기술중에 일반적으로 사용하는 구현체는 하이버네이트 Validator 이다. 이름이 하이버네이트가 붙어서 그렇지 ORM과는 관련이 없다
@Valid, @Validated
해당 내용을 정리하게된 계기 와 의 차이를 모른 상태로 단순히 데이터 바인딩시 작성한 validation 어노테이션에 따라 검증을 하기 위해 지금까지 사용하였고 이에 대해 코드 리뷰 중 지적을 받아 다시 학습을 하게 되었다. @Valid 지금까지 내가 알고 있던 내용과 동일하다. 데이터 바인딩시 contraint(validation annotaion)에 따라 데이터를 검증한다. @Validated 기능은 와 동일하다. 단 validation 그루핑을 이용하여 원하는 속성만 유효성 검사를 할 수 있도록 만들 수 있다. Constraint Groups Using Constraint Groups Controller
Bean Validation
도메인이나 Dto를 구성하는 필드의 유효성 검사를 해주는 데이터 유효성 검사 표준 기술인 Bean Validation은 반복되는 유효성 검사를 간단하게 할 수 있게 하는 기능이다. 제약 설정 @NotNull 값이 비어있지 않는 제약 @Positive 값이 양수인 제약 @PositiveOrZero 값이 양수이거나 0인 제약 @Min(value=최소값) 값의 최소값 제약 @Max(value=최대값) 값의 최대값 제약 @NotBlank collection의 대한 제약으로 최소 1개 이상의 값이 들어야 있어야 되는 제약 @NotEmpty 값에 대한 공백 제약 @Length(min, max) 값이 가지는 길이 제약 @Valid 컨트롤러에서 위에서 정의한 유효성 검사가 실제로 진행되기 위해서는 검증을 하는 변수에 대해 @Valid를 표시해야 한다. @Validated @Valid의 경우 컨트롤러 단에서 검증

<Spring MVC> 검증1 - Validation
Intro 웹 애플리케이션에서 폼 입력시 숫자를 문자로 작성하는 등의 검증 오류가 발생해서 오류 화면으로 바로 이동하게 되면 사용자는 처음부터 해당 폼으로 다시 이동해서 입력을 해야 한다. 이 경우 사용자 입장에선 매우 불편하다. 웹 서비스는 폼 입력시 오류가 발생하면, 고객이 입력한 데이터를 유지한 상태로 어떤 오류가 발생했는지 알려줘야 한다. 컨트롤러의 중요한 역할 중 하나는 HTTP 요청이 정상인지 검증하는 것이다. > 📌 클라이언트 검증, 서버 검증 클라이언트 검증은 조작할 수 있으므로 보안에 취약하다. 서버만으로 검증하면, 즉각적인 고객 사용성이 부족해진다. 둘을 적절히 섞어서 사용하되, 최종적으로 서버 검증은 필수이다. API 방식을 사용하면 API 스펙을 잘 정의해서 검증 오류를 API 응답 결과에 잘 남겨줘야 한다. 검증 과정 
[Spring] 검증(2) - BeanValidation
본 글은 인프런 김영한님의 스프링 완전 정복 로드맵을 기반으로 정리했습니다. 1. BeanValidation 필드 검증 기능을 매번 코드로 작성하기는 번거롭다. 필드에 대한 검증은 대부분 빈 값인지 아닌지, 특정 범위내에 있는지와 같이 매우 일반적인 경우가 많다. 이 때 애노테이션을 사용하여 다음처럼 검증을 매우 간단하고 명확하게 할 수 있다. 이전 글과 똑같이 상품 데이터의 이름, 가격, 수량에대해 검증하는 예제를 가지고 진행하겠다. 위와같은 애노테이션 기반의 검증을 BeanValidation 이라고 한다. BeanValidation 은 JSR-380 기술 표준으로써 특정한 구현체가 아니다. 일반적으로 구현체로 하이버네이트 Validator를 사용한다. 참고로, 이름만 같을 뿐 ORM 과는 관련 없다. implementation 'org.springframework.boot:spring-boot-starter-validation' Bean

[Spring] @Valid, @Validated를 이용한 데이터 유효성 검증
들어가기에 앞서 request 후에 서버측에서 데이터를 바인딩할때, 데이터가 유효한지(ex. 누락, 최대 크기 초과 등) 검사해야 하는 경우가 있을 수 있다. 그럴 때는 @Valid 또는 @Validated 어노테이션을 이용하여 데이터 유효성 검증을 할 수 있다. 이번 게시물에서는 @Valid와 @Validated의 차이점을 알아보고, 각각의 어노테이션을 사용해서 데이터 유효성 검증을 해보는 방법을 알아본다. 게시물 내용은 필자가 공부하기 위해 적은 내용이기 때문에 오류 사항이 있을 수 있다. 라이브러리 세팅 pom.xml에 다음 코드를 추가한다. 버전은 상황에 맞게 설정하면 된다. @Valid @RequestBody를 통해 데이터를 바인딩하는 경우를 예시로 한다. 다음과 같은 User 클래스가 있다고 하자. 유저 데이터를 서버측으로 보내게 되면 바인딩 형태는 다음과 같을 것이다. 만약 User의 accoun