이 항목에서는 서비스 계약의 정의 방법, 사용 가능한 작업(및 기본 메시지 교환에 미치는 영향), 사용되는 데이터 형식 및 시나리오의 요구 사항을 충족하는 작업을 설계하는 데 도움이 되는 기타 문제에 대해 설명합니다.
서비스 계약 만들기
서비스는 여러 작업을 노출합니다. WCF(Windows Communication Foundation) 애플리케이션에서 메서드를 만들고 특성으로 OperationContractAttribute 표시하여 작업을 정의합니다. 그런 다음, 서비스 계약을 만들려면 작업을 특성으로 표시된 인터페이스 내에서 선언하거나 동일한 특성으로 ServiceContractAttribute 표시된 클래스에서 정의하여 작업을 그룹화합니다. (기본 예제는 방법: 서비스 계약 정의)을 참조하세요.
특성이 없는 OperationContractAttribute 메서드는 서비스 작업이 아니며 WCF 서비스에서 노출되지 않습니다.
이 항목에서는 서비스 계약을 디자인할 때 다음 결정 사항에 대해 설명합니다.
클래스 또는 인터페이스를 사용할지 여부입니다.
교환할 데이터 형식을 지정하는 방법입니다.
사용할 수 있는 교환 패턴의 형식입니다.
명시적 보안 요구 사항을 계약의 일부로 만들 수 있는지 여부입니다.
작업 입력 및 출력에 대한 제한 사항입니다.
클래스 또는 인터페이스
클래스와 인터페이스는 모두 기능 그룹을 나타내므로 둘 다 WCF 서비스 계약을 정의하는 데 사용할 수 있습니다. 그러나 인터페이스는 서비스 계약을 직접 모델링하므로 사용하는 것이 좋습니다. 구현이 없으면 인터페이스는 특정 서명을 사용하여 메서드 그룹화만 정의하지 않습니다. 서비스 계약 인터페이스를 구현하고 WCF 서비스를 구현했습니다.
관리되는 인터페이스의 모든 이점은 서비스 계약 인터페이스에 적용됩니다.
서비스 계약 인터페이스는 여러 다른 서비스 계약 인터페이스를 확장할 수 있습니다.
단일 클래스는 이러한 서비스 계약 인터페이스를 구현하여 여러 서비스 계약을 구현할 수 있습니다.
서비스 계약은 동일하게 유지되는 동안 인터페이스 구현을 변경하여 서비스 계약의 구현을 수정할 수 있습니다.
이전 인터페이스와 새 인터페이스를 구현하여 서비스의 버전을 지정할 수 있습니다. 이전 클라이언트는 원래 버전에 연결하지만 최신 클라이언트는 최신 버전에 연결할 수 있습니다.
비고
다른 서비스 계약 인터페이스에서 상속하는 경우 이름 또는 네임스페이스 같은 작업 속성을 재정의할 수 없습니다. 이렇게 하려면 현재 서비스 계약에서 새 작업을 만듭니다.
인터페이스를 사용하여 서비스 계약을 만드는 예제는 방법: 계약 인터페이스를 사용하여 서비스 만들기를 참조하세요.
그러나 클래스를 사용하여 서비스 계약을 정의하고 동시에 해당 계약을 구현할 수 있습니다. 클래스에 ServiceContractAttribute를, 클래스 내 메서드에 OperationContractAttribute을 각각 직접 적용하여 서비스를 만들 때의 장점은 속도와 단순성입니다. 단점은 관리되는 클래스가 여러 상속을 지원하지 않으므로 한 번에 하나의 서비스 계약만 구현할 수 있다는 것입니다. 또한 클래스 또는 메서드 서명을 수정하면 해당 서비스에 대한 공용 계약이 수정되어 수정되지 않은 클라이언트가 서비스를 사용하지 못하게 할 수 있습니다. 자세한 내용은 서비스 계약 구현을 참조하세요.
클래스를 사용하여 서비스 계약을 만들고 동시에 구현하는 예제는 방법: 계약 클래스를 사용하여 서비스 만들기를 참조하세요.
이 시점에서 인터페이스를 사용하고 클래스를 사용하여 서비스 계약을 정의하는 것의 차이점을 이해해야 합니다. 다음 단계는 서비스와 해당 클라이언트 간에 주고받을 수 있는 데이터를 결정하는 것입니다.
매개 변수 및 반환 값
각 작업에는 반환 값과 매개 변수가 있으며, 이들이 void
인 경우에도 그렇습니다. 그러나 한 개체에서 다른 개체로 개체에 대한 참조를 전달할 수 있는 로컬 메서드와 달리 서비스 작업은 개체에 대한 참조를 전달하지 않습니다. 대신 개체의 복사본을 전달합니다.
이는 매개 변수 또는 반환 값에 사용되는 각 형식을 serialize할 수 있어야 하므로 중요합니다. 즉, 해당 형식의 개체를 바이트 스트림으로 변환하고 바이트 스트림에서 개체로 변환할 수 있어야 합니다.
기본 형식은 .NET Framework의 여러 형식과 마찬가지로 기본적으로 직렬화할 수 있습니다.
비고
작업 서명에 있는 매개변수 이름의 값은 계약의 일부이며, 대소문자 구분이 적용됩니다. 동일한 매개 변수 이름을 로컬로 사용하지만 게시된 메타데이터에서 이름을 수정하려면 다음을 참조하세요 System.ServiceModel.MessageParameterAttribute.
데이터 계약
WCF(Windows Communication Foundation) 애플리케이션과 같은 서비스 지향 애플리케이션은 Microsoft 및 비 Microsoft 플랫폼 모두에서 가능한 가장 많은 수의 클라이언트 애플리케이션과 상호 운용되도록 설계되었습니다. 가능한 가장 광범위한 상호 운용성을 위해 서비스 운영에서 교환하는 데이터를 설명하는 서비스 계약의 일부인 데이터 계약을 만들기 위해 형식 DataContractAttribute 과 DataMemberAttribute 특성을 표시하는 것이 좋습니다.
데이터 계약은 옵트인 스타일 계약입니다. 데이터 계약 특성을 명시적으로 적용하지 않는 한 형식 또는 데이터 멤버가 직렬화되지 않습니다. 데이터 계약은 관리 코드의 액세스 범위와 관련이 없습니다. 프라이빗 데이터 멤버를 직렬화하고 다른 곳으로 보내 공개적으로 액세스할 수 있습니다. (데이터 계약의 기본 예제는 방법: 클래스 또는 구조체에 대한 기본 데이터 계약 만들기를 참조하세요.) WCF는 작업의 기능을 활성화하는 기본 SOAP 메시지의 정의와 메시지 본문 내부 및 외부의 데이터 형식 직렬화를 처리합니다. 데이터 형식을 직렬화할 수 있는 한 작업을 디자인할 때 기본 메시지 교환 인프라에 대해 생각할 필요가 없습니다.
일반적인 WCF 애플리케이션은 DataContractAttribute 및 DataMemberAttribute 특성을 사용하여 작업에 대한 데이터 계약을 만들지만, 다른 직렬화 메커니즘을 사용할 수도 있습니다. 표준 ISerializable및 SerializableAttributeIXmlSerializable 메커니즘은 모두 데이터 형식의 직렬화를 한 애플리케이션에서 다른 애플리케이션으로 전송하는 기본 SOAP 메시지로 처리하는 데 작동합니다. 데이터 형식에 특별한 지원이 필요한 경우 더 많은 serialization 전략을 사용할 수 있습니다. WCF 애플리케이션에서 데이터 형식을 serialization하기 위한 선택에 대한 자세한 내용은 서비스 계약에서 데이터 전송 지정을 참조하세요.
매개 변수 및 반환 값을 메시지 교환에 매핑
서비스 작업은 애플리케이션에서 특정 표준 보안, 트랜잭션 및 세션 관련 기능을 지원하는 데 필요한 데이터 외에도 애플리케이션 데이터를 앞뒤로 전송하는 SOAP 메시지의 기본 교환에서 지원됩니다. 이 경우 서비스 작업의 서명은 데이터 전송 및 작업에 필요한 기능을 지원할 수 있는 특정 기본 MEP( 메시지 교환 패턴 )를 지정합니다. WCF 프로그래밍 모델에서 요청/회신, 단방향 및 이중 메시지 패턴의 세 가지 패턴을 지정할 수 있습니다.
요청/회신
요청/회신 패턴은 요청 보낸 사람(클라이언트 애플리케이션)이 요청의 상관 관계가 있는 회신을 수신하는 패턴입니다. 하나 이상의 매개 변수가 작업에 전달되고 반환 값이 호출자에게 다시 전달되는 작업을 지원하기 때문에 기본 MEP입니다. 예를 들어 다음 C# 코드 예제에서는 하나의 문자열을 사용하고 문자열을 반환하는 기본 서비스 작업을 보여 있습니다.
[OperationContractAttribute]
string Hello(string greeting);
다음은 동일한 Visual Basic 코드입니다.
<OperationContractAttribute()>
Function Hello (ByVal greeting As String) As String
이 작업 서명은 기본 메시지 교환 형식을 지정합니다. 상관 관계가 없는 경우 WCF는 반환 값이 의도된 작업을 확인할 수 없습니다.
다른 기본 메시지 패턴을 지정하지 않는 한, void
을(를) 반환하는 서비스 작업도 요청/응답 메시지 교환입니다 (Nothing
는 Visual Basic에서). 작업의 결과는 클라이언트가 비동기적으로 작업을 호출하지 않는 한, 일반적인 경우 해당 메시지가 비어 있더라도 반환 메시지가 수신될 때까지 클라이언트가 처리를 중지한다는 것입니다. 다음 C# 코드 예제에서는 클라이언트가 응답에서 빈 메시지를 받을 때까지 반환되지 않는 작업을 보여 있습니다.
[OperationContractAttribute]
void Hello(string greeting);
다음은 동일한 Visual Basic 코드입니다.
<OperationContractAttribute()>
Sub Hello (ByVal greeting As String)
위의 예제에서는 작업을 수행하는 데 시간이 오래 걸리는 경우 클라이언트 성능 및 응답성을 저하할 수 있지만, 반환 void
하는 경우에도 요청/회신 작업에는 장점이 있습니다. 가장 확실한 것은 응답 메시지에서 SOAP 오류를 반환할 수 있다는 것입니다. 이는 통신 또는 처리 중 일부 서비스 관련 오류 조건이 발생했음을 나타냅니다. 서비스 계약에 지정된 SOAP 오류는 개체로 FaultException<TDetail> 클라이언트 애플리케이션에 전달됩니다. 여기서 형식 매개 변수는 서비스 계약에 지정된 형식입니다. 이렇게 하면 WCF 서비스의 오류 조건에 대해 클라이언트에 쉽게 알릴 수 있습니다. 예외, SOAP 오류 및 오류 처리에 대한 자세한 내용은 계약 및 서비스에서 오류 지정 및 처리를 참조하세요. 요청/회신 서비스 및 클라이언트의 예를 보려면 방법: Request-Reply 계약 만들기를 참조하세요. 요청-회신 패턴의 문제에 대한 자세한 내용은 Request-Reply Services를 참조하세요.
단방향
WCF 서비스 애플리케이션의 클라이언트가 작업이 완료되기를 기다리지 않고 SOAP 오류를 처리하지 않는 경우 작업은 단방향 메시지 패턴을 지정할 수 있습니다. 단방향 작업은 WCF가 네트워크에 메시지를 쓴 후 클라이언트가 작업을 호출하고 처리를 계속하는 작업입니다. 일반적으로 이는 아웃바운드 메시지에서 전송되는 데이터가 매우 크지 않으면 클라이언트가 거의 즉시 계속 실행된다는 것을 의미합니다(데이터를 보내는 동안 오류가 발생하지 않는 한). 이 유형의 메시지 교환 패턴은 클라이언트에서 서비스 애플리케이션으로 이벤트와 유사한 동작을 지원합니다.
하나의 메시지가 전송되고 아무런 메시지도 수신되지 않는 메시지 교환은 반환 값이 void
이 아닌 것으로 지정된 서비스 작업을 지원할 수 없습니다. 이 경우 InvalidOperationException 예외가 발생합니다.
반환 메시지가 없다는 것은 처리 또는 통신 오류를 나타내기 위한 SOAP 오류가 반환되지 않을 것임을 의미합니다. (작업이 단방향 작업일 때 오류 정보를 전달하려면 이중 메시지 교환 패턴이 필요합니다.)
반환void
하는 작업에 대한 단방향 메시지 교환을 지정하려면 다음 C# 코드 예제와 같이 속성을 IsOneWay로 설정합니다true
.
[OperationContractAttribute(IsOneWay=true)]
void Hello(string greeting);
다음은 동일한 Visual Basic 코드입니다.
<OperationContractAttribute(IsOneWay := True)>
Sub Hello (ByVal greeting As String)
이 메서드는 앞의 요청/회신 예제와 동일합니다. 그러나 IsOneWay 속성을 true
로 설정하면 메서드는 동일하지만 서비스 작업이 반환 메시지를 보내지 않고, 아웃바운드 메시지가 채널 계층에 전달되었을 때 클라이언트가 즉시 응답하지 않고 반환됩니다. 예제는 방법: One-Way 계약 만들기를 참조하세요. 단방향 패턴에 대한 자세한 내용은 One-Way Services를 참조하세요.
이중
이중 패턴은 단방향 또는 요청/회신 메시징을 사용하든 관계없이 서비스와 클라이언트가 독립적으로 서로 메시지를 보낼 수 있는 기능을 특징으로 합니다. 이 형태의 양방향 통신은 클라이언트와 직접 통신해야 하는 서비스 또는 이벤트와 유사한 동작을 포함하여 메시지 교환의 양쪽에 비동기 환경을 제공하는 데 유용합니다.
이중 패턴은 클라이언트와 통신하기 위한 추가 메커니즘으로 인해 요청/회신 또는 단방향 패턴보다 약간 더 복잡합니다.
듀플렉스 계약을 설계하려면, 콜백 계약을 먼저 설계하고 해당 콜백 계약의 형식을 서비스 계약을 표시하는 CallbackContract 특성의 ServiceContractAttribute 속성에 할당해야 합니다.
이중 패턴을 구현하려면 클라이언트에서 호출되는 메서드 선언을 포함하는 두 번째 인터페이스를 만들어야 합니다.
서비스 및 해당 서비스에 액세스하는 클라이언트를 만드는 예제는 방법: 이중 계약 만들기 및 방법: 이중 계약을 사용하여 서비스에 액세스하는 방법을 참조하세요. 작업 샘플은 Duplex를 참조하세요. 이중 계약을 사용하는 문제에 대한 자세한 내용은 Duplex Services를 참조하세요.
주의
서비스가 이중 메시지를 받으면 들어오는 메시지의 ReplyTo
요소를 확인하여 회신을 보낼 위치를 결정합니다. 메시지를 받는 데 사용되는 채널이 보호되지 않으면 신뢰할 수 없는 클라이언트가 대상 컴퓨터와 함께 악의적인 메시지를 보내 해당 대상 컴퓨터의 ReplyTo
DOS(서비스 거부)로 이어질 수 있습니다.
Out 및 Ref 매개 변수
대부분의 경우 in
매개 변수(ByVal
Visual Basic)와 out
및 ref
매개 변수(ByRef
Visual Basic)를 사용할 수 있습니다. 두 매개 변수 모두 out
ref
데이터가 작업에서 반환됨을 나타내므로 다음과 같은 작업 서명은 작업 서명이 반환 void
되더라도 요청/회신 작업이 필요함을 지정합니다.
[ServiceContractAttribute]
public interface IMyContract
{
[OperationContractAttribute]
public void PopulateData(ref CustomDataType data);
}
다음은 동일한 Visual Basic 코드입니다.
<ServiceContractAttribute()> _
Public Interface IMyContract
<OperationContractAttribute()> _
Public Sub PopulateData(ByRef data As CustomDataType)
End Interface
유일한 예외는 서명에 특정 구조가 있는 경우입니다. 예를 들어 바인딩을 NetMsmqBinding 사용하여 작업 반환을 선언하는 데 사용되는 메서드가 반환void
되는 경우에만 클라이언트와 통신할 수 있습니다. 반환 값이든 매개 변수이든 출력 값 ref
out
이 없을 수 있습니다.
또한 out
또는 ref
매개 변수를 사용하려면, 작업에 수정된 객체를 다시 전달할 수 있는 기본 응답 메시지가 있어야 합니다. 작업이 단방향 작업인 경우 런타임에 InvalidOperationException 예외가 throw됩니다.
계약에 메시지 보호 수준 지정
계약을 디자인할 때 계약을 구현하는 서비스의 메시지 보호 수준도 결정해야 합니다. 이는 메시지 보안이 계약 엔드포인트의 바인딩에 적용되는 경우에만 필요합니다. 바인딩에서 보안이 꺼져 있는 경우(즉, 시스템 제공 바인딩이 System.ServiceModel.SecurityMode을 SecurityMode.None로 설정한 경우) 계약에 대한 메시지 보호 수준을 결정할 필요가 없습니다. 대부분의 경우 메시지 수준 보안이 적용된 시스템 제공 바인딩은 충분한 보호 수준을 제공하므로 각 작업 또는 각 메시지에 대한 보호 수준을 고려할 필요가 없습니다.
보호 수준은 서비스를 지원하는 메시지(또는 메시지 부분)가 서명, 서명 및 암호화 또는 서명 또는 암호화 없이 전송되는지 여부를 지정하는 값입니다. 보호 수준은 서비스 수준, 특정 작업, 해당 작업 내의 메시지 또는 메시지 파트 등 다양한 범위에서 설정할 수 있습니다. 명시적으로 재정의하지 않는 한 한 범위에서 설정된 값은 더 작은 범위의 기본값이 됩니다. 바인딩 구성이 계약에 필요한 최소 보호 수준을 제공할 수 없는 경우 예외가 throw됩니다. 또한 계약에 명시적으로 설정된 보호 수준 값이 없는 경우 바인딩 구성은 바인딩에 메시지 보안이 있는 경우 모든 메시지에 대한 보호 수준을 제어합니다. 이 옵션은 기본 동작입니다.
중요합니다
계약의 다양한 범위를 전체 보호 수준 ProtectionLevel.EncryptAndSign 보다 작게 명시적으로 설정할지 여부를 결정하는 것은 일반적으로 성능 향상을 위해 어느 정도의 보안을 거래하는 결정입니다. 이러한 경우 의사 결정은 작업 및 교환하는 데이터의 가치를 중심으로 결정해야 합니다. 자세한 내용은 서비스 보안을 참조하세요.
예를 들어, 다음 코드 예제에서는 계약에서 ProtectionLevel나 ProtectionLevel 속성을 설정하지 않습니다.
[ServiceContract]
public interface ISampleService
{
[OperationContractAttribute]
public string GetString();
[OperationContractAttribute]
public int GetInt();
}
다음은 동일한 Visual Basic 코드입니다.
<ServiceContractAttribute()> _
Public Interface ISampleService
<OperationContractAttribute()> _
Public Function GetString()As String
<OperationContractAttribute()> _
Public Function GetData() As Integer
End Interface
기본 ISampleService
(기본 WSHttpBinding, 즉 System.ServiceModel.SecurityMode)과 함께 엔드포인트의 Message 구현과 상호 작용할 때, 이는 기본 보호 수준이므로 모든 메시지가 암호화되고 서명됩니다. 그러나 서비스가 기본값(기본값 ISampleService
BasicHttpBinding, 즉SecurityMode)과 함께 사용되는 경우 None 이 바인딩에 대한 보안이 없으므로 모든 메시지가 텍스트로 전송되므로 보호 수준이 무시됩니다(즉, 메시지는 암호화되거나 서명되지 않음).
SecurityMode 변경Message된 경우 이러한 메시지는 암호화되고 서명됩니다(이제 바인딩의 기본 보호 수준이 되기 때문).
계약에 대한 보호 요구 사항을 명시적으로 지정하거나 조정하려면, ProtectionLevel 속성을 설정하거나 더 작은 범위의 ProtectionLevel
속성을 서비스 계약에 필요한 수준으로 설정하십시오. 이 경우 명시적 설정을 사용하려면 바인딩이 사용된 범위에 대해 최소한 해당 설정을 지원해야 합니다. 예를 들어, 다음 코드 예제는 ProtectionLevel 작업에 대해 GetGuid
값을 하나 명시적으로 지정합니다.
[ServiceContract]
public interface IExplicitProtectionLevelSampleService
{
[OperationContractAttribute]
public string GetString();
[OperationContractAttribute(ProtectionLevel=ProtectionLevel.None)]
public int GetInt();
[OperationContractAttribute(ProtectionLevel=ProtectionLevel.EncryptAndSign)]
public int GetGuid();
}
다음은 동일한 Visual Basic 코드입니다.
<ServiceContract()> _
Public Interface IExplicitProtectionLevelSampleService
<OperationContract()> _
Public Function GetString() As String
End Function
<OperationContract(ProtectionLevel := ProtectionLevel.None)> _
Public Function GetInt() As Integer
End Function
<OperationContractAttribute(ProtectionLevel := ProtectionLevel.EncryptAndSign)> _
Public Function GetGuid() As Integer
End Function
End Interface
이 IExplicitProtectionLevelSampleService
계약을 구현하고 기본값(기본WSHttpBinding값 System.ServiceModel.SecurityMode , 즉Message)을 사용하는 엔드포인트가 있는 서비스에는 다음과 같은 동작이 있습니다.
GetString
작업 메시지는 암호화되고 서명됩니다.GetInt
작업 메시지는 암호화되지 않고 서명되지 않은(즉, 일반) 텍스트로 전송됩니다.작업은
GetGuid
System.Guid 암호화되고 서명된 메시지에 반환됩니다.
보호 수준 및 사용 방법에 대한 자세한 내용은 보호 수준 이해를 참조하세요. 보안에 대한 자세한 내용은 보안 서비스를 참조하세요.
기타 작업 서명 요구 사항
일부 애플리케이션 기능에는 특정 종류의 작업 서명이 필요합니다. 예를 들어 NetMsmqBinding 바인딩은 지속성 서비스를 지원하는 클라이언트를 포함하여, 애플리케이션이 통신 중간에 다시 시작해도 메시지를 놓치지 않고 이전 위치에서 다시 시작할 수 있습니다. (자세한 내용은 WCF의 큐를 참조하세요.) 그러나 지속성 작업은 매개 변수를 하나 in
만 사용하고 반환 값이 없어야 합니다.
또 다른 예는 작업에서 형식을 Stream 사용하는 것입니다. 매개 변수는 Stream 전체 메시지 본문을 포함하므로 입력 또는 출력(즉, 매개 변수, ref
out
매개 변수 또는 반환 값)이 형식 Stream인 경우 작업에 지정된 유일한 입력 또는 출력이어야 합니다. 또한 매개 변수 또는 반환 형식은 Stream, System.ServiceModel.Channels.Message, 또는 System.Xml.Serialization.IXmlSerializable 중 하나여야 합니다. 스트림에 대한 자세한 내용은 큰 데이터 및 스트리밍을 참조하세요.
이름, 네임스페이스 및 난독 처리
계약 및 작업 정의에서 .NET 형식의 이름과 네임스페이스는 계약이 WSDL로 변환되고 계약 메시지가 만들어지고 전송될 때 중요합니다. 따라서 서비스 계약 이름 및 네임스페이스는 Name
, Namespace
, ServiceContractAttribute, OperationContractAttribute 및 기타 계약 특성과 같은 모든 지원 계약 특성의 DataContractAttribute 및 DataMemberAttribute 속성을 사용하여 명시적으로 설정하는 것이 강력히 권장됩니다.
그 결과 이름 및 네임스페이스가 명시적으로 설정되지 않은 경우 어셈블리에서 IL 난독화를 사용하면 계약 형식 이름과 네임스페이스가 변경되며, 이로 인해 일반적으로 실패하게 되는 WSDL 및 데이터 교환이 수정됩니다. 계약 이름 및 네임스페이스를 명시적으로 설정하지 않고 난독화를 사용하려는 경우 해당 및 ObfuscationAttribute 특성을 사용하여 ObfuscateAssemblyAttribute 계약 형식 이름 및 네임스페이스를 수정하지 않도록 합니다.