[Spring Boot] DTO에서 Validation 처리하기

왔다 정보리·2024년 4월 13일
2
post-thumbnail

DTO (Data Transfer Object)


DTO (Data Transfer Object)

static class ResponseDto {
    private String name;
    private String result;
}

DTO는 계층 간 데이터 전달을 위해 사용하는 객체이다. DTO는 순수하게 데이터를 전송하기 위한 객체이기 때문에 비즈니스 로직은 포함되어 있지 않다.

ex) 유저가 DTO에 데이터를 담아서 전송하는 경우, 서버가 DTO를 이용하여 유저에게 데이터를 전송하는 경우 등

DTO에서 유효성 검사를 한 이유

Controller에서 코드를 통해 유효성 검사를 할 수도 있지만, DTO에서 유효성 검사를 해야겠다고 생각한 이유는 다음과 같다. 코드로 유효성 검사를 할 경우 중복 코드, 필요 없는 코드가 많아져 코드가 지저분해진다고 느꼈다. 또한 DTO는 데이터를 주고 받는 역할을 하는 만큼 데이터에 관련된 코드는 DTO에서 모두 처리하는 게 더 깔끔하다고 생각이 되어 DTO에서 유효성 검사를 최대한 진행하기로 했다.

DTO로 Validation 처리하기


@NotNull, @NotEmpty, @NotBlank

사람들이 헷갈리기 쉬운 @NotNull, @NotEmpty, @NotBlank에 대해 조금 더 자세히 알아보겠다!

@NotNull
@NotNull은 해당 값이 null인지 아닌지 확인한다. “” 혹은 “ “ 등 null이 아닌 것들은 모두 통과된다.

@NotEmpty
@NotEmpty는 해당 값이 null 또는 비어 있는지 확인한다. 이 때 비어 있다는 것은 “”를 의미한다. String, Collection, Map, Array에 적용할 수 있다.

@NotBlank
@NotBlank는 해당 값이 null 또는 공백이 아닌지 확인한다. null, “”, “ “ 모두 허용하지 않는다. @NotBlank는 텍스트에만 적용할 수 있다.

자주 사용하는 어노테이션 정리

@Pattern(regexp = )
: 해당 값이 정규표현식과 일치하는지 확인한다

@*AssertTrue
: 해당 값이 true 인지 확인한다

@Size(min = , max = )
: 해당 값의 크기가 min과 max 사이인지 확인한다. String, Collection, Map, Array에 적용할 수 있다

@Min(value = ), @Max(value = )
: @Min은 해당 값이 min보다 크거나 같은지 확인한다. @Max는 해당 값이 max보다 작거나 같은지 확인한다. @Min@Max는 숫자에 적용할 수 있으며, double과 float에는 사용할 수 없다.

@Email
: 유효한 이메일 주소인지 확인한다.

@Positive@PositiveOrZero
: 해당 값이 양수인지 확인한다. 숫자에 적용되며 @PositiveOrZero는 0도 포함해서 확인한다.

@Negative@NegativeOrZero
: 해당 값이 음수인지 확인한다, 숫자에 적용되며 @NegativeOrZero는 0도 포함해서 확인한다.

@Past@PastOrPresent
: 날짜 값이 과거인지 아닌지 확인한다. @PastOrPresent는 현재까지 포함해서 확인한다. 날짜 유형에 적용할 수 있다.

@Future 및 @FutureOrPresent
: 날짜 값이 미래인지 아닌지 확인한다. @FutureOrPresent는 현재까지 포함해서 확인한다. 날짜 유형에 적용할 수 있다.

실전 활용 코드

  1. 의존성을 주입한다
implementation 'org.springframework.boot:spring-boot-starter-validation'

  1. DTO에서 어노테이션을 통해 유효성 검사를 진행한다

어노테이션으로 조건을 정해주고, message 속성을 통해 사용자에게 어떤 메세지를 보여줄지 정할 수 있다.

@NotBlank(message = "이름을 입력해야 합니다.")
@Pattern(regexp = "^[가-힣A-Za-z0-9]+$", message = "보관함 이름에는 한글, 영문, 숫자만 가능합니다")
@Size(min = 1, max = 5, message = "이름은 한글자 이상, 다섯글자 이하입니다.")
String name;
    
@Min(value = 1000, message = "비밀번호는 4자리여야 합니다.")
@Max(value = 9999, message = "비밀번호는 4자리여야 합니다.")
int password;
    
@NotBlank(message = "걱정 시작 시간을 입력해야 합니다.")
@Pattern(regexp = "^(1[0-2]|[1-9]):[0-5][0-9](AM|PM|am|pm)$", message = "걱정 시간 형식은 1:00~12:59(AM/PM)입니다")
String startTime;
    
@NotBlank(message = "걱정 종료 시간을 입력해야 합니다.")
@Pattern(regexp = "^(1[0-2]|[1-9]):[0-5][0-9](AM|PM|am|pm)$", message = "걱정 시간 형식은 1:00~12:59(AM/PM)입니다")
String endTime;

  1. Controller에서 DTO에 @Valid 어노테이션을 달아서 검증을 하겠다고 알려준다
@PostMapping("/join")
public BaseResponse<PostUserRes> join(@Valid @RequestBody PostJoinReq postJoinReq) {
	// 코드 작성
}

  1. 예외 처리를 위해 GlobalExceptionHandler를 작성한다
@RestControllerAdvice
public class GlobalExceptionHandler {
	@ExceptionHandler(MethodArgumentNotValidException.class)
    public BaseResponse<String> BaseException(MethodArgumentNotValidException e) {
   		 // 에러 메시지 추출
    	String errorMessage = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        log.error(errorMessage);
    
    	// 적절한 BaseResponseStatus 사용
    	return new BaseResponse<>(BaseResponseStatus.INVALID_PARAMETERS, errorMessage);
    }
}

확실히 DTO에서 유효성 검사를 진행하니 코드가 한결 깔끔해진 거 같다. 그리고 DTO에서 데이터 구조 정의, 데이터 유효성 검사까지 모두 진행하니 한 눈에 보기 편하고 명확해진 느낌이다.

참고 자료


Spring - DTO Validation
[Spring Boot] @NotNull, @NotEmpty, @NotBlank 의 차이점 및 사용법
Spring Validation Annotation 총정리
Java Bean Validation Basics | Baeldung
DTO란 무엇이고 왜 사용해야 할까?

profile
왔다 정보리

0개의 댓글