[Spring] 검증2 (Bean Validation) 정리

2025. 3. 25. 06:19코딩 도구/백엔드 개발 (Backend Development)

반응형

[Spring] 검증2 (Bean Validation) 정리

스프링 MVC 2 - 검증2(Bean Validation) 정리


이 글은 인프런 김영한님의 "스프링 MVC 2편 - 백엔드 웹 개발 활용 기술" 강의의 '검증2 - Bean Validation' 파트를 수강하고 정리한 내용입니다.

 

검증 기능을 매번 코드로 작성하는 것은 번거롭고, 유지보수에도 불편함이 따른다. 스프링에서는 Bean Validation이라는 표준 기술을 사용해, 검증 로직을 애노테이션 기반으로 간단하게 처리할 수 있다.


정리 및 흐름 요약

  • Bean Validation 소개 및 개념 정리
  • 의존성 추가 및 애노테이션 적용 방법
  • 스프링과 통합된 Bean Validation 적용 방식
  • 글로벌/오브젝트 오류 처리
  • 등록 vs 수정 상황별 검증 조건 분리 방법 (groups 사용)
  • Form 객체 분리로 실무에 맞는 검증 설계
  • HTTP API(JSON 요청)에 Bean Validation 적용 방식

1. Bean Validation 개요

  • JSR-380(Java Bean Validation 2.0) 표준
  • 구현체: Hibernate Validator (가장 널리 사용됨)
  • 목적: 공통적이고 반복적인 검증 로직을 애노테이션 기반으로 간단히 처리
@NotBlank
@Range(min = 1000, max = 1000000)
@Max(9999)

2. 적용을 위한 설정

의존성 추가 (Gradle)

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

애노테이션 예시 (Item 클래스)

@NotBlank private String itemName;
@NotNull @Range(min = 1000, max = 1000000) private Integer price;
@NotNull @Max(9999) private Integer quantity;

3. 순수 Bean Validation 테스트 (Junit)

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Item>> violations = validator.validate(item);
  • ConstraintViolation 객체를 통해 오류 메시지, 필드, 객체 등의 정보 확인 가능

4. 스프링과의 통합

  • @Validated or @Valid + BindingResult
  • @ModelAttribute에 바인딩된 객체가 유효성 검사를 자동 수행
@PostMapping("/add")
public String addItem(@Validated @ModelAttribute Item item, BindingResult bindingResult) { ... }
  • 검증 실패 시 FieldError, ObjectError 생성 및 자동 처리
  • errors.properties 파일로 메시지 커스터마이징 가능
NotBlank={0} 공백X
Range={0}, {2} ~ {1} 허용
Max={0}, 최대 {1}

5. 오브젝트 오류 처리

  • 필드 외의 복합 로직 검증은 자바 코드에서 reject() 사용
if (item.getPrice() * item.getQuantity() < 10000) {
    bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
}
  • @ScriptAssert는 비추 (복잡하고 유지보수 어려움)

6. 등록 vs 수정 검증 요구사항 분리

  • 등록: quantity는 최대 9999
  • 수정: quantity 제한 없음, id 필수

문제점

  • 같은 Item 객체에 등록과 수정 시 충돌 발생
  • 해결책:
    • groups 기능 사용
    • Form 객체 분리 (권장)

7. groups 기능 활용

public interface SaveCheck {}
public interface UpdateCheck {}
@NotNull(groups = UpdateCheck.class)
@Max(value = 9999, groups = SaveCheck.class)
@Validated(SaveCheck.class) @ModelAttribute Item item
  • 장점: 조건 분기 없이 하나의 객체로 검증 분리 가능
  • 단점: 유지보수와 가독성이 떨어짐

8. Form 전송 객체 분리 (실무 방식)

등록용

@Data
public class ItemSaveForm {
    @NotBlank private String itemName;
    @NotNull @Range(min = 1000, max = 1000000) private Integer price;
    @NotNull @Max(9999) private Integer quantity;
}

수정용

@Data
public class ItemUpdateForm {
    @NotNull private Long id;
    @NotBlank private String itemName;
    @NotNull @Range(min = 1000, max = 1000000) private Integer price;
    private Integer quantity;
}
  • 컨트롤러에서 Item 객체로 변환 후 저장 처리
  • 검증 충돌 없음, 유지보수 유리함

9. HTTP API + Bean Validation (@RequestBody)

@PostMapping("/api/items/add")
public Object addItem(@RequestBody @Validated ItemSaveForm form, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) return bindingResult.getAllErrors();
    return form;
}
  • @ModelAttribute: 필드 단위 검증, 바인딩 오류 후에도 Validator 적용
  • @RequestBody: 전체 객체 실패 시 Validator 미실행
  • API는 JSON 파싱 실패 시 예외 발생 → 예외 핸들러 필요

마무리 정리

  • Bean Validation은 표준 기반의 편리한 검증 기능
  • 스프링과 완벽하게 통합되어 손쉽게 적용 가능
  • @Valid, @Validated + BindingResult 패턴은 MVC와 API 모두 적용 가능
  • 실무에서는 Form 객체 분리 방식이 유지보수에 가장 적합
반응형