Spring Boot · 2026-02-17

Spring Boot에서 Hibernate Validator로 입력 검증 구현

Spring Boot 프로젝트에서 Hibernate Validator를 활용해 입력 검증의 원리, 설정, 예제 코드와 오류 처리 방법을 단계별로 설명하는 개발 참고자료

작성일 : 2026-02-17 ㆍ 작성자 : 관리자
post
목차

개요

서버로 들어오는 입력을 검증하지 않으면 예기치 않은 오류와 보안 취약점으로 이어진다. Spring Boot에서 Hibernate Validator를 쓰면 표준 Bean Validation(JSR 380)을 통해 일관된 검증 로직을 유지할 수 있다. 이 글에서는 spring boot hibernate validator와 bean validation spring boot 적용 방법을 초보자도 이해하기 쉽게 정리한다.

Bean Validation 개념

Hibernate Validator와 JSR

Hibernate Validator는 JSR 380(Bean Validation 2.0)을 구현한 라이브러리다. 어노테이션 기반으로 검증 규칙을 선언한다. DTO에 제약 조건을 붙이면 컨트롤러에서 자동으로 검증할 수 있다. spring validation 예제와 함께 살펴보면 흐름을 이해하기 쉽다.

환경 설정

의존성 추가

Maven 기반 프로젝트에서는 spring-boot-starter-validation을 추가하면 Hibernate Validator가 함께 포함된다.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

DTO에 검증 어노테이션 적용

입력 검증은 주로 DTO에 선언한다. 기본 어노테이션으로 @NotNull, @NotBlank, @Size, @Email, @Min, @Max 등을 사용한다.

package com.example.dto;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

public class UserDto {

  @NotBlank(message = "이름은 필수 항목입니다")
  private String name;

  @Email(message = "올바른 이메일 형식이어야 합니다")
  @NotBlank(message = "이메일은 필수 항목입니다")
  private String email;

  @Size(min = 8, message = "비밀번호는 최소 8자 이상이어야 합니다")
  private String password;

  // getters and setters
}

컨트롤러에서 검증 적용

컨트롤러 메서드 파라미터에 @Valid를 붙이면 스프링이 자동으로 검증을 수행한다. BindingResult를 함께 받으면 검증 결과를 직접 처리할 수 있다.

package com.example.controller;

import com.example.dto.UserDto;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

@RestController
public class UserController {

  @PostMapping("/users")
  public ResponseEntity<String> createUser(@Valid @RequestBody UserDto userDto, BindingResult br) {
    if (br.hasErrors()) {
      // 단순 예시: 첫 번째 오류 메시지 반환
      String error = br.getFieldErrors().get(0).getDefaultMessage();
      return ResponseEntity.badRequest().body(error);
    }
    return ResponseEntity.ok("사용자 생성 성공");
  }
}

커스텀 검증 조건 만들기

표준 어노테이션으로 표현하기 어려운 규칙은 커스텀 애노테이션과 Validator를 구현한다. 아래는 비밀번호 확인 필드 일치 여부를 검증하는 예시다.

package com.example.validation;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Constraint(validatedBy = PasswordMatchesValidator.class)
@Target({ TYPE })
@Retention(RUNTIME)
public @interface PasswordMatches {
  String message() default "비밀번호가 일치하지 않습니다";
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() default {};
}
package com.example.validation;

import com.example.dto.UserDto;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class PasswordMatchesValidator implements ConstraintValidator<PasswordMatches, UserDto> {

  @Override
  public boolean isValid(UserDto dto, ConstraintValidatorContext context) {
    return dto.getPassword() != null && dto.getPassword().equals(dto.getConfirmPassword());
  }
}

전역 예외 처리

BindingResult를 컨트롤러마다 확인하기 번거롭다. @ControllerAdvice를 사용해 검증 실패를 일괄 처리하면 코드가 깔끔해진다.

package com.example.advice;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler(MethodArgumentNotValidException.class)
  public ResponseEntity<String> handleValidationException(MethodArgumentNotValidException ex) {
    String error = ex.getBindingResult().getFieldErrors().get(0).getDefaultMessage();
    return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
  }
}

검증 흐름 요약

  • DTO에 검증 어노테이션을 선언한다.
  • 컨트롤러에서 @Valid로 검증을 트리거한다.
  • BindingResult 또는 @ControllerAdvice로 오류를 처리한다.
  • 복잡한 규칙은 커스텀 Validator로 분리한다.

테스트와 운영 시 고려사항

입력 검증은 단위 테스트와 통합 테스트에서 반드시 확인한다. 에러 메시지는 사용자 친화적으로 작성하고, 내부 로깅에는 상세 원인을 남긴다. 또한 보안상 중요한 검증 로직(예: 권한 관련 값)은 서버 사이드에서 다시 확인한다.

맺음말

spring boot hibernate validator와 bean validation spring boot를 적절히 활용하면 검증 코드의 중복을 줄이고, 유지보수를 쉽게 할 수 있다. 위 예제는 spring validation 예제 관점에서 기본 흐름과 확장 방법을 담았다. 실제 프로젝트에서는 요구사항에 맞춰 메시지 소스, 국제화, 세부 검증 로직을 추가해 활용하면 효과적이다.

spring boot hibernate validator bean validation spring boot spring validation 예제 hibernate validator spring boot validation javax validation validation 예제 controller validation