엔티티 대신 DTO를 사용하는 것은 무엇입니까?


18

RCP 응용 프로그램을 개발 중입니다.이 응용 프로그램을 처음 사용했습니다.

스프링 빈은 엔티티를 저장 / 페치하기위한 비즈니스 로직을 작성하는 데 사용됩니다.

그러나 엔터티를 클라이언트로 직접 보내는 대신 DTO로 변환하고 클라이언트 를 채우고 있습니다. 저장하는 동안 우리는 다시 DTO를 엔티티로 변환하고 저장합니다.

이러한 전환의 이점은 무엇입니까? 누군가 설명 할 수 있습니까?


What's the benefit of these conversions?소비자에게 제공되는 데이터 모델 (표현)에서 지속성 데이터 모델을 분리합니다. 디커플링의 이점은 SE에서 널리 논의되었지만 DTO 아래의 목표는 클라이언트가 서버에 대한 호출을 저장하는 데 필요한 많은 정보를 단일 응답으로 수집하는 것입니다. 통신 클라이언트 서버를 더 매끄럽게 만드는 요소
Laiv


당신의 예는 훌륭합니다. 고객 인 경우 (보기 ...) 변경하기가 쉽지만, 가장 큰 문제는 시스템에 이미 타사와 통합되어있을 때 (계약, 수수료 ...) 변경이 불가능하다는 것입니다. 시스템에 타사 통합 기능이 있으면 DTO를 사용하십시오.
Lucas Gonçalves

답변:


45

개발자가 "이것이 무슨 요점입니까?" 이를 위해 몇 가지 예를 보여 드리겠습니다.


모든 예제는이 간단한 데이터 모델을 기반으로합니다.

Person엔티티 다섯 개 속성이 있습니다 :Id, FirstName, LastName, Age, CityId

또한 응용 프로그램에서이 데이터를 다양한 방법 (보고서, 양식, 팝업 등)으로 사용한다고 가정 할 수 있습니다.

전체 응용 프로그램이 이미 존재합니다. 내가 언급 한 것은 기존 코드베이스의 변경입니다. 이것은 기억해야합니다.


예 1-기본 데이터 구조 변경-DTO 없음

요구 사항이 변경되었습니다. 사람의 나이는 정부 데이터베이스에서 동적으로 검색해야합니다 (이름과 성을 기준으로 가정).

Age더 이상 값을 로컬 에 저장할 필요가 없으므로 Person엔티티 에서 값을 제거해야합니다 . 엔터티 가 데이터베이스 데이터를 나타내는 것을 인식하는 것이 중요합니다 . 데이터베이스에 없으면 엔터티에 없습니다.
정부 웹 서비스에서 연령을 검색하면 다른 객체 (또는 int)에 저장됩니다.

그러나 프론트 엔드에는 여전히 나이가 표시됩니다. 모든보기가 Person.Age더 이상 존재하지 않는 특성 을 사용하도록 설정되었습니다 . 문제 자체가 나타납니다. 개인 을 참조하는 모든 견해를 Age수정해야합니다 .


예 2-기본 데이터 구조 변경-DTO 사용

이전 시스템 PersonDTO에는 동일한 5 가지 속성을 가진 엔티티 도 있습니다 Id, FirstName, LastName, Age, CityId. 를 검색 한 후 Person서비스 계층은이를로 변환 PersonDTO한 다음이를 반환합니다.

그러나 이제 요구 사항이 변경되었습니다. 사람의 나이는 정부 데이터베이스에서 동적으로 검색해야합니다 (이름과 성을 기준으로 가정).

Age더 이상 값을 로컬 에 저장할 필요가 없으므로 Person엔티티 에서 값을 제거해야합니다 . 엔터티 가 데이터베이스 데이터를 나타내는 것을 인식하는 것이 중요합니다 . 데이터베이스에 없으면 엔터티에 없습니다.

당신이 중간이 있기 때문에 그러나 PersonDTO,이 클래스는 할 수 있는지 중요 계속Age 속성을. 서비스 계층은를 가져 와서 Person로 변환 PersonDTO한 다음 정부 웹 서비스에서 사람의 나이를 가져 와서 해당 값을에 저장하고 PersonDTO.Age해당 객체를 전달합니다.

여기서 중요한 부분 은 서비스 계층을 사용 하는 사람은 기존 시스템과 새로운 시스템의 차이를 볼 수 없다는 것 입니다. 여기에는 프론트 엔드가 포함됩니다. 이전 시스템에서는 전체 PersonDTO객체를 받았습니다 . 그리고 새로운 시스템에서는 여전히 완전한 PersonDTO객체를 받습니다 . 보기를 업데이트 할 필요가 없습니다 .

이것이 우려 분리 라는 문구를 사용할 때의 의미 입니다. 데이터베이스에 데이터를 저장하고 프런트 엔드에 데이터를 표시하는 두 가지 다른 우려가 있으며 각각 다른 데이터 유형이 필요합니다. 이 두 데이터 유형에 현재 동일한 데이터가 포함되어 있어도 나중에 변경 될 수 있습니다.
주어진 예 Age에서 두 데이터 유형의 차이점은 다음과 같습니다. Person(데이터베이스 엔티티)에는 (가 필요하지 Age않지만 PersonDTO(프론트 엔드 데이터 유형)에는 필요합니다.
코드베이스는 우려 사항 (= 별도의 데이터 유형 생성)을 처음부터 분리함으로써 데이터 모델의 변경 사항에 대해 훨씬 탄력적입니다.

데이터베이스에 새 열을 추가 할 때 DTO 객체가 있으면 엔티티와 DTO 모두에 속성을 추가하여 이중 작업을 수행해야 함을 의미 할 수 있습니다. 즉 기술적으로 올바른. 하나의 클래스 대신 두 개의 클래스를 유지하려면 약간의 추가 노력이 필요합니다.

그러나 필요한 노력을 비교해야합니다. 하나 이상의 새 열이 추가되면 몇 가지 속성을 복사 / 붙여 넣는 데 시간이 오래 걸리지 않습니다. 데이터 모델이 구조적으로 변경 될 때, 프론트 엔드를 변경해야하는 경우 (컴파일 타임이 아닌 런타임시에만 버그를 발생시키는 방식으로) 더 많은 노력이 필요하며 개발자가 버그를 찾아야합니다.


더 많은 예를들 수 있지만 원칙은 항상 같습니다.

요약

  • 별도의 책임 (관심)은 서로 별도로 일해야합니다. 그들은 (예를 들어, 이러한 데이터 클래스로 모든 자원을 공유해서는 안 Person)
  • 엔터티와 해당 DTO에 동일한 속성이 있다고해서 동일한 엔터티로 병합해야한다는 의미는 아닙니다. 모서리를 자르지 마십시오.
    • 좀 더 뻔뻔한 예로, 데이터베이스에 국가, 노래 및 사람이 포함되어 있다고 가정 해 보겠습니다. 이들 기관 모두는있다 Name. 그러나 그들 모두가 Name속성을 가지고 있다고해서 공유 EntityWithName기본 클래스 에서 상속해야한다는 것을 의미하지는 않습니다 . 다른 Name속성에는 의미있는 관계가 없습니다.
    • 속성 중 하나 Name가 변경되면 (예 : 노래의 이름이 변경 Title되거나 사람이 a FirstName및을 얻는 경우 LastName), 처음에는 필요하지 않은 상속 취소하기 위해 더 많은 노력을 기울여야합니다 .
    • 뻔뻔 스럽지는 않지만 엔티티가있을 때 DTO가 필요하지 않다는 주장은 동일합니다. 당신이보고있는 지금 ,하지만 당신은 미래의 변화에 대비 아닙니다. IF 엔티티와 DTO는 동일하며, 경우 당신이 데이터 모델 변경이 결코 것이라는 점을 보장 할 수 있습니다; 그러면 DTO를 생략 할 수있는 것입니다. 그러나 문제는 데이터 모델이 절대 변경되지 않는다는 것을 절대 보장 할 수 없다는 것입니다.
  • 모범 사례가 항상 즉시 보상을받는 것은 아닙니다. 오래된 응용 프로그램을 다시 방문해야 할 경우 나중에 지불을 시작할 수 있습니다.
  • 기존 코드베이스의 주요 킬러는 코드 품질을 떨어 뜨리고 유지 관리가 불가능한 스파게티 코드의 쓸모없는 혼란으로 이어질 때까지 코드베이스를 유지하기가 더 어려워지는 것입니다.
  • 얻을 수있는 문제와의 분리를 구현하는 것과 같은 모범 사례는 코드베이스를 가능한 한 오랫동안 유지 관리 할 수 ​​있도록 유지 관리의 미끄러운 경사를 피하는 것입니다.

문제를 분리하는 것을 고려할 때 일반적으로 다음과 같이 생각하십시오.

모든 관심사 (UI, 데이터베이스, 논리)가 다른 위치의 다른 사람에 의해 처리된다고 가정하십시오. 그들은 이메일로만 통신 할 수 있습니다.

잘 분리 된 코드베이스에서 특정 관심사에 대한 변경은 한 사람 만 처리하면됩니다.

  • 사용자 인터페이스 변경에는 UI 개발자 만 포함됩니다.
  • 데이터 저장 방법 변경에는 데이터베이스 개발자 만 포함됩니다.
  • 비즈니스 로직을 변경하려면 비즈니스 개발자 만 참여해야합니다.

이러한 모든 개발자가 동일한 Person엔터티를 사용하고 있고 엔터티를 약간 변경 한 경우 모든 사람 이 프로세스에 참여해야합니다.

그러나 모든 계층에 대해 별도의 데이터 클래스를 사용함으로써 그 문제는 널리 퍼지지 않습니다.

  • 데이터베이스 개발자가 유효한 PersonDTO객체를 반환 할 수 있는 한 비즈니스 및 UI 개발자는 데이터 저장 / 검색 방법을 변경하지 않아도됩니다.
  • 비즈니스 개발자가 데이터를 데이터베이스에 저장하고 필요한 데이터를 프런트 엔드에 제공하는 한 데이터베이스 및 UI 개발자는 자신의 비즈니스 규칙을 재 작업하기로 결정하더라도 신경 쓰지 않습니다.
  • `PersonViewModel을 기반으로 UI를 디자인 할 수있는 한 UI 개발자는 원하는대로 UI를 만들 수 있습니다. 데이터베이스 및 비즈니스 개발자는 데이터베이스에 영향을 미치지 않기 때문에 수행 방식에 신경 쓰지 않습니다.

여기서 중요한 문구는 영향을 미치지 않기 때문 입니다. 관심사 분리를 제대로 구현하려면 다른 당사자에게 영향을 미치고 이에 관여해야하는 문제를 최소화해야합니다.

물론, 몇 가지 주요 변경 사항은 완전히 새로운 엔티티가 데이터베이스에 추가 될 때 둘 이상의 사람을 포함하지 않아도됩니다. 그러나 응용 프로그램 수명 동안 수행해야 할 사소한 변경 량을 과소 평가하지 마십시오. 주요 변경 사항은 소수입니다.


포괄적 인 답변, 감사합니다. 질문이 있습니다. 당신이 대답하면 감사 하십시오 : 1- 내가 틀렸다면 나를 수정하십시오. Business Object 또는 View ObjectPresentation LayerBusiness Layer 간에 데이터를 전송하기위한 것이고 Entity ObjectBusiness LayerData Access Layer 간에 데이터를 전송하기위한 것 입니다. DTO는 바보 BO로 사용할 수 있습니다. 2- 두 견해에 회사의 다른 정보가 필요하다고 가정하면 두 개의 다른 회사 DTO가 필요합니까?
Arash

1
@Arash (1) "DTO"는 실제로 두 계층 간 교환에 사용되는 모든 데이터 클래스에 대한 포괄적 인 정의입니다. 비즈니스 개체와 뷰 개체는 모두 DTO입니다. (2) 그것은 많은 것들에 달려 있습니다. 필요한 모든 필드 모음에 대해 새 dto를 만드는 것은 번거로운 작업입니다. 회사 전체의 DTO (합리적인 경우)를 단순히 반환 한 다음 관심 분야를 선택하도록하는 것은 본질적으로 잘못된 것이 아닙니다. 이는 적절한 우려 분리를 구현하고 과도한 엔지니어링과 무의미한 반복을 피하는 것 사이의 균형을 찾는 문제입니다.
Flater

이제 이해가 되네요. 고마워 더 평평합니다.
Arash

질문 하나 더 "비즈니스 오브젝트 보기 오브젝트"라고 말했습니다. 나는 둘 다 같다고 생각했다. 검색했을 때 Business ObjectView Object 와 비교할 때 일반적인 의미가 있음을 깨달았습니다 . 그러나 Business Object유스 케이스 에서 파생되어야 하고 Entity Object데이터 모델 에서 파생되어야 하므로 서로 다릅니다. 맞습니까? 좀 설명해 주시겠습니까?
Arash

@Arash : "비즈니스 객체"와 "뷰 객체"의 차이점은 context 입니다. 우리 인간에게는 그 구별이 사물을 제대로 이해하는 데 중요합니다. 그러나 컴파일러 (및 언어 자체)는 기술적으로 차이가 없습니다. 그들이 같다고 말할 때, 나는 기술적 인 관점에서 그것을 의미합니다. 둘 다 데이터를 보유하고 전달할 속성이있는 클래스 일뿐입니다. 그런 점에서 그들 사이에는 차이가 없습니다.
Flater
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.