본 포스팅은 김영한 강사님의 인프런 강의 "스프링 MVC 1편"을 정리한 포스팅입니다.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
https://growth-coder.tistory.com/123
이전 포스팅에 이어서 Bean Validation 사용법을 포스팅해보려 한다.
VIEW 방식
우선 build.gradle에 다음 코드를 추가한다.
implementation 'org.springframework.boot:spring-boot-starter-validation'
이제 어노테이션 기반의 검증을 사용할 수 있다.
클라이언트에서 html form 형식으로 name과 age를 넘겨주면 서버에서는 @ModelAttribute를 사용하여 객체 형식으로 해당 값들을 가져온다.
이 객체의 필드마다 원하는 검증 어노테이션을 달아주면 된다.
@Getter @Setter
public class Person {
@NotBlank
private String name;
@NotNull
private Integer age;
}
동작 순서
- 글로벌 validator를 등록한다.
- validator가 필드에 적용된 어노테이션에 대해 검증을 수행한다.
- 객체에 @Valid, @Validated만 적용하면 알아서 FieldError나 ObjectError를 BindingResult에 담아준다.
참고로 @Validated는 스프링 전용이고 @Valied는 자바 표준이다.
이러한 Bean Validation은 타입 변환에 성공했을 때만 적용한다. 타입 변환에 실패한다 typeMismatch로 FieldError를 추가한다.
필드 오류 메시지를 만드는 방법은 크게 두가지가 있다.
메시지 관리용 파일 생성
우선 어노테이션 검증에 실패했을 때 생성되는 오류 코드를 확인한다.
NotBlank 어노테이션의 경우 다음과 같은 오류 코드들을 생성한다.
NotBlank.person.name
NotBlank.name
NotBlank.java.lang.String
NotBlank
이를 사용하여 메시지 관리용 파일에 다음과 같이 메시지를 적어둔다. 물론 메시지 관리용 파일을 사용할 수 있도록 등록도 해야한다.
<errors.properties>
NotBlank.person.name=이름을 입력하세요
message 속성 사용
위 방식이 아니면 애초에 어노테이션의 message 속성에 에러 메시지를 적어둔다.
이러면 메시지 관리용 파일을 따로 생성할 필요가 없다.
@Getter @Setter
public class Person {
@NotBlank(message = "이름을 입력하세요.")
private String name;
@NotBlank
private Integer age;
}
가장 우선순위는 message 속성에 담긴 메시지이다.
참고로 필드가 아닌 글로벌 오류, 즉 ObjectError의 경우 직접 자바 코드로 검증 후 BindingResult에 넣어주는 편이 좋다.
이렇게 세팅을 마치고나면 컨트롤러에서 @Valid 혹은 @Validated 어노테이션을 달아줘야한다.
@PostMapping("/add")
public String addItemV3(@Validated @ModelAttribute Item item, BindingResult bindingResult, Model model) {
.
.
.
}
이제 Bean Validation 과정에서 오류가 발생하면 bindingResult에 담기게 된다.
view에서 에러 메시지 출력하는 과정은 이전 포스팅과 동일하다.
Rest API에 Bean Validation 적용
지금까지 SSR 방식으로 서버에서 직접 view를 렌더링할 때 Bean Validation 적용 방식을 알아보았다.
그런데 CSR 방식으로 클라이언트에서는 서버에서 데이터만 전달 받아 view를 렌더링한다고 하면 위 방식은 사용하지 못할 것이다.
예를 들어 Rest API에서는 @RequestBody 어노테이션을 사용하여 요청을 받고 @ResponseBody 어노테이션을 사용하는 방식을 택할 수 있는데 여기서도 @Valid와 @Validated를 적용할 수 있다.
먼저 Person 클래스를 만든다.
@Getter @Setter
public class Person {
@NotBlank
private String name;
@NotNull
private Integer age;
}
에러가 존재하면 에러를 출력하는 컨트롤러를 만든다.
@Slf4j
@org.springframework.stereotype.Controller
public class Controller {
@GetMapping
@ResponseBody
public String response(
@Validated @RequestBody Person person,
BindingResult bindingResult
) {
log.info(bindingResult.getAllErrors().toString());
return "ok";
}
}
name 필드는 @NotBlank가 달려있는데 한 번 postman으로 빈 값을 보내보면 다음과 같은 오류가 발생한다.
[Field error in object 'person' on field 'name': rejected value [];
codes [NotBlank.person.name,NotBlank.name,NotBlank.java.lang.String,NotBlank];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable:
codes [person.name,name];
arguments [];
default message [name]];
default message ["오류"]]
필요한 것이 있다면 적절히 꺼내서 사용하면 된다.
위 에러는 검증 과정에서 에러가 발생한다.
그런데 클라이언트가 String 타입을 입력해야하는데 int 타입을 입력하면 HttpMessageConverter가 객체로 변환하는 과정에서 에러가 발생한다.
이런 경우 400에러가 발생한다.
{
"timestamp": "2023-03-08T08:03:30.944+00:00",
"status": 400,
"error": "Bad Request",
"message": "",
"path": "/"
}
'공부 > Spring' 카테고리의 다른 글
[Spring][인프런 스프링 MVC] 파일 업로드 및 저장 방법 (0) | 2023.03.20 |
---|---|
[Spring][인프런 스프링 MVC] 필터와 인터셉터의 차이 (0) | 2023.03.12 |
[Spring] Bean Validation (@Validated, @Valid 사용법) (0) | 2023.03.08 |
[Spring][인프런 스프링 MVC] @ModelAttribute와 검증 (Validation) (0) | 2023.03.07 |
[Spring][인프런 MVC 1편] 로그(logger) 사용법 (0) | 2023.03.06 |
댓글