Spring Boot 애플리케이션을 개발할 때 입력 값의 유효성을 검증하는 것은 중요한 과정입니다. 이를 위해 자주 사용하는 어노테이션 중 하나가 Bean Validation에서 제공하는 @NotNull, @NotEmpty, @NotBlank입니다. 이 글에서는 각 어노테이션의 차이점과 사용법을 예제와 함께 알아보겠습니다.
@NotNull, @NotEmpty, @NotBlank란?
이 세 가지 어노테이션은 Java Bean Validation API(javax.validation.constraints)에서 제공되며, 주로 Spring Boot의 유효성 검사 과정에서 사용됩니다.
각각의 동작 방식은 다음과 같습니다.
어노테이션설명대상 타입
@NotNull | 값이 null이 아니어야 합니다. | 모든 객체 타입 |
@NotEmpty | 값이 null이 아니고, 빈 문자열 또는 컬렉션이 아님 | 문자열, 컬렉션, 배열 등 |
@NotBlank | 값이 null이 아니고, 공백만 포함하지 않아야 함 | 문자열 타입 |
각 어노테이션의 동작 원리
@NotNull
- 검증 조건: 값이 null인지 여부만 검사합니다.
- 사용 예: 필수 입력 값이 반드시 존재해야 할 때 사용.
import javax.validation.constraints.NotNull;
public class UserRequest {
@NotNull(message = "사용자 이름은 필수 입력 값입니다.")
private String name;
}
- 테스트 케이스:
- 입력: name = null → 검증 실패.
- 입력: name = "" → 검증 성공 (빈 문자열 허용).
@NotEmpty
- 검증 조건: 값이 null이 아니고, 비어 있지 않은 경우("" 또는 empty collection)만 통과합니다.
- 사용 예: 문자열이 비어 있지 않아야 하거나, 리스트나 배열에 값이 반드시 존재해야 할 때 사용.
import javax.validation.constraints.NotEmpty;
public class UserRequest {
@NotEmpty(message = "취미 목록은 비어 있을 수 없습니다.")
private List<String> hobbies;
}
- 테스트 케이스:
- 입력: hobbies = null → 검증 실패.
- 입력: hobbies = [] → 검증 실패.
- 입력: hobbies = ["Reading", "Cooking"] → 검증 성공.
@NotBlank
- 검증 조건: 값이 null이 아니고, 공백 문자(" ", "\t")만 포함하지 않아야 합니다.
- 사용 예: 문자열이 공백만 포함해서는 안 되는 경우 사용.
import javax.validation.constraints.NotBlank;
public class UserRequest {
@NotBlank(message = "비밀번호는 공백만으로 구성될 수 없습니다.")
private String password;
}
- 테스트 케이스:
- 입력: password = null → 검증 실패.
- 입력: password = "" → 검증 실패.
- 입력: password = " " → 검증 실패.
- 입력: password = "abc123" → 검증 성공.
차이점 비교
어노테이션null 값 허용빈 문자열 허용 ("")공백 문자만 허용 (" ")
@NotNull | ❌ | ✅ | ✅ |
@NotEmpty | ❌ | ❌ | ✅ |
@NotBlank | ❌ | ❌ | ❌ |
- @NotNull은 null만 체크하므로 빈 값("")이나 공백(" ")은 허용됩니다.
- @NotEmpty는 빈 값("")이나 비어 있는 컬렉션도 허용하지 않습니다.
- @NotBlank는 공백 문자만 포함된 경우도 허용하지 않습니다.
사용 방법
의존성 추가
Spring Boot에서는 기본적으로 Bean Validation API가 포함되어 있습니다. 만약 필요하다면 spring-boot-starter-validation 의존성을 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
컨트롤러에서 사용
유효성 검사를 적용하려면 DTO 클래스에 어노테이션을 추가하고, 컨트롤러 메서드에서 @Valid 또는 @Validated를 사용합니다.
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping
public String createUser(@RequestBody @Valid UserRequest request) {
return "User created with name: " + request.getName();
}
}
DTO 클래스
각 어노테이션을 적절히 사용해 유효성 검사를 적용합니다.
import javax.validation.constraints.NotNull;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotBlank;
public class UserRequest {
@NotNull(message = "이름은 필수 입력 값입니다.")
private String name;
@NotEmpty(message = "취미 목록은 비어 있을 수 없습니다.")
private List<String> hobbies;
@NotBlank(message = "비밀번호는 공백만으로 구성될 수 없습니다.")
private String password;
// Getters and Setters
}
에러 메시지 처리
Spring Boot에서는 기본적으로 유효성 검증 실패 시 에러 메시지를 반환합니다. 이를 커스터마이징하려면 @ControllerAdvice를 사용합니다.
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class GlobalExceptionHandler {
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Map<String, String> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage()));
return errors;
}
}
유의 사항
- 컬렉션과 배열
- @NotBlank는 컬렉션이나 배열에는 사용할 수 없습니다. 이 경우 @NotEmpty를 사용하세요.
- 성능 고려
- 큰 데이터 구조에 대해 검증을 수행할 경우, 필요하지 않은 곳에서 어노테이션을 남발하면 성능 문제가 발생할 수 있습니다.
- 상황에 맞는 선택
- 값만 존재하면 되는 경우: @NotNull
- 빈 값이 허용되지 않는 경우: @NotEmpty
- 공백도 허용되지 않는 경우: @NotBlank
'Spring > Spring' 카테고리의 다른 글
Spring Retry로 안전한 Feign 호출 처리하기 (0) | 2024.11.20 |
---|---|
Spring에서 동일한 타입의 Bean 충돌 문제 해결하기 (1) | 2024.11.19 |
스프링에서 Bean 등록 및 관리: 어노테이션을 통한 의존성 주입 (0) | 2024.11.11 |