기술 노트
[Spring] RESTful API를 위한 첫 조건 Validation, 유효성 검증
REST통신에서 서버가 데이터를 주고 받는 첫 번째 단계의 할 일은 가져온 데이터가 유효한지 검증 하는 과정이다.유효성 검증이란?API 서버로 들어온 데이터가 올바른 데이터인지 검증하는 과정을 말한다. API 서버로 들어오는 데이터는 DTO( Data Transfer Object ) 형태로 들어오게 되는데, 이는 계층간 특별한 로직 없이 순수한 데이터 셋 만을 전송하기위해…

REST통신에서 서버가 데이터를 주고 받는 첫 번째 단계의 할 일은 가져온 데이터가 유효한지 검증 하는 과정이다.
유효성 검증이란?
API 서버로 들어온 데이터가 올바른 데이터인지 검증하는 과정을 말한다.
API 서버로 들어오는 데이터는 DTO( Data Transfer Object ) 형태로 들어오게 되는데, 이는 계층간 특별한 로직 없이 순수한 데이터 셋 만을 전송하기위해 만들어진 객체이다.
Java에서 DTO를 검증하기 위해
@Valid와 @Validated
어노테이션을 메소드 매개변수 앞에 달아서 검증할 수 있다.
@Valid 어노테이션은 javax.validation 패키지에 포함되어있고
@Validated 어노테이션은 스프링 웹 org.springframwork.web.bind.annotation 패키지에 포함되어있다.
public User getUser(@Valid @RequestBody UserDto userDto){ return user(userDto); }@Valid와 @Validation 어노테이션을 사용하면 어노테이션 객체 내부의 검증 패턴이 실행되는데,
주요 검증 어노테이션으로는
- @NotNull: 값이 null이 아닌지 확인합니다.
- @NotEmpty: 문자열이 null이 아니고, 길이가 0이 아닌지 확인합니다.
- @NotBlank: 문자열이 null이 아니고, 공백이 아닌 문자가 하나 이상 포함되어 있는지 확인합니다.
- @Size: 문자열, 컬렉션, 맵 또는 배열의 크기/길이를 제한합니다.
- @Min: 숫자가 지정된 최소값 이상인지 확인합니다.
- @Max: 숫자가 지정된 최대값 이하인지 확인합니다.
- @Email: 문자열이 유효한 이메일 주소 형식인지 확인합니다.
- @Pattern: 문자열이 지정된 정규 표현식과 일치하는지 확인합니다.
public class UserDto {
@NotBlank(message = "Username is mandatory")
@Size(min = 3, max = 20, message = "Username must be between 3 and 20 characters")
private String username;
@Email(message = "Email should be valid")
@NotBlank(message = "Email is mandatory")
private String email;
@NotBlank(message = "Password is mandatory")
@Size(min = 6, message = "Password must be at least 6 characters")
private String password;
}이런 식으로 사용할 수 있다.
추가적으로 스프링에서
@Validated는 유효성 검사 그룹을 지원하여 DTO객체 내의 인터페이스 형태의 그룹 검증을 구현할 수 있다.
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
public class UserDto {
@NotBlank(message = "Username is mandatory", groups = Create.class)
@Size(min = 3, max = 20, message = "Username must be between 3 and 20 characters", groups = Create.class)
private String username;
@NotBlank(message = "Email is mandatory", groups = {Create.class, Update.class})
private String email;
@NotBlank(message = "Password is mandatory", groups = Create.class)
@Size(min = 6, message = "Password must be at least 6 characters", groups = Create.class)
private String password;
// Default group for general validation
@NotBlank(message = "Name is mandatory", groups = Default.class)
private String name;
public interface Create {}
public interface Update {}
// Getters and setters
}@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping("/register")
public ResponseEntity<String> registerUser(
@Validated(UserDto.Create.class) @RequestBody UserDto userDto
) {
// 서비스 로직 호출 등
return ResponseEntity.ok("User registered successfully");
}
@PutMapping("/update")
public ResponseEntity<String> updateUser(
@Validated(UserDto.Update.class) @RequestBody UserDto userDto
) {
// 서비스 로직 호출 등
return ResponseEntity.ok("User updated successfully");
}
}이런식으로 생성DTO와 수정DTO 검증을 분할할 수 있다.
검증 실패
만약 검증에서 실패한다면 기본적으로
javax.validation의
ConstraintViolationException이 발생하고
스프링에서는 @RequestBody 혹은 @ModelAttribute 파라미터에 대해 검증이 실패하면
org.springframwork.web.bind의
MethodArgumentNotValidException이 발생한다.
따라서 해당하는 예외에 대해 적절한 처리가 이루어져야 한다.