DTO (Data Transfer Object)
DTO란 계층간 데이터 교환을 위해 사용하는 객체(Java Beans)
DTO는 왜 필요할까?
1. Entity
2. Service
3. Dto
4.Controller
위 예제 코드의 테스트 코드는 Posts라는 엔티티를 생성하는 코드이다. 이를 위해 맨 처음에 PostsSaveRequestDto라는 Dto 객체를 빌더 패턴으로 생성하고 Dto를 컨트롤러에게 던져준다. 컨트롤러는 해당 Dto를 다시 Service에게 넘겨주고, Service 단에서 JPA를 이용하여 생성된 객체를 저장한다.
그런데 DTO와 Entity는 거의 똑같은 것 같은데, 왜 변환을 해서 사용해야 하며, 그렇다면 언제 DTO가 필요할까?
- Entity클래스와 거의 유사한 형태임에도 DTO 클래스를 추가로 생성하는 이유는 Entity 클래스가 데이터베이스와 맞닿은 핵심 클래스이기 때문
Entity 클래스를 기준으로 테이블이 생성되고 스키마가 변경되는데, 화면 변경과 같은 사소한 기능 변경을 위해 테이블과 연결된 Entity 클래스를 변경하는 것이 너무나 큰 변경이 될 수 있음
또한 View Layer와 DB Layer 역할 분리를 철저히 하는 것이 좋은데, 실제로 Controller에서 결과값으로 여러 테이블을 조인해서 줘야 할 경우가 빈번하기 때문에 Entity 클래스만으로 표현하기 어려운 경우가 많음 - 다양한 비즈니스 로직과 요구사항에 대해 유연하게 대응할 수 있음
파라미터로 엔티티 자체를 받게 되면 엔티티에서 정해진 포맷에 맞춰 개발을 해야 한다. 하지만 DTO는 각 비즈니스 로직에 맞춘 필드들만 생성함으로써 DTO를 보면 어떤 값들이 매핑되는지 쉽게 파악할 수 있고, 만약 API 설계 상황에서 필드에 다른 이름을 부여하거나 하는 상황에서도 유연하게 대처할 수 있음 - Controller와 Service 사이에서 강한 의존을 방지하기 위해 DTO를 사용한다.
Service가 받고 싶은 파라미터가 Controller에게 종속적이게 되면 Service가 Controller 패키지에게 의존하게 된다. 따라서 이를 방지하기 위해서라도 Service가 원하는 포맷에 맞춰 Controller 단에서 DTO를 통해 그 포맷을 맞추는 것 - Service 레이어가 모듈로 분리되어버리면 해당 Type을 쓸 수 없게 된다.
- 트랜잭션으로 처리되어야 하는 DTO 항목이, 항상 요청으로 들어온 결과값과 동일하지 않을 수 있다.
위 그림에서 사용자 요청의 파라미터를 통해 외부 API를 여러번 호출한 이후 Service 레이어를 호출하는 경우, Controller가 받은 Web DTO와 Service가 받아야 할 DTO가 달라진다.
외부 API 호출뿐만 아니라 Client 요청 이후 Service 레이어를 호출하기 전 다른 작업으로 인해 데이터 포맷이 달라질 수도 있다.
이런 경우에 Service 레이어가 Controller 레이어 DTO에 의존하고 있다면 문제가 될 수 있다. 따라서 Service 레이어는 자신이 원하는 포맷으로 데이터를 받을 수 있어야 한다.
참고로 위에 예제에서 Controller에서 (Controller-Service 사이에 중간 레이어를 두고 하는 경우 포함) 외부 API를 조회하는 이유는 Service에서 해당 작업을 수행하는 경우 트랜잭션과 무관한 작업이 트랜잭션 내에 포함되기 때문에 DB 타임아웃과 같은 이슈가 발생할 수 있기 때문이다.
이러한 문제를 해결하기 위해서는 Service는 자신이 원하는 포맷에 맞게 데이터를 받고, Controller에서 그 포맷을 만들어주는 것이 필요하다.
'Study > Spring' 카테고리의 다른 글
[JPA] 테이블 연관관계 매핑 기초 (0) | 2023.02.10 |
---|---|
[Spring] Spring Security란? (0) | 2023.01.31 |
[Spring] 좋은 객체 지향 프로그래밍이란? (0) | 2023.01.24 |
[Spring] JPA 란? (0) | 2023.01.15 |
[Spring] Spring Security + JWT 로그인 (0) | 2023.01.08 |