[Spring] 검증 - Validation, Bean Validation

윤짱·2026년 1월 28일

Spring

목록 보기
14/18
post-thumbnail

강의 정보 : 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술

Validation

  • 컨트롤러의 중요한 역할중 하나는 HTTP 요청이 정상인지 검증하는 것이다.

  • 클라이언트 검증, 서버 검증
    - 클라이언트 검증은 조작할 수 있으므로 보안에 취약하다.
    - 서버만으로 검증하면, 즉각적인 고객 사용성이 부족해진다.
    - 둘을 적절히 섞어서 사용하되, 최종적으로 서버 검증은 필수
    - API 방식을 사용하면 API 스펙을 잘 정의해서 검증 오류를 API 응답 결과에 잘 남겨주어야 함

  • 검증 오류 보관
    Map<String, String> errors = new HashMap<>();
    : 만약 검증 시 오류가 발생하면 어떤 검증에서 오류가 발생했는지 정보를 담아 둔다.
    검증시 오류가 발생하면 errors 에 담아둔다. 이때 어떤 필드에서 오류가 발생했는지 구분하기 위해 오류가 발생한 필드명을 key로 사용한다. 이후 뷰에서 이 데이터를 사용해서 고객에게 친절한 오류 메시지를 출력할 수 있다. 오류 메시지는 errors 에 내용이 있을 때만 출력하면 된다.

  • 특정 필드의 범위를 넘어서는 검증 로직
    - 특정 필드를 넘어서는 오류를 처리할 때에는 필드 이름을 넣을 수 없으므로 globalError라는 key를 사용한다.

BindingResult

스프링이 제공하는 검증 오류를 보관하는 객체이다. 검증 오류가 발생하면 여기에 보관하면 된다. BindingResult 가 있으면 @ModelAttribute 에 데이터 바인딩 시 오류가 발생해도 컨트롤러가 호출된다.

예) @ModelAttribute에 바인딩 시 타입 오류가 발생하면?

  • BindingResult 가 없으면 400 오류가 발생하면서 컨트롤러가 호출되지 않고, 오류 페이지로 이동한다.
  • BindingResult 가 있으면 오류 정보(FieldError )를 BindingResult 에 담아서 컨트롤러를 정상 호

BindingResult에 검증 오류를 적용하는 3가지 방법

  • @ModelAttribute 의 객체에 타입 오류 등으로 바인딩이 실패하는 경우 스프링이 FieldError 생성해서 BindingResult 에 넣어준다.
  • 개발자가 직접 넣어준다.
  • Validator 사용 이것은 뒤에서 설명

주의

  • BindingResult 는 검증할 대상 바로 다음에 와야한다. 순서가 중요하다. 예를 들어서 @ModelAttribute Item item , 바로 다음에 BindingResult 가 와야 한다.
  • BindingResult 는 Model에 자동으로 포함된다.

BindingResult와 Errors

  • org.springframework.validation.Errors
  • org.springframework.validation.BindingResult

BindingResult 는 인터페이스이고, Errors 인터페이스를 상속받고 있다.
실제 넘어오는 구현체는 BeanPropertyBindingResult 라는 것인데, 둘다 구현하고 있으므로 BindingResult 대신에 Errors 를 사용해도 된다. Errors 인터페이스는 단순한 오류 저장과 조회 기능을 제공한다.
BindingResult 는 여기에 더해서 추가적인 기능들을 제공한다. addError()

로 여기서는 BindingResult 를 사용하자. 주로 관례상 BindingResult 를 많이 사용한다.
`BindingRes

Bean Validation

public class Item {

	private Long id;

	@NotBlank
	private String itemName;

	@NotNull
	@Range(min = 1000, max = 1000000)
	private Integer price;

	@NotNull
	@Max(9999)
	private Integer quantity;
	//...
}

이런 검증 로직을 모든 프로젝트에 적용할 수 있게 공통화하고 표준화하는 것이 Bean Validation이다.

Bean Validation 이란?
먼저 Bean Validation은 특정한 구현체가 아니라 Bean Validation 2.0(JSR-380)이라는 기술 표준이다. 쉽게 이야기해서 검증 애노테이션과 여러 인터페이스의 모음이다. 마치 JPA가 표준 기술이고 그 구현체로 하이버네이트가 있는 것과 같다. (ORM과는 관련이 없다.)

스프링 적용

  • 스프링 부트가 spring-boot-starter-validation 라이브러리를 넣으면 자동으로 Bean Validator를 인지하고 스프링에 통합한다.
  • LocalValidatorFactoryBean 을 글로벌 Validator로 등록한다. 이 Validator는 @NotNull 같은 애노테이션을 보고 검증을 수행한다. 이렇게 글로벌 Validator가 적용되어 있기 때문에, @Valid , @Validated 만 적용하면 된다. 검증 오류가 발생하면, FieldError , ObjectError 를 생성해서 BindingResult 에 담아준다.

에러 코드

NotBlank 라는 오류 코드를 기반으로 MessageCodesResolver 를 통해 다양한 메시지 코드가 생성

  • @NotBlank, @Range 등등

BeanValidation 메시지 찾는 순서
1. 생성된 메시지 코드 순서대로 messageSource 에서 메시지 찾기
2. 애노테이션의 message 속성 사용 @NotBlank(message = "공백! {0}")
3. 라이브러리가 제공하는 기본 값 사용 공백일 수 없습니다.

오브젝트 오류

Bean Validation에서 특정 필드(FieldError )가 아닌 해당 오브젝트 관련 오류(ObjectError )는 @ScriptAssert() 를 사용하면 된다. 그러나 보통 관련 부분만 직접 자바 코드로 작성하는 것을 권장한다.

HTTP 메시지 컨버터

@Valid , @ValidatedHttpMessageConverter (@RequestBody )에도 적용할 수 있다.

  • @ModelAttribute 는 HTTP 요청 파라미터(URL 쿼리 스트링, POST Form)를 다룰 때 사용한다.
  • @RequestBody 는 HTTP Body의 데이터를 객체로 변환할 때 사용한다. 주로 API JSON 요청을 다룰 때 사용한다.

@ModelAttribute vs @RequestBody
HTTP 요청 파리미터를 처리하는 @ModelAttribute 는 각각의 필드 단위로 세밀하게 적용된다. 그래서 특정 필드에 타입이 맞지 않는 오류가 발생해도 나머지 필드는 정상 처리할 수 있었다.
HttpMessageConverter@ModelAttribute 와 다르게 각각의 필드 단위로 적용되는 것이 아니라, 전체 객체 단위로 적용된다.
따라서 메시지 컨버터의 작동이 성공해서 ItemSaveForm 객체를 만들어야 @Valid , @Validated 가 적용된다.

  • @ModelAttribute 는 필드 단위로 정교하게 바인딩이 적용된다. 특정 필드가 바인딩 되지 않아도 나머지 필드는 정상 바인딩 되고, Validator를 사용한 검증도 적용할 수 있다.
  • @RequestBody 는 HttpMessageConverter 단계에서 JSON 데이터를 객체로 변경하지 못하면
profile
바르게 살자...

0개의 댓글