ㅅㅇ
[Spring Boot] 유효성 검사 & 데이터 검증 Vaildation 본문
유효성 검사 & 데이터 검증 Vaildation 이란?
- 서비스의 비즈니스 로직이 올바르게 동작하기 위해 사용되는 데이터에 대한 사전 검증하는 작업
- 유효성 검사 혹은 데이터 검증이라고 부르는데, 흔히 Validation 이라고 부름
- 들어오는 데이터에 대해 개발자가 의도한 값이 의도한 형식의 값으로 제대로 들어오는지 체크하는 과정
- 데이터의 검증은 여러 계층에서 발생하는 흔한 작업
- 기존 Validation의 여러 문제가 있는데, 이를 해결하기 위해 Java에서 Bean Validation, Hibernate Validator 를 제공함
- Bean Validation 은 어노테이션을 통해 다양한 데이터를 검증할 수 있게 기능을 제공
- Hibernate Validator는 Bean Validation 명세에 대한 구현체
- Spring Boot 의 유효성 검사 표준은 Hibernate Validator 이다.
- 3 버전부터 starter-validation 을 추가해야 함.
Validation 관련 어노테이션
어노테이션 | 의미 |
@Size | 문자의 길이 조건 |
@NotNull | null 값 불가 |
@NotEmpty | null 값 불가 + “” 값 불가 |
@NotBlank | null 값 불가 + “” 값 불가 + “ “ 값 불가 |
@Past | 과거 날짜 |
@PastOrPresent | 과거 날짜 + 오늘 날짜 |
@Future | 미래 날짜 |
@FutureOrPresent | 미래 날짜 + 오늘 날짜 |
@Pattern | 정규식을 통한 조건 |
@Max | 최대값 조건 설정 (문자열 길이 제한 가능) |
@Min | 최소값 조건 설정 |
@AssertTrue/AssertFalse | 참/거짓 조건 설정 |
@Valid | 해당 객체의 유효성 검사 |
EX ) 회원 가입 시, 이메일 양식 유효성 검사
- pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
- DTO 에 검증 기준 어노테이션 설정
package io.csy.hot.model.dto;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Builder
@ToString
public class SignUpDTO {
// @NotBlank // null, 빈 문자열 (스페이스 포함X) 불가
@NotEmpty(message = "이메일을 입력하지 않았습니다.") // null, 빈 문자열, 스페이스만 포함한 문자열 불가
@Email(message = "이메일 형식이 맞지 않습니다.") // 이메일 형식만 가능
private String accountEmail;
@NotEmpty(message = "비밀번호을 입력하지 않았습니다.") // null, 빈 문자열, 스페이스만 포함한 문자열 불가
@Pattern(regexp="[a-zA-Z1-9]{6,12}", message = "비밀번호는 영어와 숫자로 포함해서 6~12자리 이내로 입력해주세요.")
private String accountPassword;
@NotBlank(message = "이름을 입력하지 않았습니다.")
@Size(min = 2, max = 8, message = "이름을 2 ~ 8 자 사이로 입력해주세요.")
private String accountName;
@NotNull // null 불가능
private String accountBirth;
@NotNull
private String accountAddress;
@NotNull
@Pattern(regexp = "^01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$", message = "전화번호 형식이 맞지 않습니다.")
private String accountPhoneNumber;
@NotNull
private String accountGender;
}
- 컨트롤러에 적용.
들어오는 데이터 SignUpDTO signUp 매개변수에 @Valid 어노테이션을 붙이기
package io.csy.hot.controller;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.csy.hot.model.AccountService;
import io.csy.hot.model.dto.AccountDTO;
import io.csy.hot.model.dto.SignUpDTO;
@RestController
@RequestMapping("auth")
@CrossOrigin(origins = "*", allowedHeaders = "*")
public class AccountController {
@Autowired
private AccountService accountService;
@PostMapping("/sing-up")
public void signUp(@Valid @RequestBody SignUpDTO signUp) throws Exception {
AccountDTO account = accountService.signUp(signUp);
}
}
데이터 유효성 검사 예외 처리
- 유효성 @Vaild 유효성 검사 후 에러 발생 시, 클라이언트에게 에러 응답을 보내는 처리이다.
- 데이터 유효성 에러 시, MethodArgumentNotValidException 의 예외 발생
- ResponseEntityExceptionHandler 의 handleMethodArgumentNotValid 을 오버라이딩하여 처리
- 로그백으로 로그 남기는 것도 포함되어 있음. (빼도 무관)
- DTO 에 작성한 각 message 들고 오는 법
String detailMessage = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage();
- 아래 코드는 MethodArgumentNotValidException 예외에 대한 처리에 관하여 글로벌핸들러 코드만 나와 있는 것.
import java.nio.file.AccessDeniedException;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler{
private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
CommonErrorCode errorCode = CommonErrorCode.METHOD_ARGUMENT_NOT_VALID;
String detailMessage = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage();
LOGGER.warn("HandleHttpRequestMethodNotSupportedException:CLIENT REQUEST ERROR:INVALID_METHOD: {}", ex.getMessage());
return ErrorResponse.toDataVaildErrorResponse(errorCode, detailMessage, request.getDescription(false).substring(4)); }
}
- ex) 에러 응답 예시
{
"timestamp": "Fri Feb 03 01:04:30 KST 2023",
"status": 400,
"error": "METHOD_ARGUMENT_NOT_VALID",
"message": "데이터유효성 검사 결과, 규칙에 맞지 않는 데이터입니다. : 전화번호 양식이 맞지 않습니다.",
"path": "/auth/sing-up"
}
'SW_STUDY > SpringBoot' 카테고리의 다른 글
[Spring Securtiy] Spring Securtiy FilterChain필터 (0) | 2023.03.08 |
---|---|
[Spring Securtiy] Spring Securtiy 기본 개념 (0) | 2023.03.08 |
[Spring Boot] 예외 처리 ExceptionHandler 예시 (0) | 2023.01.31 |
[Spring Boot] 예외 처리 ExceptionHandler 개념 (0) | 2023.01.31 |
[Spring Boot] 로그 처리 Logback (1) | 2023.01.28 |