DTO
DTO란?
DTO(Data Transfer Object)란 계층간 데이터 교환을 위해 사용하는 객체(Java Beans)이다.
DTO가 필요한 이유
- 클라이언트의 Request Body를 하나의 객체로 모두 전달받을 수 있기 때문에 코드 자체가 간결해진다.
- Request Body의 데이터 유효성(Validation) 검증이 단순해진다.
- 도메인 Model을 캡슐화하고, UI화면에서 사용하는 데이터만 선택적으로 보낼 수 있다.
1
2
3
4
5
6
7
@Getter
@Setter
public class MemberPostDto {
private String email;
private String name;
private String phone;
}
1
2
3
4
@PostMapping //회원등록 컨트롤러
public ResponseEntity postMember(@RequestBody MemberPostDto memberPostDto){
return new ResponseEntity<>(memberPostDto, HttpStatus.CREATED);
}
DTO 사용법
JSON 형식의 Request Body를 전달받기 위해서는 DTO 객체에
@RequestBody애너테이션을 붙여야 한다.Response Body를 JSON 형식으로 전달하기 위해서는 객체와 테이블간 패러다임 불일치가 발생한다
Response Body를 JSON 형식으로 전달하기 위해서는
@ResponseBody애너테이션을 메서드 앞에 붙여 주어야 하지만ResponseEntity 객체를 리턴 값으로 사용할 경우
@ResponseBody를 생략할 수 있다.클라이언트 쪽에서 JSON 형식의 데이터를 서버 쪽으로 전송하면
서버 쪽의 웹 애플리케이션은 전달받은 JSON 형식의 데이터를 DTO 같은 Java의 객체로 변환하는데
이를 역직렬화(Deserialization)이라고 한다.
서버 쪽에서 클라이언트에게 응답 데이터를 전송하기 위해서
DTO 같은 Java의 객체를 JSON 형식으로 변환하는 것을 직렬화(Serialization)라고 한다.
JSON 직렬화(Serialization): Java 객체 → JSON
JSON 역직렬화(Deserialization): JSON → Java 객체
DTO 클래스의 단점
Controller 클래스에 해당하는 DTO 클래스를 추가적으로 작성해야 함
결과적으로 Controller 클래스가 늘어남에 따라 DTO 클래스가 늘어남
DTO 유효성검증
- 프론트엔드 쪽에서 유효성 검증을 진행했다 하더라도 서버 쪽에서 추가적으로 유효성 검증을 반드시 진행해야
의존성 추가
1
2
3
4
5
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
...
...
}
유효성 검증을 위한 어노테이션
1
2
3
4
5
6
7
8
9
10
11
public class MemberPostDto {//회원등록 컨트롤러
@NotBlank
@Email
private String email;
@NotBlank(message = "이름은 공백이 아니어야 합니다.")
private String name;
@Pattern(regexp = "^010-\\d{3,4}-\\d{4}$",
message = "휴대폰 번호는 010으로 시작하는 11자리 숫자와 '-'로 구성되어야 합니다.")
private String phone;
- Jakarta Bean Validation의 애너테이션을 이용하면 Controller 로직에서 유효성 검증 로직을 분리 가능
Dto 유효성 검증 로직 실행
Spring에서 지원하는
@Validated애너테이션을 사용하면 쿼리 파라미터(Query Parameter 또는 Query String) 및@Pathvariable에 대한 유효성 검증을 진행할 수 있음유효성 검증 애너테이션이 추가된 DTO 클래스에서 유효성 검증 로직이 실행되게 하기 위해서는
DTO 클래스에
@Valid애너테이션을 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RestController
@RequestMapping("/v1/members")
@Validated // 유효성
public class MemberController {
@PatchMapping("/{member-id}")
public ResponseEntity patchMember
(@PathVariable("member-id") @Min(1) long memberId,
@Valid//유효성 @RequestBody MemberPatchDto memberPatchDto) {
memberPatchDto.setMemberId(memberId);
//need Business logic
return new ResponseEntity<>(memberPatchDto, HttpStatus.OK);
}
}