REST API-DTO? [닫은]


154

현재 프로젝트에 대한 REST-API를 작성 중이며 모범 사례에 대한 기사를 읽었습니다. 많은 사람들이 DTO에 반대하는 것처럼 보이고 단순히 도메인 모델 만 노출시키는 반면 다른 사람들은 DTO (또는 사용자 모델 또는 호출하려는 대상)가 나쁜 습관이라고 생각하는 것 같습니다. 개인적으로, 나는 이 기사 가 많은 의미가 있다고 생각했습니다 .

그러나 모든 추가 매핑 코드, DTO 대응 부분과 100 % 동일 할 수있는 도메인 모델 등 DTO의 단점도 이해합니다.

우리의 API는 대부분 다른 클라이언트가 데이터를 소비 할 수 있도록 만들어졌지만, 올바르게 사용하면 가능한 경우 자체 웹 GUI에도 사용하려고합니다.

문제는 모든 도메인 데이터를 다른 클라이언트 사용자에게 공개하지 않을 수 있다는 것입니다. 대부분의 데이터는 자체 웹 응용 프로그램에서만 의미가 있습니다. 또한 모든 시나리오, 특히 다른 객체와의 관계 등에서 객체에 대한 모든 데이터를 공개하지 않을 수도 있습니다. 예를 들어 특정 객체의 목록을 공개하는 경우 전체 객체 계층 구조를 공개하지 않아도됩니다. 개체의 자식은 노출되지 않지만 링크 (hateoas)를 통해 검색 할 수 있습니다.

이 문제를 해결하려면 어떻게해야합니까? 도메인 모델에서 Jackson 믹스 인을 사용하여 다른 시나리오에서 어떤 데이터가 노출 될지를 제어하려고 생각했습니다. 아니면 단점과 논쟁이 있더라도 DTO를 계속 사용해야합니까?


9
이 질문이 닫히더라도 놀라지 마십시오. 토론 기반 질문에 더 가깝기 때문에 명확한 정답이 없습니다. 다른 사람들에게 물어 보면 다른 답변을 얻을 수 있습니다.
Ben Thurley

2
해당 기사 링크 ( ibm.com/developerworks/community/blogs/barcia/entry/… )가 손상되었습니다.
pinkpanther

7
@pinkpanther 대단한 기사이며 더 이상 사용할 수없는 것이 유감입니다. 다음은 웹 아카이브 캐시 버전 입니다.
cassiomolin

답변:


252

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 수업에 더 나은 이름을 부여하려면이 답변을 참조하십시오 .


2
DTO 방식으로 진행 한 경우 모든 도메인 개체를 DTO 또는 동일하지 않은 도메인 개체에 매핑 하시겠습니까? 또한 다양한 시나리오 / 컨텍스트를 기반으로 데이터를 노출하는 문제를 어떻게 해결 하시겠습니까? 도메인 개체 당 여러 DTO?
benbjo

6
@benbjo 그것은 당신에게 달려 있습니다. 나는 보통 가장 복잡한 엔터티 만 DTO에 매핑합니다. 모든 속성을 노출하고 싶지 않은 엔터티와 관계가 많은 엔터티입니다. DTO 는 HATEOAS에서 사용할 링크 목록을 가질 수있는 유연성을 제공합니다 . 이것이 내 지속성 객체에 추가하지 않는 종류입니다.
cassiomolin

2
@molin은 정보와 제안에 감사드립니다. MapStruct를 확실히 확인하겠습니다. 한눈에 그것은 내 요구에 아주 잘 맞는 것 같습니다.
benbjo

6
친애하는 downvoter, 최소한 downvote의 이유를 설명해 주시겠습니까?
cassiomolin 2016 년

8
REST API에서 도메인 엔티티 대신 DTO를 사용해야하는 아키텍처적인 이유도 있습니다. 기존 클라이언트가 중단되지 않도록 REST API를 변경해서는 안됩니다. API에서 도메인 모델을 직접 사용하는 경우 API와 도메인 모델간에 바람직하지 않은 연결을 만듭니다. Service Loose Coupling 설계 원칙에 따라 서비스 계약은 서비스 로직 또는 구현 세부 사항과 밀접하게 연결되어서는 안됩니다.
Paulo Merson

25

API가 공개되어 있고 여러 버전을 지원해야하는 경우 DTO를 사용해야합니다.

반면 개인 API이고 클라이언트와 서버를 모두 제어하는 ​​경우 DTO를 건너 뛰고 직접 도메인 모델을 노출시키는 경향이 있습니다.


나는 마지막 부분에서 당신에 동의하고 나는 보통 그렇게하지만, 이것은 나의 첫 번째 공개 API입니다. 공개 부분에 DTO를 사용하는 것에 대한 의견을 고려할 것입니다. "자신의 개밥을 먹는 것"이 ​​좋은 원칙이더라도 API의 개인 부분과 공용 부분은 실제로 분리되어야합니다.
benbjo

11

저는 DTO를 사용하는 경향이 있습니다.

나는 단점을 좋아하지 않지만 다른 옵션은 더 나쁘다.

도메인 개체가 노출되면 보안 문제와 데이터 유출이 발생할 수 있습니다. Jackson 주석은 문제를 해결하는 것처럼 보이지만 실수를하거나 노출해서는 안되는 데이터를 노출하는 것은 너무 쉽습니다. DTO 클래스를 설계 할 때는 그러한 실수를하기가 훨씬 어렵습니다.

다른 한편으로 DTO 접근 방식의 단점은 객체 대 객체 매핑 및 롬복 과 같은 것들로 보일러 플레이트 를 줄이면서 줄일 수 있습니다 .


9

이미 말했듯이 이것은 분명히 의견 관련 질문입니다. 필자는 필요한 모든 상용구 코드로 인해 No-DTO 접근 방식에 더 매료되었습니다.

이것은 json / rest api의 응답 측에 주로 적용됩니다. 나는이 경우에 많은 json보기 / 필터를 작성하지 않기 위해 jackson addon을 작성했습니다 : https://github.com/Antibrumm/jackson-antpathfilter

반면에 DTO는 이러한 API의 요청 입력 측면에서 좋은 것입니다. 예를 들어, 엔티티에서 직접 작업하는 것은 양방향 관계를 고려하기가 매우 어려울 수 있습니다. 또한 호출자가 예를 들어 "작성자"속성을 수정하게하고 싶지 않습니다. 따라서 이러한 요청을 매핑하는 동안 특정 필드를 폐기해야합니다.


2
나는 내 질문이 다소 의견과 관련이 있고 (추천되지 않음) 동의하지만 내 문제를 해결하는 방법에 대한 팁을 찾고있었습니다. Jackson addon을 많이 사용하지만 믹스 인을 사용하여 다른 시나리오에서 노출해야 할 데이터를 제어하는 ​​것이 좋은 방법이라고 생각합니까?
benbjo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.