Controller 단에서 필요한 정보를 DTO에 담아(@RequestBody 사용) 받는 중이다.
유효성 검증을 위해 @Valid를 붙이고, DTO 내부의 각 필드마다 맞는 유효성검증 애너테이션을 사용중인데
문자열이나 숫자를 위한 유효성 검사용 애너테이션은 잘 사용하고 있지만 List<?> 필드가 있다면 이에 맞는 유효성 검증은 어떻게 이루어 져야 할까?
(e.g. List<Long>
, List<SongDTO>
...)
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/admin-account/student", name = "[관리자모드]학생 관리", produces = "application/json")
public class StudentAccountController {
private final StudentAccountUseCase studentAccountUseCase;
@DupleCheck
@PostMapping(name = "학생 추가")
public BaseResponse<Object> add(@AuthToken String token, @Valid @RequestBody StudentAccountDTO.RegisterRequest request) {
studentAccountUseCase.registerStudent(token, request.toCommand());
return BaseResponse.ofSuccess("");
}
전체 코드가 아니라 필요한 부분만 보고 싶으시다면 밑으로!
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class StudentAccountDTO {
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class RegisterRequest {
@NotBlank(message = Expression.MUST_INPUT_REQUEST_MSG)
@Pattern(regexp = Expression.USER_NAME_REG_EXP, message = Expression.USER_NAME_MSG)
private String name;
@NotBlank
@Pattern(regexp = Expression.STUDENT_NUMBER_REG_EXP, message = Expression.STUDENT_NUMBER_MSG)
private String studentNumber;
@NotNull
@Email
private String email;
@Pattern(regexp= Expression.USER_PHONE_NUM_REG_EXP, message= Expression.PHONE_NUM_MSG)
private String phoneNum;
@NotBlank
private String registrationStatus;
@Pattern(regexp = Expression.SCHOOL_YEAR_REG_EXP, message = Expression.SCHOOL_YEAR_MSG)
private String schoolYear;
private List<@Min(1) Long> courseInfoIdList;
public StudentAccountCommand.Register toCommand() {
return StudentAccountCommand.Register.builder()
.name(name)
.studentNumber(studentNumber)
.email(email)
.phoneNum(phoneNum)
.registrationStatus(RegistrationStatus.from(registrationStatus))
.schoolYear(DthStringUtil.removeStr(schoolYear))
.courseInfoIdList(courseInfoIdList)
.build();
}
}
}
뜯어보자.
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class StudentAccountDTO {
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class RegisterRequest {
@NotBlank(message = Expression.MUST_INPUT_REQUEST_MSG)
@Pattern(regexp = Expression.USER_NAME_REG_EXP, message = Expression.USER_NAME_MSG)
private String name;
.
.
(중략)
.
.
// @Min(1)을 여기, 위에 붙이는게 아니라 List<> 안의 변수 타입 앞에 붙여주면 된다.
private List<@Min(1) Long> courseInfoIdList;
public StudentAccountCommand.Register toCommand() {
return StudentAccountCommand.Register.builder()
.name(name)
.studentNumber(studentNumber)
.email(email)
.phoneNum(phoneNum)
.registrationStatus(RegistrationStatus.from(registrationStatus))
.schoolYear(DthStringUtil.removeStr(schoolYear))
.courseInfoIdList(courseInfoIdList)
.build();
}
}
}
List<SongDTO>
처럼 어떤 커스텀 오브젝트를 쓴다면, @NoArgsConstructor(access = AccessLevel.PROTECTED)
public class SongDTO {
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class RegisterRequest {
@Min(1)
private Long courseInfoId;
}
}
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class StudentAccountDTO {
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class RegisterRequest {
@NotBlank(message = Expression.MUST_INPUT_REQUEST_MSG)
@Pattern(regexp = Expression.USER_NAME_REG_EXP, message = Expression.USER_NAME_MSG)
private String name;
.
.
(중략)
.
.
@Valid // 여기에 Valid를 붙여야 SongDTO 내부에서 유효성검증이 가능하다.
private List<SongDTO> songDtoList;
public StudentAccountCommand.Register toCommand() {
return StudentAccountCommand.Register.builder()
.name(name)
.studentNumber(studentNumber)
.email(email)
.phoneNum(phoneNum)
.registrationStatus(RegistrationStatus.from(registrationStatus))
.schoolYear(DthStringUtil.removeStr(schoolYear))
.courseInfoIdList(courseInfoIdList)
.build();
}
}
}
먼저 처음 알게된 것은 List< 여기에도 애너테이션 사용이 가능 Type> 이라는 것이다.
또한 DTO로 했을 때는, Controller의 @RequestBody 객체에 붙인 @Valid로는 해당 클래스단 까지만 유효성검증이 이루어지는 걸까?
Controller의 request는
@Valid @RequestBody StudentAccountDTO.RegisterRequest request
정말 request 객체의 변수까지만 유효성 검증이 되었고 request 변수 중 songDtoList 처럼
private List<SongDTO> songDtoList;
특정 DTO 클래스 Type으로 받는다면 위에 @Valid
를 꼭 써서 검증을 주입해주자.