티스토리 뷰

Bean Validation

  • Bean Validation은 엔터프라이즈 레벨의 애플리케이션 개발시 자주 반복되는 유효성 검사 패턴을 정리한 Java EE 표준이다. 레드햇, 오라클 등 세계 굴지의 IT 기업에 종사하는 전문가 집단이 참여하여 표준을 만들었다. 인터페이스를 잘 이해하고 구현체를 활용하면 소스 코드의 가독성을 높아지고 많은 코드를 절약할 수 있다.
  • 1.0(JSR 303)이 최초 버전으로 2009-10-12 발표되었다. [스펙 링크]
  • 1.1(JSR 349)가 2013-04-10 발표되었다. [스펙 링크]
  • 2.0(JSR 380)이 현재 최신 버전으로 2017-08-03 발표되었다. Java 8이 요구되며 그 밑의 버전은 지원하지 않는다. [스펙 링크]
  • JSR 380 스펙의 인터페이스는 javax.validation 그룹의 validation-api 아티팩트에서 확인할 수 있다. [메이븐 저장소 링크] 인터페이스에 대한 대표적인 구현체로는 org.hibernate.validator 그룹의 hibernate-validator 아티팩트가 있다. [메이븐 저장소 링크] Spring Boot 2.0 기반의 프로젝트라면 이미 둘다 적용되어 있어 따로 종속성 관리를 할 필요가 없다.
  • Spring Boot에서의 사용법은 무척 간단하다. 컨트롤러 메써드의 파라메터 레벨에 JSR 380이 제공하는 @Valid 어노테이션만 명시하면 된다.

요청 클래스

  • 클라이언트로부터의 요청 파라메터를 담을 클래스를 아래와 같이 작성한다.
data class CreateFooRequest(

        @JsonProperty("bar")
        @get:NotEmpty(message = "for는 필수 항목입니다")
        val bar: String
) {

    @AssertTrue(message = "bar 커스텀 조건을 만족하지 않았습니다.")
    fun isBarTrue(): Boolean {
        return false
    }
}
  • 필드 레벨에 JSR 380이 제공하는 유효성 검사 어노테이션을 명시하면 자동으로 유효성 검사를 수행해준다.
  • @AssertTrueJSR 380이 제공하지 않는 별도의 유효성 검사를 작성하고자 할 경우 사용할 수 있다.

@ControllerAdvice

  • 유효성 검사의 결과가 여과없이 클라이언트에게 노출되는 것을 방지하기 위해 컨트롤러 어드바이스 클래스를 아래와 같이 작성한다.
@ControllerAdvice
class FooControllerAdvice {

    @ExceptionHandler(MethodArgumentNotValidException::class)
    @ResponseBody
    fun handleMethodArgumentNotValidException(ex: MethodArgumentNotValidException): ResponseEntity<*> {

        return ResponseEntity(ex.bindingResult.allErrors.get(0).defaultMessage, HttpStatus.BAD_REQUEST)
    }
}
  • 컨트롤러에서 유효성 검사 실패시 발생하는 예외는 2가지가 있다. 메써드 레벨에 @RequestBody가 명시되었을 경우(주로 POST, PUT 요청) MethodArgumentNotValidException 예외가 발생한다. 메써드 레벨에 @RequestBody가 명시되어 있지 않을 경우(주로 GET 요청) @ModelAttribute가 기본 적용되어 BindException이 발생한다. 따라서 2가지 경우에 대한 예외 처리를 작성하면 입맛에 맞는 커스텀 오류 응답을 클라이언트에게 제공할 수 있다 [관련 링크]

@RestController

  • 컨트롤러 클래스를 아래와 같이 작성한다.
@RestController
class FooController {

    @PostMapping("/foos")
    fun createFoo(@RequestBody @Validated request: CreateFooRequest): ResponseEntity<*> {

        return ResponseEntity<Any>(HttpStatus.OK)
    }
}
  • 요청 파라메터 앞에 명시한 @Validated가 유효성 검사를 활성해주는 역할을 한다. (@Valid를 명시해도 된다.)
댓글
댓글쓰기 폼