개발은 재밌어야 한다
article thumbnail
반응형

Spring Boot 애플리케이션을 개발할 때 입력 값의 유효성을 검증하는 것은 중요한 과정입니다. 이를 위해 자주 사용하는 어노테이션 중 하나가 Bean Validation에서 제공하는 @NotNull, @NotEmpty, @NotBlank입니다. 이 글에서는 각 어노테이션의 차이점과 사용법을 예제와 함께 알아보겠습니다.


1. @NotNull, @NotEmpty, @NotBlank란?

이 세 가지 어노테이션은 Java Bean Validation API(javax.validation.constraints)에서 제공되며, 주로 Spring Boot의 유효성 검사 과정에서 사용됩니다.
각각의 동작 방식은 다음과 같습니다.

어노테이션설명대상 타입

@NotNull 값이 null이 아니어야 합니다. 모든 객체 타입
@NotEmpty 값이 null이 아니고, 빈 문자열 또는 컬렉션이 아님 문자열, 컬렉션, 배열 등
@NotBlank 값이 null이 아니고, 공백만 포함하지 않아야 함 문자열 타입

2. 각 어노테이션의 동작 원리

2.1. @NotNull

  • 검증 조건: 값이 null인지 여부만 검사합니다.
  • 사용 예: 필수 입력 값이 반드시 존재해야 할 때 사용.
<java />
import javax.validation.constraints.NotNull; public class UserRequest { @NotNull(message = "사용자 이름은 필수 입력 값입니다.") private String name; }
 
  • 테스트 케이스:
    • 입력: name = null → 검증 실패.
    • 입력: name = "" → 검증 성공 (빈 문자열 허용).

2.2. @NotEmpty

  • 검증 조건: 값이 null이 아니고, 비어 있지 않은 경우("" 또는 empty collection)만 통과합니다.
  • 사용 예: 문자열이 비어 있지 않아야 하거나, 리스트나 배열에 값이 반드시 존재해야 할 때 사용.
  •  
<java />
import javax.validation.constraints.NotEmpty; public class UserRequest { @NotEmpty(message = "취미 목록은 비어 있을 수 없습니다.") private List<String> hobbies; }
  • 테스트 케이스:
    • 입력: hobbies = null → 검증 실패.
    • 입력: hobbies = [] → 검증 실패.
    • 입력: hobbies = ["Reading", "Cooking"] → 검증 성공.

2.3. @NotBlank

  • 검증 조건: 값이 null이 아니고, 공백 문자(" ", "\t")만 포함하지 않아야 합니다.
  • 사용 예: 문자열이 공백만 포함해서는 안 되는 경우 사용.
<java />
import javax.validation.constraints.NotBlank; public class UserRequest { @NotBlank(message = "비밀번호는 공백만으로 구성될 수 없습니다.") private String password; }
  • 테스트 케이스:
    • 입력: password = null → 검증 실패.
    • 입력: password = "" → 검증 실패.
    • 입력: password = " " → 검증 실패.
    • 입력: password = "abc123" → 검증 성공.

3. 차이점 비교

어노테이션null 값 허용빈 문자열 허용 ("")공백 문자만 허용 (" ")

@NotNull
@NotEmpty
@NotBlank
  • @NotNull은 null만 체크하므로 빈 값("")이나 공백(" ")은 허용됩니다.
  • @NotEmpty는 빈 값("")이나 비어 있는 컬렉션도 허용하지 않습니다.
  • @NotBlank는 공백 문자만 포함된 경우도 허용하지 않습니다.

4. 사용 방법

4.1. 의존성 추가

Spring Boot에서는 기본적으로 Bean Validation API가 포함되어 있습니다. 만약 필요하다면 spring-boot-starter-validation 의존성을 추가

<java />
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
컨트롤러에서 사용

유효성 검사를 적용하려면 DTO 클래스에 어노테이션을 추가하고, 컨트롤러 메서드에서 @Valid 또는 @Validated를 사용합니다.

<java />
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(); } }
 

4.2. DTO 클래스

각 어노테이션을 적절히 사용해 유효성 검사를 적용합니다.

 
<java />
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 }

4.3. 에러 메시지 처리

Spring Boot에서는 기본적으로 유효성 검증 실패 시 에러 메시지를 반환합니다. 이를 커스터마이징하려면 @ControllerAdvice를 사용합니다.

<java />
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; } }

5. 유의 사항

  1. 컬렉션과 배열
    • @NotBlank는 컬렉션이나 배열에는 사용할 수 없습니다. 이 경우 @NotEmpty를 사용하세요.
  2. 성능 고려
    • 큰 데이터 구조에 대해 검증을 수행할 경우, 필요하지 않은 곳에서 어노테이션을 남발하면 성능 문제가 발생할 수 있습니다.
  3. 상황에 맞는 선택
    • 값만 존재하면 되는 경우: @NotNull
    • 빈 값이 허용되지 않는 경우: @NotEmpty
    • 공백도 허용되지 않는 경우: @NotBlank
반응형
profile

개발은 재밌어야 한다

@ghyeong

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!