🎯 목표 : Spring MVC에서의 DTO 개념과 필요성에 대한 이해
📒 DTO(Data Transfer Object)
📌 DTO ?
- Data Transfer Object의 약자로 엔터프라이즈 애플리케이션 아키텍처 패턴의 하나다.
- 계층간 데이터 교환이 이루어 질수 있도록 하는 객체로, JSON과 같은 직렬화에도 사용되는 객체다.
- Controller와 같이 클라이언트 단과 직접 접촉하는 계층에서는 Entity 대신 DTO를 사용하여 데이터를 교환하는 것이 좋다.
- DTO 는 Getter,Setter를 포함하며, 비즈니스 로직은 포함하지 않는다. Setter를 가지는 경우 가변 객체로 활용 될수 있다.
📌 DTO 적용
- 클라이언트 요청 데이터를 하나의 객체로 받을수 있게 적용할수 있다.
@RestController
@RequestMapping("/members")
public class MemberController {
@PostMapping
public ResponseEntity postMember(@RequestParam("email") String email,
@RequestParam("name") String name,
@RequestParam("phone") String phone) {
Map<String, String> map = new HashMap<>();
map.put("email", email);
map.put("name", name);
map.put("phone", phone);
return new ResponseEntity<Map>(map, HttpStatus.CREATED);
}
}
- DTO 객체를 활용하여 위 예시 컨트롤러에 적용해 보았다.
@RestController
@RequestMapping("/members")
public class MemberController {
@PostMapping
public ResponseEntity postMember(@valid MemberPostDto memberPostDto) {
return new ResponseEntity<memberPostDto>(memberPostDto, HttpStatus.CREATED);
}
}
- 위와 같이 코드가 간결해지고, 데이터를 객체에 저장하여 전달 하는 역할을 하고 있다.
- 요청 데이터에 대한 유효성 검증로직도 DTO 클래스에서 작성하여 핸들러 메소드의 간결함을 유지할 수 있다.
@Getter
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;
}
- API 계층에서의 활용성을 확인하기 위해 간단한 예시 코드로 작성하였다.
- Service 계층과 API 계층간 데이터를 주고 받을때, RequestDto -> Entity -> ResponseDto 와 같이 맵핑도 필요하게 될 것이고 다양한 과정이 필요하게 될것이다.
📌 DTO 사용해야 하는 이유?
Entity와 DTO를 분리 해야하는 이유인 동시에 DTO를 사용해야 하는 이유가 된다.
- DTO를 사용하지 않을경우 Entity의 변경에 의해 API 스팩이 변경될수 있다.
- Entity와 API가 1:1로 대응한다면, Entity의 수정이 일어날 때마다 API 스팩을 일일이 변경해야한다.
- 이러한 작업은 번거롭고 에러의 원인이 되며 런타임 에러로 검출될 가능성이 아주 높다.
- 위 경우에서 DTO 객체를 사용하게 되면, DTO에서 Entity로의 맵핑 과정에 컴파일 에러가 발생되므로 Entity의 변경사항을 확인 할수 있다.
- 하나의 Entity에 대하여 여러개의 API가 존재할 수 있다.
- API 별로 Entity에 대해 요구하는 데이터는 다를 수도 있다. 이 경우, 그냥 Entity 객체를 넘겨주게 되면 필요한 데이터를 포함한 불필요한 데이터 까지 API로 넘겨지게 되지만, 기능상 문제는 없을것이다.
- 하지만, JSON 데이터에 나타나서는 안될 데이터를 포함한 보안상에 문제가 발생 할 수 있다.
- JSON 데이터로 전달을 막을수 있는 기능이 있지만, 이는 API 스팩에 맞춰 데이터 전달을 제한 하는 것 이므로, Entity 객체는 API 스팩에 의존성을 갖게 되어 좋지 못한 설계가 된다.
- 또한, API 스팩 마다 데이터의 제한을 변경 해 줘야 될 경우가 발생하므로, 유지 보수가 복잡해 진다.
- 그러므로, DTO를 활용하여 API 스팩에 준하는 데이터를 주고 받을수 있도록 설계하는 것이 좋다.
- 데이터를 주고 받을때 Entity 객체를 그대로 사용한다면, Entity 데이터 외의 데이터를 주고 받고 할수 없다.
- DTO를 사용하면 Entity 데이터 외의 필요한 데이터를 추가하여 전달 할수 있다.
참고 & Reference
- VO(Value Object)는 DTO와 동일한 개념이지만 Read Only로 특정한 비즈니스 데이터 자체의 값을 담는 객체고, DTO는 풀 네임과 같이 레이어 간의 전송 목적의 객체다.
Reference
https://tecoble.techcourse.co.kr/post/2021-05-16-dto-vs-vo-vs-entity/
https://gmlwjd9405.github.io/2018/12/25/difference-dao-dto-entity.html