John's Code Journey

[Spring Boot] Validation 검증 본문

IT공부/Spring Boot

[Spring Boot] Validation 검증

Johnnnn 2025. 4. 28. 15:43
728x90

spring boot

📝 Validation 

스프링에서 Validation(검증)은 사용자 입력 데이터를 검증하고, 이를 통해 유효하지 않은 데이터가 애플리케이션에 들어가는 것을 막기 위한 중요한 과정입니다. 특히, 웹 애플리케이션에서 폼 제출이나 API 요청 시 검증은 필수적입니다. 이 글에서는 스프링에서 Validation을 구현하는 방법, 주요 어노테이션, 그리고 @Valid와 @Validated의 차이를 중심으로 자세히 설명합니다.

 

1. 스프링 Validation 개요

스프링 Validation은 주로 Bean Validation API를 기반으로 동작합니다. 이 API는 객체에 대해 유효성 검사를 수행하고, 검증 규칙을 어노테이션을 통해 정의합니다. 스프링은 @Valid@Validated 어노테이션을 통해 이러한 검증을 트리거할 수 있도록 도와줍니다.

왜 Validation이 필요한가?

  • 유효성 검증은 사용자 입력이 올바른지 확인하는 데 중요합니다.
  • 보안신뢰성을 높이고, 예상치 못한 오류나 악의적인 데이터가 시스템에 침투하는 것을 막습니다.
  • 애플리케이션의 품질을 보장합니다.

2. 주요 어노테이션

  • @NotNull: null이 아니어야 함
  • @NotBlank: 공백 문자열이 아니어야 함
  • @Email: 이메일 형식이어야 함
  • @Min, @Max: 최소값, 최대값 제한
  • @Size(min, max): 문자열 길이 제한

3. DTO 클래스에 어노테이션 적용

DTO 클래스에 유효성 검사를 위한 어노테이션을 붙입니다.

import jakarta.validation.constraints.*;

public class UserDTO {

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

    @Min(value = 18, message = "나이는 18세 이상이어야 합니다.")
    private int age;

    @Email(message = "이메일 형식이 올바르지 않습니다.")
    private String email;

    // getter/setter
}

 

4. 컨트롤러에서 검증 실행

  • @Valid 또는 @Validated를 메서드 파라미터에 사용하여 검증을 트리거합니다.
  • BindingResult를 통해 검증 결과를 확인할 수 있습니다.
@PostMapping("/users")
public ResponseEntity<?> createUser(
    @RequestBody @Valid UserDTO userDto,  // 검증 실행
    BindingResult result
) {
    if (result.hasErrors()) {
        return ResponseEntity.badRequest().body(result.getAllErrors());
    }

    return ResponseEntity.ok("사용자 생성 완료");
}

5. @Valid vs @Validated

1. @Valid

  • 소속: javax.validation 패키지 (또는 jakarta.validation 패키지)
  • 기능: DTO 클래스에 선언된 검증 어노테이션들을 기본적으로 실행합니다.
  • 그룹 검증지원하지 않음.
  • 주요 사용처: 메서드 파라미터나 필드에서 사용하여 객체 검증을 수행합니다.

2. @Validated

  • 소속: 스프링 프레임워크 (org.springframework.validation.annotation 패키지)
  • 기능: @Valid와 유사하게 검증을 수행하지만, 그룹 검증지원합니다.
  • 그룹 검증을 통해 특정 검증 그룹을 지정하여 조건별로 검증할 수 있습니다.
  • 주요 사용처: 메서드 파라미터나 클래스에 사용하여 그룹 검증을 포함한 검증을 실행할 수 있습니다.
public interface Create {}  // 회원가입용 검증 그룹
public interface Update {}  // 수정용 검증 그룹

@PostMapping("/users")
public ResponseEntity<?> createUser(@RequestBody @Validated(Create.class) UserDTO userDto) {
    // Create 그룹에 대한 검증만 수행
    return ResponseEntity.ok("회원 가입 성공");
}

@PostMapping("/users/update")
public ResponseEntity<?> updateUser(@RequestBody @Validated(Update.class) UserDTO userDto) {
    // Update 그룹에 대한 검증만 수행
    return ResponseEntity.ok("정보 수정 성공");
}

🤡주요 차이점

  1. 그룹 검증 지원 여부
    • @Valid: 기본 검증만 수행하며, 그룹 검증을 지원하지 않음.
    • @Validated: 검증 그룹을 지정할 수 있어 그룹 검증을 지원함.
  2. 그룹 검증의 용도
    • 그룹 검증은 동일한 객체라도 상황에 맞게 다른 검증을 적용하고자 할 때 유용합니다. 예를 들어, 회원가입할 때와 사용자 정보를 수정할 때 검증하는 필드가 다를 수 있기 때문에 그룹을 나누어 검증할 수 있습니다.
public class UserDTO {

    @NotBlank(groups = Create.class)
    private String username;

    @Min(value = 18, groups = {Create.class, Update.class})
    private int age;

    @Email(groups = Create.class)  // Create 그룹에서만 검증
    private String email;

    // getter/setter
}

여기서 username은 회원가입할 때만 필수이고, age는 회원가입수정 시 모두 검증되고, email은 회원가입에서만 검증됩니다.

 

❓어떤 경우에 @Valid와 @Validated를 사용할까?

  • @Valid: 기본적인 검증을 실행할 때 사용합니다. 예를 들어, 단순히 모든 필드를 검증하고자 할 때 유용합니다.
@PostMapping("/users")
public ResponseEntity<?> createUser(@RequestBody @Valid UserDTO userDto) {
    // 검증 실행
    return ResponseEntity.ok("회원 가입 성공");
}
  • @Validated: 그룹별 검증을 하고 싶을 때 사용합니다. 예를 들어, 회원가입과 수정을 다르게 검증하고 싶을 때 @Validated와 함께 그룹을 지정하여 검증할 수 있습니다.
public interface Create {}  // 회원가입 검증 그룹
public interface Update {}  // 수정 검증 그룹

@PostMapping("/users")
public ResponseEntity<?> createUser(@RequestBody @Validated(Create.class) UserDTO userDto) {
    return ResponseEntity.ok("회원 가입 성공");
}

@PostMapping("/users/update")
public ResponseEntity<?> updateUser(@RequestBody @Validated(Update.class) UserDTO userDto) {
    return ResponseEntity.ok("정보 수정 성공");
}

🎯결론

  • **@Valid**는 기본적인 검증을 위한 어노테이션으로, 그룹을 다루지 않습니다.
  • **@Validated**는 그룹 검증지원하며, 다양한 검증 그룹을 지정하여 조건에 맞는 검증을 수행할 수 있습니다.

따라서, 그룹별로 다르게 검증해야 하는 경우에는 @Validated를 사용하고, 기본적인 검증만 필요한 경우 @Valid를 사용하면 됩니다.