현재 프로젝트에 대한 REST-API를 작성 중이며 모범 사례에 대한 기사를 읽었습니다. 많은 사람들이 DTO에 반대하는 것처럼 보이고 단순히 도메인 모델 만 노출시키는 반면 다른 사람들은 DTO (또는 사용자 모델 또는 호출하려는 대상)가 나쁜 습관이라고 생각하는 것 같습니다. 개인적으로, 나는 이 기사 가 많은 의미가 있다고 생각했습니다 .
그러나 모든 추가 매핑 코드, DTO 대응 부분과 100 % 동일 할 수있는 도메인 모델 등 DTO의 단점도 이해합니다.
우리의 API는 대부분 다른 클라이언트가 데이터를 소비 할 수 있도록 만들어졌지만, 올바르게 사용하면 가능한 경우 자체 웹 GUI에도 사용하려고합니다.
문제는 모든 도메인 데이터를 다른 클라이언트 사용자에게 공개하지 않을 수 있다는 것입니다. 대부분의 데이터는 자체 웹 응용 프로그램에서만 의미가 있습니다. 또한 모든 시나리오, 특히 다른 객체와의 관계 등에서 객체에 대한 모든 데이터를 공개하지 않을 수도 있습니다. 예를 들어 특정 객체의 목록을 공개하는 경우 전체 객체 계층 구조를 공개하지 않아도됩니다. 개체의 자식은 노출되지 않지만 링크 (hateoas)를 통해 검색 할 수 있습니다.
이 문제를 해결하려면 어떻게해야합니까? 도메인 모델에서 Jackson 믹스 인을 사용하여 다른 시나리오에서 어떤 데이터가 노출 될지를 제어하려고 생각했습니다. 아니면 단점과 논쟁이 있더라도 DTO를 계속 사용해야합니까?
답변
REST API에서 DTO를 사용해야하는 이유
DTO는 약자에 대한 D ATA T 를 ransfer O bject .
이 패턴은 웹 서비스 처럼 원격 인터페이스 로 데이터를 전송 하는 매우 잘 정의 된 목적으로 만들어졌습니다 . 이 패턴은 REST API에 매우 적합하며 DTO는 장기적으로 더 많은 유연성 을 제공합니다 .
애플리케이션 의 도메인 을 나타내는 모델과 API 가 처리 하는 데이터 를 나타내는 모델은 서로 다른 관심사 이며 서로 분리 되어야합니다 . 애플리케이션 도메인 모델에서 필드를 추가, 제거 또는 이름을 바꿀 때 API 클라이언트를 중단하지 않으려 고합니다.
서비스 계층은 도메인 / 지속성 모델에서 작동하지만 API 컨트롤러는 다른 모델 집합에서 작동해야합니다. 예를 들어, 도메인 / 지속성 모델이 새로운 비즈니스 요구 사항을 지원하도록 발전함에 따라 이러한 변경을 지원하기 위해 새 버전의 API 모델을 만들 수 있습니다. 새 버전이 출시 될 때 이전 버전의 API를 더 이상 사용하지 않을 수도 있습니다. 그리고 사물이 분리 될 때 완벽하게 달성 할 수 있습니다.
퍼시스턴스 모델 대신 DTO 노출의 몇 가지 이점을 언급하면 다음과 같습니다.
-
API 모델에서 지속성 모델을 분리 합니다.
-
DTO는 필요에 맞게 조정할 수 있으며 지속성 엔터티의 특성 집합 만 노출 할 때 유용합니다. 당신은 같은 주석이 필요하지 않습니다
@XmlTransient
및@JsonIgnore
일부 속성의 직렬화를 방지 할 수 있습니다. -
DTO를 사용하면 지속성 엔터티 에 주석 이 포함되지 않습니다. 즉, 지속성 엔터티에 비 지속성 관련 주석이 포함되지 않습니다.
-
당신은해야합니다 모든 권한 을 만들거나 자원을 업데이트 할 때 당신이 받고있는 속성 이상을.
-
당신이 사용하는 경우 자신감을 , 당신은 사용할 수 있습니다
@ApiModel
및@ApiModelProperty
주석 당신의 영속 엔티티를 엉망으로하지 않고 API 모델을 문서화 할 수 있습니다. -
각 버전의 API마다 다른 DTO를 가질 수 있습니다.
-
관계를 매핑 할 때 유연성이 향상됩니다.
-
미디어 유형마다 다른 DTO를 가질 수 있습니다.
-
DTO는 HATEOAS에 대한 링크 목록을 가질 수 있습니다 . 그것은 영속 객체에 추가해서는 안되는 종류입니다. 사용하는 경우 봄 HATEOAS을 , 당신은 당신의 DTO 클래스를 확장 할 수 있습니다
RepresentationModel
(이전으로 알려진ResourceSupport
) 또는로 포장EntityModel
(이전으로 알려진Resource<T>
).
상용구 코드 다루기
지속성 엔터티를 DTO에 매핑하거나 그 반대로 수동 으로 매핑 할 필요는 없습니다 . 이를 위해 사용할 수 있는 많은 매핑 프레임 워크 가 있습니다. 예를 들어 주석 기반이며 Maven Annotation Processor로 작동하는 MapStruct를 살펴보십시오 . CDI 및 Spring 기반 애플리케이션 모두에서 잘 작동합니다.
또한 getter, setter , 및 메소드 를 생성 하기 위해 Lombok 을 고려할 수도 있습니다.equals()
hashcode()
toString()
관련 : DTO 수업에 더 나은 이름을 부여하려면이 답변을 참조하십시오 .
답변
API가 공개되어 있고 여러 버전을 지원해야하는 경우 DTO를 사용해야합니다.
반면 개인 API이고 클라이언트와 서버를 모두 제어하는 경우 DTO를 건너 뛰고 직접 도메인 모델을 노출시키는 경향이 있습니다.
답변
저는 DTO를 사용하는 경향이 있습니다.
나는 단점을 좋아하지 않지만 다른 옵션은 더 나쁘다.
도메인 개체가 노출되면 보안 문제와 데이터 유출이 발생할 수 있습니다. Jackson 주석은 문제를 해결하는 것처럼 보이지만 실수를하거나 노출해서는 안되는 데이터를 노출하는 것은 너무 쉽습니다. DTO 클래스를 설계 할 때는 그러한 실수를하기가 훨씬 어렵습니다.
다른 한편으로 DTO 접근 방식의 단점은 객체 대 객체 매핑 및 롬복 과 같은 것들로 보일러 플레이트 를 줄이면서 줄일 수 있습니다 .
답변
이미 말했듯이 이것은 분명히 의견 관련 질문입니다. 필자는 필요한 모든 상용구 코드로 인해 No-DTO 접근 방식에 더 매료되었습니다.
이것은 json / rest api의 응답 측에 주로 적용됩니다. 나는이 경우에 많은 json보기 / 필터를 작성하지 않기 위해 jackson addon을 작성했습니다 : https://github.com/Antibrumm/jackson-antpathfilter
반면에 DTO는 이러한 API의 요청 입력 측면에서 좋은 것입니다. 예를 들어, 엔티티에서 직접 작업하는 것은 양방향 관계를 고려하기가 매우 어려울 수 있습니다. 또한 호출자가 예를 들어 “작성자”속성을 수정하게하고 싶지 않습니다. 따라서 이러한 요청을 매핑하는 동안 특정 필드를 폐기해야합니다.