기타

유효성검사와 예외처리

MIN우 2023. 5. 25. 23:04
728x90

애플리케이션의 비즈니스 로직이 올바르게 동작하려면 데이터를 사전 검증하는 작업이 필요하다. 이것은 유효성 검사 또는 데이터 검증이라한다. 유효성 검사의 예로는 여러 계층에서 들어오는 데이터에 대해 의도한 형식대로 값이 들어오는지 체크하는 과정이 있다. 이 같은 유효성 검사(validation)는 프로그래밍에서 매우 중요한 부분이며, 자바에서 가장 신경 써야 하는 것 중 하나로 NullPointException 예외가 있다.

 

10.3.3 스프링 부트의 유효성 검사

유효성 검사는 각 계층으로 데이터가 넘어오는 시점에 해당 데이터에 대한 검사를 실시한다. 스프링부트 프로젝트에서는 계층 간 데이터 전송에 대체로 DTO객체를 활용하고 있기 때문에 아래 그림과 같이 유효성 검사를 DTO 객체를 대상으로 수행하는 것이 일반적이다.

 

먼저 DTO와 컨트롤러를 생성한다. ValidRequestDto라는 이름의 DTO객체를 생성한다

  • data/dto/ValidRequestDto.java
// 예제 10.2
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class ValidRequestDto {

    
    @NotBlank
    private String name;

    @Email
    private String email;

    @Pattern(regexp = "01(?:0|1|[6-9])[.-]?(\\\\d{3}|\\\\d{4})[.-]?(\\\\d{4})$")
    private String phoneNumber;

    
    @Min(value = 20)
    @Max(value = 40)
    private int age;

  
    @Size(min = 0, max = 40)
    private String description;

    
    @Positive
    private int count;

    @AssertTrue
    private boolean booleanCheck;

}

각 필드에 어노테이션은 유효성 검사를 위한 조건을 설정하는데 사용된다

@Pattern(regexp = "01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$")
private  String phoneNumber;**
  • 01: 문자열이 "01"로 시작하는지 확인합니다.
  • (?:0|1|[6-9]): 그 다음 문자는 0, 1 또는 6-9 사이의 숫자 중 하나인지 확인합니다. **(?:)**는 비캡처 그룹을 나타냅니다. 따라서 이 그룹으로 매칭된 값은 추출되지 않습니다.
  • [.-]?: 옵션으로, 문자열에서 점 또는 대시 기호가 나타날 수 있습니다.
  • (\\d{3}|\\d{4}): 다음으로, 3자리 또는 4자리의 숫자 중 하나인지 확인합니다. **\\d**는 숫자를 나타내며, **{3}**는 세 번 반복됨을 의미합니다. **|**는 두 개의 선택지 중 하나를 의미합니다.
  • [.-]?: 다시 한 번, 문자열에서 점 또는 대시 기호가 나타날 수 있습니다.
  • (\\d{4}): 마지막으로, 4자리 숫자인지 확인합니다.

 

 

  • 문자열 검증
  • @Null : Null 값만 허용 @NotNull : Null을 허용하지 않음. "", " "는 허용 @NotEmpty : null, ""을 허용하지 않음. " "는 허용 @NotBlank : null, "", " " 모두 허용하지 않음
  • 최댓값/최솟값 검증@DecimalMin(value = "$numberString") : $numberString 이상의 값을 허용 @DecimalMax(value = "$numberString") : $numberString 이하의 값을 허용 @Min(value = $number) : $number 이상의 값을 허용 @Max(value = $number) : $number 이하의 값을 허용
  • BigDecimal, BigInteger, int, long 등의 타입을 지원
  • 값의 범위 검증@Positive : 양수를 허용 @PositiveOrZero : 0을 포함한 양수를 허용 @Negative : 음수를 허용 @NegativeOrZero : 0을 포함한 음수를 허용
  • BigDecimal, BigInteger, int, long등의 타입을 지원
  • 시간에 대한 검증@Future : 현재보다 미래의 날짜를 허용 @FutureOrPresent : 현재를 포함한 미래의 날짜를 허용 @Past : 현재보다 과거의 날짜를 허용 @PastOrPresent : 현재를 포함한 과거의 날짜를 허용
  • Date, LocalDate, LocalDateTime 등의 타입 지원
  • 이메일 검증
  • @Email : 이메일 형식을 검사. ""는 허용
  • Boolean 검증
  • @AssertTrue : true 체크, null 값은 체크하지 않음 @AssertFalse : false 체크, null 값은 체크하지 않음
  • 이메일 검증
  • @Email : 이메일 형식을 검사. ""는 허용
  • 자릿수 범위 검증@Digits(integer=$number1, fraction=$number2) : $number1의 정수 자릿수와 $number2의 소수 자릿수를 허용
  • BigDemical, BigInteger, int, long등의 타입을 지원
  • Boolean 검증
  • @AssertTrue : true 체크, null 값은 체크하지 않음 @AssertFalse : false 체크, null 값은 체크하지 않음
  • 문자열 길이 검증
  • @Size(min = $minNumber, max = $maxNumber) : 문자열의 길이를 제한

Try ~ Catch 구문을 이용해서 Exception 처리를 하는방법

@Transactional
public void subscribe(long fromUserId,long toUserId){

    try{
        subscribeRepository.mSubscribe(fromUserId, toUserId);
    }catch (Exception e){
        throw new CustomApiException("이미 구독 하였습니다.");
    }

}

CustomApiException.java

public class CustomApiException extends RuntimeException {

    public CustomApiException(String message) {
        super(message);
    }
}

ControllerExceptionHandler.java

@RestController
@ControllerAdvice // 모든 exception을 낚아챔
public class ControllerExceptionHandler {

@ExceptionHandler(CustomApiException.class) //RuntimeException 함수를 가로챔
public ResponseEntity<?> ApiException(CustomApiException e){

  
    return new ResponseEntity<>(new CMResDto<>(-1,e.getMessage(),null),HttpStatus.BAD_REQUEST);
}

<?>: 타입 파라미터를 대치하는 것으로 모든 클래스나 인터페이스타입이 올 수 있습니다.

제네릭이란?

https://coding-factory.tistory.com/573

 

[Java] 제네릭(Generic) 사용법 & 예제 총정리

제네릭을 사용해야하는 이유 제네릭 타입을 사용함으로써 잘못된 타입이 사용될 수 있는 문제를 컴파일 과정에서 제거할 수 있기 때문입니다. 자바 컴파일러는 코드에서 잘못 사용된 타입 때문

coding-factory.tistory.com

CMResDto.java

@AllArgsConstructor
@NoArgsConstructor
@Data
public class CMResDto<T>{
    private int code; // 1(성공),-1(실패)
    private String message;
    private T data;
}

CMResDto는 공통응답을 처리해줄 수 있는 Dto클래스입니다.

ex)

 

728x90