Coding/Back - Spring Framework

Spring DTO, Validation #Day5

꿀딴지- 2023. 8. 22. 14:54

DTO(Data Transfer Object) @Valid @RequestBody

  • 엔터프라이즈 애플리케이션 아키텍처 패턴
  • data : 파라미터를 - Transfer : 전송해주는 - Object: 객체 즉, DTO클래스가 요청/응답 데이터(파라미터)를 하나의 객체로 전달해줌

→ 파라미터가 변경되더라도 DTO만 수정하면 다른 객체들은 수정될 필요가 없음(선택 아닌 필수!)

→ DTO를 적극 활용해야 하며, DTO는 특별한 일이 없는한 json 포맷으로 데이터를 주고 받는다.

→ DTO를 사용한다면 요청과 응답에서 DTO로 통신해야 한다.

 

사용방법

  • 네이밍 : 컨트롤러의 도메인명(컨트롤러는 생략) + 메서드 타입 + Dto : ex. BorderPostDto
  • 클래스 단위보다 메서드에 맞게 DTO를 만들어주는게 더 좋음(파라미터는 메서드에서 사용하기 때문) → 최대한 많이 구분해서 나눌수록 더 DTO스러워짐
  • @RequestBody : JSON 형식의 Request Body를 DTO 클래스의 객체로 변환을 시켜주는 역할
    • 역직렬화(Deserialization) : JSON → Java 객체
  • @ResponseBody : ResponseEntity 객체를 리턴 값으로 사용할 경우 생략
    • 직렬화(Serialization) : Java 객체 → JSON

Validation(DTO 유효성 검증)

build.gradle파일 내 spring 의존성 추가 :유효성 검사 도구

dependencies{ ..
	implementation 'org.springframework.boot:spring-boot-starter-validation’
}

validation은 DTO (역)직렬화 과정에서 확인하기 때문에, 메서드 파라미터로 들어오기 전에 처리됨

 

1. @RequestBody의 유효성 검사 @Valid

  • @Valid : 유효성 검증이 필요하다는 것을 선언
    • DTO 유효성 검증을 하기 위해서는 반드시 필요하며, 없으면 DTO내의 유효성 검증 애너테이션 무시됨
    • @Vaild @RequstBody 처럼 앞에 붙으며, RequestBody로서 역할 할때 유효성 검증하겠다는 의미
  • DTO 에서 각 데이터 별 유효성 검사 기준 적용
    • 다양한 타입의 유효성검증 애너테이션이 있고, 필요 시 문서 참고
    • @Email @NotBlank @Pattern(regexp=”정규식”, message=”안내문구”) @커스텀 에노테이션 가능

 

2. @PathVariable 유효성 검사 @Validated

  • @Validated : 클래서에서 유효성 검사를 하겠다는 애너테이션 필요
  • @PathVariable 다음에 유효성 검사 할 내용 작성
    • ConstraintViolationException 오류 발생
    • @Min(1) @Positive
@RestController
@RequestMapping("/v1/members")
@Validated 
public class MemberController {

	@PatchMapping("/{member-id}")
	public ResponseEntity patchMember(
    	@PathVariable("member-id") @Min(2) long memberId,
        @Valid @RequestBody MemberPatchDto memberPatchDto) 
        {
        memberPatchDto.setMemberId(memberId); // id는 path로 들어왔기 때문에 세팅 필요함
        // ...
        return new ResponseEntity<>(memberPatchDto, HttpStatus.OK);
    }
}
//request body 오류 시 
// 콘솔 출력 : 에너테이션에 message 작성해두면 콘솔에 출력 됨
WARN 62934 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity com.example._0822_lc_dto.web.BoardApiController.postBoard(com.example._0822_lc_dto.web.dto.BoardPostDto): [Field error in object 'boardPostDto' on field 'content': rejected value [null]; codes [NotBlank.boardPostDto.content,NotBlank.content,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [boardPostDto.content,content]; arguments []; default message [content]]; default message [게시글 내용이 있어야 합니다.]] ]// client 응답
"status": 400,
"error": "Bad Request"

//path param 오료 시
// 콘솔 출력 (WRAN아니고 ERROR 로 뜸)
ERROR 62934 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is javax.validation.ConstraintViolationException: getBoard.id: 2 이상이어야 합니다] with root cause
// cleint 응답
"status": 500,
"error": "Internal Server Error"

 

ResponseDTO

// 컨트롤러 클래스
public class CoffeeController {
	@PostMapping
	public ResponseEntity<CoffeeResponseDto> postCoffee(@Valid @RequestBody CoffeePostDto coffeePostDto) {
	    System.out.println("커피메뉴 생성 : "+coffeePostDto.getKorName());
	    CoffeeResponseDto responseDto = new CoffeeResponseDto();
	    return new ResponseEntity<>(responseDto, HttpStatus.CREATED);
	}
}

// reponse dto 클래스
public class CoffeeResponseDto {
    private LocalDateTime completedAt;
    public CoffeeResponseDto(){ //응답할 떄 시간 찍기
        this.completedAt = LocalDateTime.now();
    }
}

'Coding > Back - Spring Framework' 카테고리의 다른 글

Spring 예외처리 #Day7  (0) 2023.08.24
Spring Business(Service) Layer #Day6  (0) 2023.08.23
Spring Presentation(API) Layer #Day4  (0) 2023.08.21
Spring MVC  (0) 2023.08.21
Spring Servlet Filter, Interceptor, AOP #Day3  (0) 2023.08.18