Data Transfer Object의 약자로, 데이터를 전달하기 위해서 사용하는 객체를 의미합니다.
DTO를 사용하게 되면 다음과 같은 장점이 있습니다.
일반적으로 3번의 검증과 예외처리를 진행한다.
왜 이렇게 여러번 검증해야 할까?
일반적으로 프론트엔드 쪽 웹사이트에서는 JS를 이용하여 사용자가 입력하는 입력 폼 필드의 값에 대해 1차적으로 유효성 검증을 진행한다.
하지만 JS로 전송되는 데이터는 브라우저의 개발자 도구를 사용해서 breakpoint를 추가한 뒤에 얼마든지 그 값을 조작할 수 있기 때문에 프론트엔드 쪽에서 유효성 검사를 진행했다고 하더라도 서버 쪽에서 한번 더 유효성 검사를 진행해야 한다.
한마디로, 프론트엔드에서 하는 검증은 사용자에게 편의를 주기위해(의미 없는 요청이 진행되지 않도록) 검증하고, 백엔드에서 정말 그 값에 대해 검증을 진행하여야 한다는 의미다!
1. 가장 먼저 Build.gradle에서 의존성을 추가해줘야 합니다.
implementation 'org.springframework.boot:spring-boot-starter-validation'
2. DTO에 @Validation 어노테이션을 사용 해 값을 검증한다.
@Data
@Builder
public class ChildRequestDTO {
private String profileImage;
@NotNull(message = "닉네임은 필수 값입니다.")
@Size(max = 10, message = "닉네임은 최대 10자까지 입력 가능합니다.")
private String nickname;
@NotNull(message = "성별은 필수 값입니다.")
private Gender gender;
@NotNull(message = "생일은 필수 값입니다.")
private LocalDate birth;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
3. 해당 DTO를 사용하는 Controller 에서 @Valid를 적용한다.
@RestController
@RequestMapping("/api/child")
@RequiredArgsConstructor
public class ChildController {
private final ChildService childService;
@PostMapping
public ResponseEntity<Void> addChild(@Valid @RequestBody ChildRequestDTO childRequestDTO) {
childService.addChild(childRequestDTO);
return new ResponseEntity<>(HttpStatus.OK);
}
}
예외처리를 해주어야 합니다.
4. MethodArgumentNotValidException 예외처리 진행
Validation Exception이 발생한다면 MethodArgumentNotValidException이 발생하게 됩니다. 이를 GlobalExceptionHandler에서 처리해주어 검증에 실패한 필드에 대한 메시지를 출력합니다.
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}
// 다른 예외 핸들러도 추가할 수 있습니다.
}
위와 같이 유효성 검증을 추가하고, 예외처리를 해준다면

이렇게 잘못된 요청이 들어왔을떄(위 예시는 score, playtime필드가 @NotNull인데, Null이 들어온 케이스) 값을 검증해주어 유효성을 판단하여 줍니다.
DTO를 사용하여 들어오는 값에 대한 검증을 진행하고, 이를 통해 유효성 검사의 역할을 분리하여 결합도를 떨어트리는 결과를 가져옵니다.