📌@Valid, @Validated
우리가 웹사이트에서 회원가입을 할 때, 이런 걸 검사해야 합니다.
✔ 이름을 입력했는지?
✔ 나이가 너무 어리진 않은지?
✔ 이메일 형식이 맞는지?
이런 검사를 백엔드(Spring) 에서 자동으로 해주는 게 @Valid랑 @Validated입니다.
@Valid 사용법 (기본 검사)
예를 들어 회원가입할 때, 이름이 비어있으면 안 되고, 나이는 18살 이상이어야 한다는 조건을 붙인다고 생각합시다.
UserDTO (데이터 저장하는 클래스)
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
public class UserDTO {
@NotBlank(message = "이름을 입력하세요!")
private String name;
@NotNull(message = "나이를 입력하세요!")
@Min(value = 18, message = "나이는 18살 이상이어야 합니다.")
private Integer age;
// 기본 생성자, getter, setter 필요
}
UserController (검사 적용)
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping("/create")
public String createUser(@Valid @RequestBody UserDTO user) {
return "회원가입 완료! " + user.getName();
}
}
📌 결과
✅ {"name": "홍길동", "age": 20} → 회원가입 성공
❌ {"name": "", "age": 17} → 이름을 입력하세요!, 나이는 18살 이상이어야 합니다.
@Validated 사용법 (그룹 검사)
예를 들어,
- 회원가입할 때(CreateGroup)는 이름과 나이 둘 다 필수!
- 정보 수정할 때(UpdateGroup)는 이름만 필수!
그룹 인터페이스 만들기
public interface CreateGroup {}
public interface UpdateGroup {}
이 인터페이스는 단순히 "이름표" 역할만 하면 되기 때문에, 별도의 코드가 필요하지 않습니다.
UserDTO에 그룹 적용
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.springframework.validation.annotation.Validated;
@Validated
public class UserDTO {
@NotBlank(groups = {CreateGroup.class, UpdateGroup.class}, message = "이름을 입력하세요!")
private String name;
@NotNull(groups = {CreateGroup.class}, message = "나이를 입력하세요!")
@Min(value = 18, groups = {CreateGroup.class}, message = "나이는 18살 이상이어야 합니다.")
private Integer age;
// 기본 생성자, getter, setter 필요
}
UserController에서 특정 그룹만 검사
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping("/create")
public String createUser(@Validated(CreateGroup.class) @RequestBody UserDTO user) {
return "회원가입 완료! " + user.getName();
}
@PutMapping("/update")
public String updateUser(@Validated(UpdateGroup.class) @RequestBody UserDTO user) {
return "회원정보 수정 완료! " + user.getName();
}
}
📌 결과
✅ POST /create (회원가입)
{ "name": "홍길동", "age": 20 } → 회원가입 성공!
{ "name": "홍길동" } → ❌ "나이를 입력하세요!"
✅ PUT /update (정보 수정)
{ "name": "홍길동" } → 수정 성공!
{ "age": 20 } → ❌ "이름을 입력하세요!"
정리
✔ @Valid: 모든 필드 검사
✔ @Validated: 필요한 것만 골라서 검사
✔ 그룹이 필요 없으면 @Valid 사용
✔ 검사를 다르게 하고 싶으면 @Validated 사용
실사용 예제
DTO 클래스
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Data
public class UserRequestDto {
@NotBlank(message = "이름은 필수 입력 값입니다.")
@Size(min = 2, max = 30, message = "이름은 2자 이상 30자 이하로 입력해주세요.")
private String name;
@NotBlank(message = "이메일은 필수 입력 값입니다.")
@Email(message = "유효한 이메일 형식을 입력해주세요.")
private String email;
@NotBlank(message = "비밀번호는 필수 입력 값입니다.")
@Size(min = 6, message = "비밀번호는 최소 6자 이상이어야 합니다.")
private String password;
}
컨트롤러
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
@Validated
public class UserController {
@PostMapping("/register")
public ResponseEntity<String> registerUser(@Valid @RequestBody UserRequestDto userRequestDto) {
return ResponseEntity.ok("회원가입 성공: " + userRequestDto.getName());
}
}
요청 및 성공시 응답
POST /users/register
Content-Type: application/json
{
"name": "홍길동",
"email": "hong@example.com",
"password": "password123"
}
HTTP/1.1 200 OK
회원가입 성공: 홍길동
요청 및 실패시 응답
POST /users/register
Content-Type: application/json
{
"name": "",
"email": "not-an-email",
"password": "123"
}
HTTP/1.1 400 Bad Request
{
"message": "이름은 필수 입력 값입니다.",
"message": "유효한 이메일 형식을 입력해주세요.",
"message": "비밀번호는 최소 6자 이상이어야 합니다."
}'Spring' 카테고리의 다른 글
| @PostConstruct , @PreDestory (0) | 2025.03.26 |
|---|---|
| 스프링의 메세지, 국제화 (0) | 2025.02.13 |
| @Scheduled (0) | 2025.01.24 |
| @Controller 와 @RestController (2) | 2025.01.22 |
| ResponseEntity (0) | 2025.01.16 |