[Spring/Springboot] @Valid 란?
2024. 12. 23. 00:00ㆍCS/Spring
@Valid
- 스프링에서 입력 데이터의 유효성(Validation)을 자동으로 검사
- 클라이언트가 보낸 데이터를 확인해서 규칙에 맞지 않으면 자동으로 오류를 알려줌
1. DTO 클래스에서 사용
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
public class SignUpRequestDTO {
@NotNull(message = "이름은 필수")
private String name;
@NotNull(message = "이메일은 필")
@Email(message = "유효한 이메일 주소를 입력")
private String email;
}
//각각 @NotNull, @Email(이메일형식)이 검사를 통과하지 못하면, 오류 발생
2. 컨트롤러에서 사용
- 미션으로 직접 작성한 코드를 통해서 이해하기 → 컨트롤러에서 호출하고 오류 발생 메세지 응답까지 흐름 살펴보기
@PostMapping("/")
public ApiResponse<StoreResponseDTO. addStoreToSpecificRegionResultDto> addStore(@RequestBody @Valid StoreRequestDTO.addStoreToSpecificRegionDto request){
Store store = storeCommandService.addStoreToSpecificRegion(request);
return ApiResponse.onSuccess(StoreConverter.toAddStoreResultDto(store));
}
- 클라이언트 요청 전송 -> 클라이언트가 addStore API에 POST 요청을 보냄
- 요청 본문에 StoreRequestDTO.addStoreToSpecificRegionDto 형태의 데이터를 포함 ->regionName 필드가 포함됨
- addStore 메서드는 @Valid 어노테이션을 통해 StoreRequestDTO.addStoreToSpecificRegionDto 데이터의 유효성을 검사
@Documented
@Constraint(validatedBy = RegionExistValidator.class)
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExistRegion {
String message() default "해당 지역이 존재하지 않습니다.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
- 특히, regionName 필드에는 @ExistRegion 어노테이션이 적용되어 있으므로 RegionExistValidator가 실행
@Component
@RequiredArgsConstructor
public class RegionExistValidator implements ConstraintValidator<ExistRegion, String> {
//RegionExistValidator는 ConstraintValidator 인터페이스를 구현하여 @ExistRegion 어노테이션을 해석**
private final RegionService regionService;
@Override
public void initialize(ExistRegion constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(String regionName, ConstraintValidatorContext context) {
//isValid 메서드가 호출되면서 regionName 값이 RegionService의 existsByName 메서드를 통해 존재하는지 확인
boolean isValid = regionService.existsByName(regionName);
if (!isValid) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(ErrorStatus.REGION_NOT_FOUND.toString()).addConstraintViolation();
}
return isValid;
}
//RegionService.existsByName(regionName)가 true를 반환하면 isValid 메서드는 true를 반환하며 검증을 통과
//false일 경우, 검증이 실패하며 오류 메시지로 ErrorStatus.REGION_NOT_FOUND가 설정
}
@PostMapping("/")
public ApiResponse<StoreResponseDTO. addStoreToSpecificRegionResultDto> addStore(@RequestBody @Valid StoreRequestDTO.addStoreToSpecificRegionDto request){
Store store = storeCommandService.addStoreToSpecificRegion(request);
return ApiResponse.onSuccess(StoreConverter.toAddStoreResultDto(store));
}
//유효성 검사를 통과하면 addStore 메서드는 다음 단계로 진행
//만약 검증이 실패하면, @Valid는 예외를 발생시킴 -> 스프링은 해당 예외를 처리하여 클라이언트에게 유효성 검사 실패 응답을 반환
'CS > Spring' 카테고리의 다른 글
[Spring/Springboot] Spring Data JPA - Paging/Slice (0) | 2024.12.23 |
---|---|
[Spring/Springboot] @RestControllerAdvice/API 응답 통일/에러 핸들러 (0) | 2024.12.22 |
[Spring/Springboot] N+1 문제 해결 방안 - Batch Size/2차 캐시/Subselect Fetching/DTO (0) | 2024.12.22 |
[Spring/Springboot] QueryDSL이란? (0) | 2024.12.22 |
[Spring/Springboot] @EntityGraph (0) | 2024.12.22 |