일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- GraphQL
- n poem
- 쿼리셋합치기
- 운영체제
- 컨트리뷰팅
- Java
- 2차원배열 정렬
- 프로젝트설정
- 마이크로서비스패턴
- circuitbreaker
- 주니어개발자
- 상속모델
- DI
- bean-validator
- IOC
- Npoem
- bulk_create
- Spring
- SpringBoot
- 일급함수
- circular dependency
- cannot import name
- 함수형프로그래밍
- API문서화
- 객체비교
- django
- resilience4j
- 토이프로젝트
- 좋은코드란
- Not Null constraint failed
- Today
- Total
코딩 하는 가든
spring - validation (유효성 검사) 하기 본문
Validation을 해보자
웹 개발을 하다 보면 서버에 들어온 요청이 서버에서 요구하는 스펙에 잘 맞게 들어왔는지 검사해야 할 필요가 있습니다.
예를 들어 회원가입을 할 때 이름은 필수로 들어와야 한다던지, 나이는 0보다 커야 한다던지 같은 것 입니다.
물론 이런 식으로 들어온 요청에 대해 검사를 할 수도 있을 것입니다.
//이름이 비어있으면 exception을 던진다.
if (request.getName() == null) {
throw Exception;
}
// 나이가 0보다 작으면 exception을 던진다.
if (request.getAge() < 0) {
throw Exception;
}
하지만 점점 커지는 웹 어플리케이션 에서 위처럼 요청에 대한 검사를 하다 보면 필드가 늘어남에 따라 코드의 대부분이 유효성 검사 코드로 뒤덮일 것입니다.
스프링에서는 이런 상황을 방지하기 위해서 손쉽게 Validation을 하기 위 전략 중 하나로 Hibernate Bean Validator를 사용할 수 있습니다.
Hibernate Bean Validator는 유효성 검사를 해야 하는 필드에 @NotEmpty, @NotNull, @Max와 같은 어노테이션을 붙여줌으로써 유효성 검사를 진행할 수 있습니다.
Bean Validator 사용 하기
먼저 Hibernate bean validator에 대한 의존성 설정을 해야 합니다.
pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
스프링 부트 + gradle를 사용할 경우는 다음과 같이 해줍니다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
// 기타 의존성
}
예시를 위해 간단한 회원가입 시 사용할 Dto 클래스를 만들어 보았습니다.
public class MemberDto {
private String realName;
private String password;
private String nickName;
private int age;
}
회원 가입을 위해서는 [이름, 비밀번호, 닉네임, 나이]가 필요합니다.
@RestController
public class MemberController {
@PostMapping("/member")
public String createMember(@RequestBody MemberDto memberDto) {
System.out.println("memberDto.getRealName() = " + memberDto.getRealName());
System.out.println("memberDto.getPassword() = " + memberDto.getPassword());
System.out.println("memberDto.getNickName() = " + memberDto.getNickName());
System.out.println("memberDto.getAge() = " + memberDto.getAge());
// 비지니스 로직이 들어가는 자리.
return "성공!";
}
}
간단하게 "/member"에 MemberDto를 RequestBody로 받아보았습니다.
아래 보이는 것처럼 Postman을 통해 요청을 보내 보니 요청이 제대로 도달한 것을 알 수 있습니다.
하지만 여기서 RealName이나 Password를 보내지 않으면 어떻게 될까요?
Password를 빼고 보내도 Password가 null로 찍힐 뿐 요청을 처리하는데 아무 문제가 없었습니다.
하지만 우리는 요청으로 받는 Request의 Body에 RealName과 Password가 Null이면 요청을 거부하고 예외 처리를 해주고 싶습니다.
그럴 때는 아래와 같이 RequestBody를 받는 부분 앞에 @Valid 어노테이션을 붙여줍니다.
그리고 Dto 클래스에 가서 Non-Nullable 하게 만들고 싶은 필드에 @NotNull 어노테이션을 달아줍니다.
public class MemberDto {
@NotNull
private String realName;
@NotNull
private String password;
private String nickName;
private int age;
}
이 상태에서 다시 Password를 빼고 요청을 보내보면!?
클라이언트에서 요청을 잘못했다는 400 status code와 함께 에러 리스폰스를 응답해 준 것을 볼 수 있습니다.
서버 쪽에는 아래와 같이 MethodArgumentNotValidException이 발생하게 됩니다.
Resolved [org.springframework.web.bind.MethodArgumentNotValidException:
Validation failed for argument [0] in public java.lang.String
garden.practice.validation.MemberController.createMember
(garden.practice.validation.MemberDto):
[Field error in object 'memberDto' on field 'password': rejected value [null];
codes [NotNull.memberDto.password,NotNull.password,NotNull.java.lang.String,NotNull];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [memberDto.password,password];
arguments []; default message [password]]; default message [널이어서는 안됩니다]] ]
우리는 이런 에러를 exception handler를 통해 응답에 메세지를 담아 넘겨주는 등의 행위를 할 수 있을 것입니다.
Bean Validator 에는 @NotNull 어노테이션뿐 아니라 @NotEmpty, @Max, @Min, @Length와 같은 여러 가지 어노테이션이 존재합니다.
어떤 어노테이션이 존재하는지는 공식 문서 (docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-builtin-constraints) 에 가면 자세히 나와 있습니다.
또한 javax.validation.constraints 패키지에 가면 어노테이션의 구성을 볼 수 도 있으니 궁금하신 분들은 찾아보시길 바랍니다.
이렇게 Bean Validation의 사용법에 대해 알아보았습니다.
'Spring (boot)' 카테고리의 다른 글
Spring Webflux에 Resilience4j를 이용해 서킷브레이커 패턴 구현하기 - (2) (0) | 2021.05.05 |
---|---|
Spring Webflux에 Resilience4j를 이용해 서킷브레이커 패턴 구현하기 - (1) (0) | 2021.05.02 |
spring - 스프링에서의 필터 개념 및 예제 (2) | 2020.08.31 |
spring - 의존성 주입을 받는 여러 가지 방법 (0) | 2020.08.02 |
spring - DI의 개념, 그리고 spring에서의 DI와 IoC (2) (0) | 2020.07.26 |