스프링 프로젝트를 진행하다 보면 데이터 검증(validation)은 필수적입니다. 그러나 간단한 검증조차 매번 반복된 코드를 작성하게 되면 유지보수는 어렵고 비효율적입니다. 이럴 때 Bean Validation을 활용하면 편리하게 검증 로직을 관리할 수 있습니다.
Bean Validation(JSR-380)은 자바에서 사용하는 데이터 유효성 검사 표준입니다. 간단한 애노테이션으로 다양한 검증 로직을 표준화하고 공통화할 수 있습니다. 대표적인 구현체는 Hibernate Validator이며, 스프링 부트에서 간편하게 연동됩니다.
주요 애노테이션 예시:
@NotNull: null 허용 X@NotBlank: 빈 문자열과 공백 허용 X@Range(min, max): 숫자의 범위 지정@Max(value): 최대값 지정@Data
public class ItemSaveForm {
@NotBlank(message = "상품명은 필수입니다.")
private String itemName;
@NotNull(message = "가격은 필수입니다.")
@Range(min = 1000, max = 1000000, message = "가격은 1,000원 ~ 1,000,000원 사이여야 합니다.")
private Integer price;
@NotNull(message = "수량은 필수입니다.")
@Max(value = 9999, message = "수량은 최대 9999까지 입력 가능합니다.")
private Integer quantity;
}
@PostMapping("/add")
public String addItem(@Validated @ModelAttribute ItemSaveForm form, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "addForm";
}
// 성공 로직
itemService.save(form);
return "redirect:/items";
}
필드 간 복합적인 검증은 자바 코드로 직접 처리하는 방식을 권장합니다.
if (form.getPrice() != null && form.getQuantity() != null) {
int totalPrice = form.getPrice() * form.getQuantity();
if (totalPrice < 10000) {
bindingResult.reject("totalPriceMin", "총 금액은 최소 10,000원 이상이어야 합니다.");
}
}
실무에서는 등록과 수정 요구사항이 다를 경우가 많아 DTO를 명확히 분리해 사용하는 것이 효과적입니다.
ItemSaveForm: 등록 시 필요한 검증 조건ItemUpdateForm: 수정 시 필요한 검증 조건이러한 방식을 사용하면 조건에 따른 검증 충돌을 피할 수 있으며, 유지보수성도 향상됩니다.
API 요청에서도 Bean Validation을 간편히 활용할 수 있습니다.
@RestController
public class ItemApiController {
@PostMapping("/api/items")
public ResponseEntity<?> addItem(@RequestBody @Validated ItemSaveForm form, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return ResponseEntity.badRequest().body(bindingResult.getAllErrors());
}
// 성공 로직
return ResponseEntity.ok().body(form);
}
}
Bean Validation을 사용하면 중복된 검증 로직을 제거하고, 일관된 방식으로 데이터 유효성을 관리할 수 있습니다. 특히 DTO를 상황별로 분리하고 명확하게 검증 조건을 정의하는 것이 현업에서 가장 선호하는 방식입니다.

