728x90
(1) 유효성 검사(Validation) 란?
- 어떤 데이터의 값이 유효한지, 타당한지 확인하는 것을 의미합니다.
- 보안적인 측면에서 올바르지 않는 데이터가 서버로 전송되거나 DB에 전송되지 않도록 하는 것입니다.
(2) 관련 어노테이션
- JSR-303 Validator
- @AssertFalse - 거짓인가?
- @AssertTrue - 참인가?
- @Max - 지정 값 이하인가?
- @Min - 지정 값 이상인가?
- @DecimalMax - 지정 값 이하 실수인가?
- @DecimalMin - 지정 값 이상 실수인가?
- @NotNull - Null이 아닌가?
- @Null - Null 인가?
- @Digits (integer=, fraction=) - 대상 수가 지정된 정수, 소수 자리 수 이내인가?
- @Pattern(regex=,flag=) - 정규식을 만족 하는가?
- @Future - 미래날짜인가?
- @Past - 과거 날짜인가?
- @Size(min=, max=) - 문자열, 배열 등의 크기가 지정크기를 만족 하는가?
- Hibernate
- @NotEmpty - Empty 값이 아닌가?
- @Email - 이메일 형식인가?
- @URL - URL 형식인가?
- @Length(min=, max=) - 문자열의 길이가 min과 max 사이인가?
- @Range(min=, max=) - 숫자 범위가 min과 max 사이인가?
(3) 사용법
- build.gradle
dependencies {
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
// https://mvnrepository.com/artifact/org.json/json
implementation group: 'org.json', name: 'json', version: '20160810'
implementation 'org.springframework.boot:spring-boot-starter-validation:2.3.3.RELEASE'
}
- DTO
@NotNull
@NotBlank(message = "이메일 입력은 필수입니다.")
@Email(message = "이메일 형식으로 입력해 주세요.")
private String email;
@NotNull
@NotBlank(message = "비밀번호 입력은 필수입니다.")
private String password;
- Controller
//회원 가입
@PostMapping("/api/user/signup")
public Object registerUsers(@Valid @RequestBody UserSignupRequestDto userSignupRequestDto){
}
- ErrorCode
import lombok.Getter;
public enum ErrorCode {
NOT_NULL("ERROR_CODE_NOT_NULL","필수값이 누락되었습니다.")
, MIN_VALUE("ERROR_CODE_MIN_VALUE", "최소값보다 커야 합니다.")
, PATTERN("ERROR_CODE_PATTERN","값 형식이 다릅니다.")
, NOT_BLANK("ERROR_CODE_NOT_BLANK","필수값이 누락되었습니다.")
, EMAIL("ERROR_CODE_EMAIL","이메일 형식이 아닙니다.")
;
@Getter
private String code;
@Getter
private String description;
ErrorCode(String code, String description) {
this.code = code;
this.description = description;
}
}
- ErrorResponse
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class ErrorResponse {
private String code;
private String description;
private String errorMessage;
public ErrorResponse(String code, String description) {
this.code = code;
this.description = description;
}
public ErrorResponse(String code, String description, String errorMessage) {
this.code = code;
this.description = description;
this.errorMessage = errorMessage;
}
}
- ExceptionController
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
@Slf4j
@ControllerAdvice
public class ExceptionController {
/**
* @valid 유효성체크에 통과하지 못하면 MethodArgumentNotValidException 이 발생한다.
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> methodValidException(MethodArgumentNotValidException e, HttpServletRequest request){
log.warn("MethodArgumentNotValidException 발생!!! url:{}, trace:{}",request.getRequestURI(), e.getStackTrace());
ErrorResponse errorResponse = makeErrorResponse(e.getBindingResult());
return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.BAD_REQUEST);
}
private ErrorResponse makeErrorResponse(BindingResult bindingResult){
String code = "";
String description = "";
String errorMessage = "";
//에러가 있다면
if(bindingResult.hasErrors()){
//DTO에 설정한 meaasge값을 가져온다
errorMessage = bindingResult.getFieldError().getDefaultMessage();
//DTO에 유효성체크를 걸어놓은 어노테이션명을 가져온다.
String bindResultCode = bindingResult.getFieldError().getCode();
// switch (bindResultCode){
switch (Objects.requireNonNull(bindResultCode)){
case "NotNull":
code = ErrorCode.NOT_NULL.getCode();
description = ErrorCode.NOT_NULL.getDescription();
break;
case "NotBlank":
code = ErrorCode.NOT_BLANK.getCode();
description = ErrorCode.NOT_BLANK.getDescription();
break;
case "Min":
code = ErrorCode.MIN_VALUE.getCode();
description = ErrorCode.MIN_VALUE.getDescription();
break;
case "Pattern":
code = ErrorCode.PATTERN.getCode();
description = ErrorCode.PATTERN.getDescription();
break;
case "Email":
code = ErrorCode.EMAIL.getCode();
description = ErrorCode.EMAIL.getDescription();
break;
}
}
return new ErrorResponse(code, description, errorMessage);
}
}
- Controller에서 @Valid 어노테이션이 붙은 값이 넘어왔을때 DTO에서 지정해준 조건에 맞지 않는다면 ExceptionController의 makeErrorResponse 함수가 작동하게 되고, 프론트엔드로 ErrorCode에서 지정해준 값과 DTO에 지정해준 Message가 Response Body에 담겨 프론트엔드로 응답하게 됩니다.
반응형
'Study > Spring' 카테고리의 다른 글
[Spring] QueryDSL-JPA (0) | 2024.12.30 |
---|---|
[Spring] @InitBinder (0) | 2021.08.08 |
[Spring] @Data 어노테이션 (0) | 2021.06.30 |
[Spring] 영속성 컨텍스트 (Persistence Context) (0) | 2021.06.30 |
[Spring Boot] Spring 프레임워크 (2) | 2021.06.26 |