이 항목에서는 시간이 지남에 따라 쉽게 발전할 수 있는 데이터 계약을 만드는 모범 사례를 나열합니다. 데이터 계약에 대한 자세한 내용은 데이터 계약 사용의 항목을 참조하세요.
스키마 유효성 검사에 대한 참고 사항
데이터 계약 버전 관리와 관련하여 WCF(Windows Communication Foundation)에서 내보낸 데이터 계약 스키마에는 기본적으로 요소가 선택 사항으로 표시되어 있다는 사실 외에는 버전 관리 지원이 없다는 점에 유의해야 합니다.
즉, 새 데이터 멤버 추가와 같은 가장 일반적인 버전 관리 시나리오도 지정된 스키마와 관련하여 원활한 방식으로 구현할 수 없습니다. 데이터 계약의 최신 버전(예: 새 데이터 멤버 포함)은 이전 스키마를 사용하여 유효성을 검사하지 않습니다.
그러나 엄격한 스키마 준수가 필요하지 않은 많은 시나리오가 있습니다. ASP.NET 사용하여 만든 WCF 및 XML 웹 서비스를 비롯한 많은 웹 서비스 플랫폼은 기본적으로 스키마 유효성 검사를 수행하지 않으므로 스키마에서 설명하지 않는 추가 요소를 허용합니다. 이러한 플랫폼을 사용하는 경우 많은 버전 관리 시나리오를 구현하기 쉽습니다.
따라서 두 가지 데이터 계약 버전 관리 지침 집합이 있습니다. 하나는 엄격한 스키마 유효성이 중요한 시나리오에 대한 집합이고, 다른 하나는 그렇지 않은 시나리오에 대한 집합입니다.
스키마 유효성 검사가 필요한 경우 버전 관리
모든 방향에서 엄격한 스키마 유효성이 필요한 경우(신규 및 이전 버전에서 신규로) 데이터 계약은 변경할 수 없는 것으로 간주되어야 합니다. 버전 관리가 필요한 경우 다른 이름 또는 네임스페이스를 사용하여 새 데이터 계약을 만들어야 하며, 데이터 형식을 사용하는 서비스 계약의 버전을 적절하게 지정해야 합니다.
예를 들어 PoProcessing
구매 주문 처리 서비스 계약의 PostPurchaseOrder
작업은 PurchaseOrder
데이터 계약을 준수하는 매개변수를 사용합니다.
PurchaseOrder
계약을 변경해야 하는 경우 새 데이터 계약( 즉, PurchaseOrder2
변경 내용 포함)을 만들어야 합니다. 그런 다음 서비스 계약 수준에서 버전 관리 작업을 처리해야 합니다. 예를 들어 PostPurchaseOrder2
작업이 PurchaseOrder2
매개 변수를 사용하게 만들거나 PoProcessing2
서비스 계약에서 PostPurchaseOrder
작업이 PurchaseOrder2
데이터 계약을 사용하도록 만듭니다.
다른 데이터 계약에서 참조하는 데이터 계약의 변경 내용도 서비스 모델 계층으로 확장됩니다. 예를 들어 이전 시나리오 PurchaseOrder
에서는 데이터 계약을 변경할 필요가 없습니다. 그러나 Customer
데이터 계약의 데이터 멤버가 포함되어 있으며, 그 데이터 계약의 데이터 멤버 Address
는 반드시 변경되어야 합니다. 이 경우, 필요한 변경 사항이 포함된 Address2
데이터 계약, Customer2
데이터 멤버가 포함된 Address2
데이터 계약, 그리고 PurchaseOrder2
데이터 멤버가 포함된 Customer2
데이터 계약을 각각 만들어야 합니다. 이전의 경우와 마찬가지로 서비스 계약도 버전 관리해야 합니다.
이러한 예제에서는 이름이 변경되지만("2"를 추가하여) 버전 번호 또는 날짜와 함께 새 네임스페이스를 추가하여 이름 대신 네임스페이스를 변경하는 것이 좋습니다. 예를 들어 http://schemas.contoso.com/2005/05/21/PurchaseOrder
데이터 계약은 http://schemas.contoso.com/2005/10/14/PurchaseOrder
데이터 계약으로 변경됩니다.
자세한 내용은 모범 사례: 서비스 버전 관리를 참조하세요.
경우에 따라 애플리케이션에서 보낸 메시지에 대해 엄격한 스키마 준수를 보장해야 하지만 들어오는 메시지를 엄격하게 스키마 규격으로 사용할 수는 없습니다. 이 경우 들어오는 메시지에 불필요한 데이터가 포함될 위험이 있습니다. 불필요한 값은 WCF에서 저장 및 반환되므로 스키마가 잘못된 메시지가 전송됩니다. 이 문제를 방지하려면 라운드트립 기능을 해제해야 합니다. 두 가지 방법으로 이 작업을 수행할 수 있습니다.
어떤 형식에도 IExtensibleDataObject 인터페이스를 구현하지 마세요.
서비스 계약에 ServiceBehaviorAttribute 특성을 적용하고 IgnoreExtensionDataObject 속성을
true
로 설정합니다.
라운드트립에 대한 자세한 내용은 Forward-Compatible 데이터 계약을 참조하세요.
스키마 유효성 검사가 필요하지 않은 경우 버전 관리
엄격한 스키마 규정 준수는 거의 필요하지 않습니다. 많은 플랫폼은 스키마에서 설명하지 않는 추가 요소를 허용합니다. 허용되는 한 데이터 계약 버전 관리 및 Forward-Compatible 데이터 계약에 설명된 전체 기능 집합을 사용할 수 있습니다. 다음 지침이 권장됩니다.
이전 버전이 필요한 형식의 새 버전을 보내거나 새 버전이 필요한 이전 버전을 보내려면 일부 지침을 정확히 따라야 합니다. 다른 지침은 반드시 필요한 것은 아니지만 스키마 버전 관리의 향후 영향을 받을 수 있으므로 여기에 나열됩니다.
형식 상속을 통해 데이터 계약의 버전을 지정하지 마세요. 이후 버전을 만들려면 기존 형식에서 데이터 계약을 변경하거나 관련 없는 새 형식을 만듭니다.
상속을 버전 관리 메커니즘으로 사용하지 않고 특정 규칙을 따르는 경우 데이터 계약과 함께 상속을 사용할 수 있습니다. 형식이 특정 기본 형식에서 파생되는 경우 데이터 계약이 동일하지 않은 경우 이후 버전의 다른 기본 형식에서 파생되지 않습니다. 한 가지 예외는 데이터 계약 형식과 해당 기본 형식 간에 계층 구조에 형식을 삽입할 수 있지만 계층 구조의 다른 형식의 가능한 버전에서 다른 멤버와 이름이 같은 데이터 멤버를 포함하지 않는 경우에만 가능합니다. 일반적으로 동일한 상속 계층 구조의 다른 수준에서 이름이 같은 데이터 멤버를 사용하면 심각한 버전 관리 문제가 발생할 수 있으므로 피해야 합니다.
데이터 계약의 첫 번째 버전부터는 라운드트립 기능을 구현하세요 IExtensibleDataObject. 자세한 내용은 Forward-Compatible 데이터 계약을 참조하세요. 이 인터페이스를 구현하지 않고 하나 이상의 형식 버전을 릴리스한 경우 형식의 다음 버전에서 구현합니다.
이후 버전에서는 데이터 계약 이름 또는 네임스페이스를 변경하지 마세요. 데이터 계약의 기본 형식의 이름 또는 네임스페이스를 변경하는 경우 해당 속성Name과 같은 적절한 메커니즘을 사용하여 데이터 계약 이름 및 네임스페이 DataContractAttribute 스를 유지해야 합니다. 이름 지정에 대한 자세한 내용은 데이터 계약 이름을 참조하세요.
이후 버전에서는 데이터 멤버의 이름을 변경하지 마세요. 데이터 멤버의 내부 필드, 속성 또는 이벤트의 이름을 변경하는 경우 해당 속성을
Name
사용하여 DataMemberAttribute 기존 데이터 멤버 이름을 유지합니다.이후 버전에서는 해당 데이터 멤버에 대한 결과 데이터 계약이 변경되도록 데이터 멤버의 기본 필드, 속성 또는 이벤트의 형식을 변경하지 마세요. 인터페이스 형식은 예상 데이터 계약을 결정할 때 Object와 동등합니다.
이후 버전에서는 Order 속성의 DataMemberAttribute 속성을 조정하여 기존 데이터 멤버의 순서를 변경하지 마세요.
이후 버전에서는 새 데이터 멤버를 추가할 수 있습니다. 항상 다음 규칙을 따라야 합니다.
속성은 항상 기본값인 IsRequired에
false
남아 있어야 합니다.기본값
null
이나 0이 멤버에 대해 허용될 수 없는 경우, 멤버가 들어오는 스트림에 없을 때 적절한 기본값을 제공할 수 있도록 OnDeserializingAttribute을 사용하여 콜백 메서드를 제공해야 합니다. 콜백에 대한 자세한 내용은 Version-Tolerant Serialization 콜백을 참조하세요.이 DataMemberAttribute.Order 속성을 사용하여 새로 추가된 모든 데이터 멤버가 기존 데이터 멤버 뒤로 나타나도록 해야 합니다. 이 작업을 수행하는 권장 방법은 다음과 같습니다. 데이터 계약의 첫 번째 버전에 있는 데이터 멤버에는 해당
Order
속성이 설정되지 않아야 합니다. 데이터 계약의 버전 2에 추가된 모든 데이터 멤버의 속성은Order
2로 설정되어야 합니다. 데이터 계약의 버전 3에 추가된 모든 데이터 멤버는Order
3으로 설정되어야 합니다. 둘 이상의 데이터 멤버를 동일한Order
숫자로 설정하는 것이 허용됩니다.
이전 버전에서 IsRequired 속성이 기본 값으로 설정된 경우라도 이후 버전에서 데이터 멤버를 제거하지 마세요.
기존 데이터 멤버의
IsRequired
속성을 버전에서 버전으로 변경하지 마세요.필요한 데이터 멤버(여기서
IsRequired
는true
)의 경우, 속성을 버전마다 변경하지 마세요.분기된 버전 관리 계층을 만들려고 시도하지 마세요. 즉, 항상 이러한 지침에서 허용하는 변경 내용만 사용하여 모든 버전에서 다른 버전으로의 경로가 하나 이상 있어야 합니다.
예를 들어 Person 데이터 계약의 버전 1에 Name 데이터 멤버만 포함된 경우 Age 멤버만 추가하고 버전 2b에 주소 멤버만 추가하는 계약의 버전 2a를 만들어서는 안 됩니다. 2a에서 2b로 이동하면 나이를 제거하고 주소를 추가하는 작업이 포함되며, 다른 방향으로 이동하면 주소를 제거하고 나이를 추가해야 합니다. 멤버 제거는 이러한 지침에 의해 허용되지 않습니다.
일반적으로 새 버전의 애플리케이션에서 기존 데이터 계약 형식의 새 하위 형식을 만들지 않아야 합니다. 마찬가지로 개체로 선언된 데이터 멤버 대신 또는 인터페이스 형식으로 사용되는 새 데이터 계약을 만들면 안 됩니다. 이러한 새 클래스를 만드는 것은 이전 애플리케이션의 모든 인스턴스의 알려진 형식 목록에 새 형식을 추가할 수 있는 경우에만 허용됩니다. 예를 들어 애플리케이션 버전 1에서는 Book 및 Newspaper 데이터 계약 하위 형식이 있는 LibraryItem 데이터 계약 형식이 있을 수 있습니다. 그런 다음 LibraryItem에는 책과 신문이 포함된 알려진 형식 목록이 있습니다. 이제 버전 2에서 LibraryItem의 하위 형식인 Magazine 형식을 추가한다고 가정합니다. 버전 2에서 버전 1로 Magazine 인스턴스를 보내면 알려진 형식 목록에서 Magazine 데이터 계약을 찾을 수 없으며 예외가 throw됩니다.
버전 간에 열거형 멤버를 추가하거나 제거해서는 안 됩니다. 특성의 Name 속성을
EnumMemberAttribute
사용하여 데이터 계약 모델의 이름을 동일하게 유지하지 않는 한 열거형 멤버의 이름을 바꾸면 안 됩니다.컬렉션은 데이터 계약의 컬렉션 형식에 설명된 대로 데이터 계약 모델에서 서로 교환할 수 있습니다. 이렇게 하면 뛰어난 유연성이 가능합니다. 그러나 버전에서 버전으로 교환할 수 없는 방식으로 컬렉션 형식을 실수로 변경하지 않도록 합니다. 예를 들어 사용자 지정되지 않은 컬렉션(즉, 특성이 없는
CollectionDataContractAttribute
컬렉션)에서 사용자 지정된 컬렉션 또는 사용자 지정되지 않은 컬렉션으로 변경하지 마세요. 또한 각 버전 간에 속성을CollectionDataContractAttribute
변경하지 마세요. 기본 컬렉션 형식의 이름 또는 네임스페이스가 변경되고 데이터 계약 이름과 네임스페이스를 이전 버전과 동일하게 설정해야 하는 경우 유일한 변경은 Name 또는 Namespace 속성을 추가하는 것입니다.
여기에 나열된 지침 중 일부는 특별한 상황이 적용될 때 안전하게 무시할 수 있습니다. 지침에서 벗어나기 전에 관련된 직렬화, 역직렬화 및 스키마 메커니즘을 완전히 이해해야 합니다.