@Valid를 사용해서 @RequestBody 객체를 검증하자

콜트·2021년 3월 12일
0

Edit. 앱 개발기

목록 보기
5/11

시작하기에 앞서, 아래의 사진을 보자.. 정말 끔찍하다. 부끄럽지만 직전 프로젝트에서 실제로 작성했던 코드다.

위 코드는 @RequestBody 요청 객체를 검증하기 위함이었는데, 이런식으로 요청 객체를 처리하다보니 반복되는 코드가 너무 많았고 가독성도 심히 좋지 않았다. 그에 따라 다음과 같은 고민을 하게 되었다.

조금 더 멋지게(?), 깔끔하게 요청을 검증하는 코드를 작성할 수 있는 방법이 없을까?`

코드를 좀 더 섹시하게 작성하고 싶다!

그래서 찾은 것이 @Valid 어노테이션이다. 먼저 아래의 사진을 보면 그 차이를 확연히 볼 수 있다. 반복되는 if에서 탈출하고, 훨씬 깔끔해졌다!


@Valid?


위 사진은 @Valid 어노테이션을 캡쳐한 화면이다. 주석을 해석해보자면 대충 다음과 같은 내용이며 메서드, 필드, 생성자, 파라미터 등에 사용할 수 있다.

개체와 해당 속성에 정의된 제약 조건을 통해 속성, 메서드 매개 변수 또는 메서드 반환 유형을 검증한다.

사용 방법

먼저 build.gradle에 다음과 같은 의존성을 추가해준다.

implementation 'org.springframework.boot:spring-boot-starter-validation'

참고!

SpringBoot가 버전업을 하면서 기존에는 springboot-web 의존성안에 있던 constraints package(앞서 언급했던)가 아예 모듈로 빠졌다고 한다.

그 다음, @RequestBody가 선언된 파라미터에 @Valid를 선언해주면, @RequestBody로 들어오는 객체에 대한 검증을 수행하게 된다.

이때, 검증을 수행할 제약 조건은 앞서 언급한 어노테이션들을 이용해서 아래 사진과 같이 지정해주면 된다. message 속성을 통해 검증을 통과하지 못했을 때 출력할 메시지를 지정해줄 수도 있다.

참고!

@Valid의 유효성 검증을 통과하지 못하면 MethodArgumentValidException이 발생한다. 그러니까, @RestControllerAdvice와 함께 @ExceptionHandler 등을 적절하게 사용하면 펀쿨섹하게(?) 예외 처리를 할 수 있다!

참고자료 - @RestControllerAdvice를 사용해보자

제약 조건


위 사진은 앞의 @Valid가 포함되어 있는 javax.validation 패키지의 일부이다. constraints 내부에 제약조건을 지정할 수 있는 다양한 어노테이션들이 있다. 이름만 봐도 의미를 알기 쉽게 잘 구성되어 있지만 간단하게 짚고 넘어가도록 하겠다(자세한 내용은 직접 뜯어보면서 확인해보시라!).

@AssertFalse

  • 지원 타입 : Boolean, boolean
  • 제약 조건 : null을 허용하며, 값이 false 여야 한다.

@AssertTrue

  • 지원 타입 : Boolean, boolean
  • 제약 조건 : null을 허용하며, 값이 true 여야 한다.

@DecimalMax

  • 지원 타입
    • BigDecimal
    • BigInteger
    • CharSequence
    • byte, short, int, long, and their respective wrappers
    • double, float 타입은 반올림 오류로 인해 지원하지 않는다.
  • 제약 조건 : null을 허용하며, 지정된 maximum 값 보다 값이 작거나 같아야 한다.

@DecimalMin

  • 지원 타입
    • BigDecimal
    • BigInteger
    • CharSequence
    • byte, short, int, long, and their respective wrappers
    • double, float 타입은 반올림 오류로 인해 지원하지 않는다.
  • 제약 조건 : null을 허용하며, 지정된 minimum 값 보다 값이 크거나 같아야 한다.

@Digits

  • 지원 타입
    • BigDecimal
    • BigInteger
    • CharSequence
    • byte, short, int, long, and their respective wrappers
  • 제약 조건 : null을 허용하며, 자릿수가 지정된 허용 범위 내여야 한다.

@Email

  • 지원 타입
    • String
    • CharSequence
  • 제약 조건 : 문자열이 올바른 형식의 이메일 주소여야 하며, null을 허용한다.

@Future

  • 지원 타입
    • Date
    • Calendar
    • Instant
    • LocalDate
    • LocalDateTime
    • LocalTime
    • ...
  • 제약 조건 : null을 허용하며, 현재보다 미래의 시간이어야 한다.

@FutureOrPresent

  • 지원 타입
    • Date
    • Calendar
    • Instant
    • LocalDate
    • LocalDateTime
    • LocalTime
    • ...
  • 제약 조건 : null을 허용하며, 현재와 같거나 미래의 시간이어야 한다.

@Max

  • 지원 타입
    • BigDecimal
    • BigInteger
    • byte, short, int, long, and their respective wrappers
    • double, float 타입은 반올림 오류로 인해 지원하지 않는다.
  • 제약 조건 : null을 허용하며, 지정된 maximum 값보다 값이 작거나 같아야 한다.

@Min

  • 지원 타입
    • BigDecimal
    • BigInteger
    • byte, short, int, long, and their respective wrappers
    • double, float 타입은 반올림 오류로 인해 지원하지 않는다.
  • 제약 조건 : null을 허용하며, 지정된 minimum 값보다 값이 크거나 같아야 한다.

@Negative

  • 지원 타입
    • BigDecimal
    • BigInteger
    • byte, short, int, long, and their respective wrappers
  • 제약 조건 : null을 허용하며, 음수여야 하고 0은 허용하지 않는다.

@NegativeOrZero

  • 지원 타입
    • BigDecimal
    • BigInteger
    • byte, short, int, long, and their respective wrappers
  • 제약 조건 : null을 허용하며, 음수여야 하고 0도 허용한다.

@NotBlank

  • 지원 타입
    • CharSequence
  • 제약 조건 : null을 허용하지 않으며, 공백이 아닌 1자리 이상의 문자열을 포함해야 한다.

@NotEmpty

  • 지원 타입
    • CharSequence (length of character sequence is evaluated)
    • Collection (collection size is evaluated)
    • Map (map size is evaluated)
    • Array (array length is evaluated)
  • 제약 조건 : null을 허용하지 않으며, empty가 아니어야 한다.

@NotNull

  • 지원 타입
    • 모든 타입을 지원한다.
  • 제약 조건 : null이 아니어야 한다.

@Null

  • 지원 타입
    • 모든 타입을 지원한다.
  • 제약 조건 : null이어야 한다.

@Past

  • 지원 타입
    • Date
    • Calendar
    • Instant
    • LocalDate
    • LocalDateTime
    • LocalTime
    • ...
  • 제약 조건 : null을 허용하며, 현재보다 과거의 시간이어야 한다.

@PastOrPresent

  • 지원 타입
    • Date
    • Calendar
    • Instant
    • LocalDate
    • LocalDateTime
    • LocalTime
    • ...
  • 제약 조건 : null을 허용하며, 현재와 같거나 과거의 시간이어야 한다.

@Pattern

  • 지원 타입
    • CharSequence
  • 제약 조건 : null을 허용하며, 지정된 패턴(정규식)에 부합해야 한다.

@Positive

  • 지원 타입
    • BigDecimal
    • BigInteger
    • byte, short, int, long, float, double, and their respective wrappers
  • 제약 조건 : null을 허용하며, 양수여야 하고 0은 허용하지 않는다.

@PositiveOrZero

  • 지원 타입
    • BigDecimal
    • BigInteger
    • byte, short, int, long, float, double, and their respective wrappers
  • 제약 조건 : null을 허용하며, 양수여야 하고 0도 허용한다.

@Size

  • 지원 타입
    • CharSequence (length of character sequence is evaluated)
    • Collection (collection size is evaluated)
    • Map (map size is evaluated)
    • Array (array length is evaluated)
  • 제약 조건 : null을 허용하며, 해당 요소의 평가대상이 지정된 size 값의 범위 내에 포함되어야 한다.

참고자료


profile
개발 블로그이지만 꼭 개발 이야기만 쓰라는 법은 없으니, 그냥 쓰고 싶은 내용이면 뭐든 쓰려고 합니다. 코드는 깃허브에다 작성할 수도 있으니까요.

0개의 댓글