다음을 통해 공유


엔드포인트 주소 지정

WCF(Windows Communication Foundation) 서비스와의 모든 통신은 서비스의 해당 엔드포인트를 통해 이루어집니다. 각 ServiceEndpoint에는 Address, BindingContract가 포함되어 있습니다. 계약은 사용할 수 있는 작업을 지정합니다. 바인딩은 서비스와 통신하는 방법을 지정하고 주소는 서비스를 찾을 위치를 지정합니다. 모든 엔드포인트에는 고유한 주소가 있어야 합니다. 엔드포인트 주소는 서비스 주소를 표시하는 URI(Uniform Resource Identifier)가 포함된 EndpointAddress 클래스, 서비스의 보안 ID를 표시하는 Identity 및 선택적 Headers의 컬렉션에 의해 표시됩니다. 선택적 헤더는 엔드포인트를 확인하거나 상호 작용하는 데 필요한 자세한 주소 지정 정보를 제공합니다. 예를 들어 헤더는 들어오는 메시지를 처리하는 방법, 엔드포인트가 회신 메시지를 보내야 하는 위치 또는 여러 인스턴스를 사용할 수 있는 경우 특정 사용자의 들어오는 메시지를 처리하는 데 사용할 서비스 인스턴스를 나타낼 수 있습니다.

엔드포인트 주소 정의

WCF에서 EndpointAddress는 WS-Addressing 표준에 정의된 EPR(엔드포인트 참조)을 모델링합니다.

대부분 전송 주소 URI에는 네 가지 부분이 있습니다. 예를 들어 이 URI http://www.fabrikam.com:322/mathservice.svc/secureEndpoint에는 다음과 같은 네 부분이 있습니다.

  • 스키마: http:

  • 컴퓨터: www.fabrikam.com

  • (선택적) 포트: 322

  • 경로: /mathservice.svc/secureEndpoint

EPR 모델 일부에서는 각 엔드포인트 참조에 추가 식별 정보를 추가하는 일부 참조 매개 변수를 포함할 수 있습니다. WCF에서 이러한 참조 매개 변수는 AddressHeader 클래스의 인스턴스로 모델링됩니다.

서비스의 엔드포인트 주소는 코드를 사용하여 명령적으로 지정하거나 구성을 통해 선언적으로 지정할 수 있습니다. 배포된 서비스의 바인딩과 주소는 일반적으로 서비스를 개발할 때 사용되는 바인딩 및 주소와는 다르기 때문에 코드에서 엔드포인트를 정의하는 방식은 대개 실용적이지 않습니다. 일반적으로 코드 대신 구성을 사용하여 서비스 엔드포인트를 정의하는 것이 좋습니다. 바인딩 및 주소 지정 정보를 코드와 구분하면 애플리케이션을 다시 컴파일하여 재배포할 필요 없이 해당 정보를 변경할 수 있습니다. 코드 또는 구성에서 엔드포인트를 지정하지 않으면 런타임이 서비스에서 구현되는 각 계약의 각 기본 주소에 대해 기본 엔드포인트를 하나씩 추가합니다.

WCF에서 서비스의 대한 엔드포인트 주소를 지정하기 위한 두 가지 방법이 있습니다. 서비스와 연결된 각 엔드포인트에 대한 절대 주소를 지정하거나 서비스의 ServiceHost에 대한 기본 주소를 제공할 수 있으며 그런 다음 이 기본 주소를 기준으로 정의된 이 서비스와 연결된 각 엔드포인트에 대한 주소를 지정할 수 있습니다. 이러한 각 절차를 사용하여 구성 또는 코드에서 서비스에 대한 엔드포인트 주소를 지정할 수 있습니다. 상대 주소를 지정하지 않을 경우 서비스는 기본 주소를 사용합니다. 또한 하나의 서비스에 대해 여러 기본 주소를 사용할 수 있지만 각 서비스는 각 전송에 대해 하나의 기본 주소만 허용됩니다. 여러 엔드포인트를 가진 경우 각 엔드포인트는 서로 다른 바인딩으로 구성되며 해당 주소가 고유해야 합니다. 동일한 바인딩을 사용하지만 서로 다른 계약을 사용하는 엔드포인트는 동일한 주소를 사용할 수 있습니다.

IIS를 사용하여 호스팅하는 경우 사용자는 ServiceHost 인스턴스를 직접 관리하지 않습니다. IIS에서 호스팅하는 경우 기본 주소는 항상 서비스의 .svc 파일에 지정된 주소입니다. 따라서 IIS에서 호스팅되는 서비스 엔드포인트에는 상대 엔드포인트 주소를 사용해야 합니다. 정규화된 엔드포인트 주소를 제공할 경우 서비스 배포 시 오류가 발생할 수 있습니다. 자세한 내용은 인터넷 정보 서비스 호스팅 WCF 서비스 배포를 참조하세요.

구성에서 엔드포인트 주소 정의

구성 파일에 엔드포인트를 정의하려면 <엔드포인트> 요소를 사용합니다.

<configuration>
  <system.serviceModel>
    <services>
      <service name="UE.Samples.HelloService"
               behaviorConfiguration="HelloServiceBehavior">
        <endpoint address="/Address1"
                  binding="basicHttpBinding" 
                  contract="UE.Samples.IHello"/>

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="HelloServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Open 메서드를 호출하는 경우(즉, 호스팅 응용 프로그램이 서비스를 시작하려고 시도하는 경우) 시스템은 "UE.Samples.HelloService"를 지정하는 이름 특성을 가진 <서비스> 요소를 검색합니다. <서비스> 요소를 찾은 경우 시스템은 지정된 클래스를 로드하고 구성 파일에서 제공된 엔드포인트 정의를 사용하여 엔드포인트를 만듭니다. 이 메커니즘을 통해 두 개의 코드 줄에서 서비스를 로드하고 시작하는 동시에 해당 코드의 바인딩 및 주소 지정 정보를 유지할 수 있습니다. 이 접근 방식의 이점은 애플리케이션을 다시 컴파일하거나 다시 배포할 필요 없이 이러한 변경 작업을 수행할 수 있다는 점입니다.

선택적 헤더는 <헤더>에서 선언됩니다. 다음은 두 가지 헤더(http://tempuri1.org/의 "Gold" 클라이언트 및 http://tempuri2.org/의 "Standard" 클라이언트)를 구별하는 구성 파일에서 서비스의 엔드포인트를 지정하는 데 사용되는 요소의 예제입니다. 이 서비스를 호출하는 클라이언트의 구성 파일에는 적절한 <헤더>가 있어야 합니다.

<configuration>
  <system.serviceModel>
    <services>
      <service name="UE.Samples.HelloService"
               behaviorConfiguration="HelloServiceBehavior">
        <endpoint address="/Address1"
                  binding="basicHttpBinding" 
                  contract="UE.Samples.IHello">
          <headers>
            <Member xmlns="http://tempuri1.org/">Gold</Member>
          </headers>
        </endpoint>
        <endpoint address="/Address2"
          binding="basicHttpBinding" 
          contract="UE.Samples.IHello">
          <headers>
            <Member xmlns="http://tempuri2.org/">Silver</Member>
          </headers>
        </endpoint>

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="HelloServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

또한 헤더는 이전에 설명한 것처럼 엔드포인트의 모든 메시지 대신 개별 메시지에서 설정될 수 있습니다. 이 작업은 다음 예제에서처럼 보내는 메시지에 사용자 지정 헤더를 추가하기 위해 OperationContextScope를 사용하여 클라이언트 애플리케이션에서 새 컨텍스트를 만들어 수행합니다.

SampleServiceClient wcfClient = new SampleServiceClient(new InstanceContext(this));
try
{
  using (OperationContextScope scope = new OperationContextScope(wcfClient.InnerChannel))
  {
    MessageHeader header
      = MessageHeader.CreateHeader(
      "Service-Bound-CustomHeader",
      "http://Microsoft.WCF.Documentation",
      "Custom Happy Value."
      );
    OperationContext.Current.OutgoingMessageHeaders.Add(header);

    // Making calls.
    Console.WriteLine("Enter the greeting to send: ");
    string greeting = Console.ReadLine();

    //Console.ReadLine();
    header = MessageHeader.CreateHeader(
        "Service-Bound-OneWayHeader",
        "http://Microsoft.WCF.Documentation",
        "Different Happy Value."
      );
    OperationContext.Current.OutgoingMessageHeaders.Add(header);

    // One-way
    wcfClient.Push(greeting);
    this.wait.WaitOne();

    // Done with service.
    wcfClient.Close();
    Console.WriteLine("Done!");
    Console.ReadLine();
  }
}
catch (TimeoutException timeProblem)
{
  Console.WriteLine("The service operation timed out. " + timeProblem.Message);
  Console.ReadLine();
  wcfClient.Abort();
}
catch (CommunicationException commProblem)
{
  Console.WriteLine("There was a communication problem. " + commProblem.Message);
  Console.ReadLine();
  wcfClient.Abort();
}
Dim wcfClient As New SampleServiceClient(New InstanceContext(Me))
Try
    Using scope As New OperationContextScope(wcfClient.InnerChannel)
        Dim header As MessageHeader = MessageHeader.CreateHeader("Service-Bound-CustomHeader", _
                            "http://Microsoft.WCF.Documentation", "Custom Happy Value.")
        OperationContext.Current.OutgoingMessageHeaders.Add(header)

        ' Making calls.
        Console.WriteLine("Enter the greeting to send: ")
        Dim greeting As String = Console.ReadLine()

        'Console.ReadLine();
        header = MessageHeader.CreateHeader("Service-Bound-OneWayHeader", _
                                            "http://Microsoft.WCF.Documentation", "Different Happy Value.")
        OperationContext.Current.OutgoingMessageHeaders.Add(header)

        ' One-way
        wcfClient.Push(greeting)
        Me.wait.WaitOne()

        ' Done with service. 
        wcfClient.Close()
        Console.WriteLine("Done!")
        Console.ReadLine()
    End Using
Catch timeProblem As TimeoutException
    Console.WriteLine("The service operation timed out. " & timeProblem.Message)
    Console.ReadLine()
    wcfClient.Abort()
Catch commProblem As CommunicationException
    Console.WriteLine("There was a communication problem. " & commProblem.Message)
    Console.ReadLine()
    wcfClient.Abort()
End Try

메타데이터의 엔드포인트 주소

엔드포인트 주소는 해당 엔드포인트의 EndpointReference 요소 내에서 WS-Addressing wsdl:port(EPR) 요소로서 WSDL(웹 서비스 기술 언어)로 표시됩니다. EPR에는 엔드포인트 주소와 주소 속성이 포함되어 있습니다. wsdl:port 내의 EPR은 다음 예제에 표시된 것처럼 soap:Address로 바뀝니다.

코드에서 엔드포인트 주소 정의

엔드포인트 주소는 EndpointAddress 클래스를 사용하여 코드에 만들 수 있습니다. 엔드포인트 주소에 대해 지정된 URI는 정규화된 경로 또는 서비스 기본 주소에 상대적인 경로일 수 있습니다. 다음 코드에서는 EndpointAddress 클래스의 인스턴스를 만들어 서비스를 호스팅하는 ServiceHost 인스턴스에 추가하는 방법을 보여 줍니다.

다음 예제에서는 전체 엔드포인트 주소를 코드에서 지정하는 방법을 보여 줍니다.

Uri baseAddress = new Uri("http://localhost:8000/HelloService");
string address = "http://localhost:8000/HelloService/MyService";

using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
    serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), address);
    serviceHost.Open();
    Console.WriteLine("Press <enter> to terminate service");
    Console.ReadLine();
    serviceHost.Close();
}

다음 예제에서는 상대 주소("MyService")를 서비스 호스트의 기본 주소에 추가하는 방법을 보여 줍니다.

Uri baseAddress = new Uri("http://localhost:8000/HelloService");

using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService), baseAddress))
{
    serviceHost.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(), "MyService");
    serviceHost.Open();
    Console.WriteLine("Press <enter> to terminate service");
    Console.ReadLine();
    serviceHost.Close();
}

참고 항목

ServiceDescriptionOnOpening 메서드 다음에 나오는 서비스 애플리케이션의 ServiceHostBase 속성은 수정하면 안 됩니다. CredentialsAddServiceEndpoint에서 ServiceHostBase 속성과 ServiceHost 메서드와 같은 일부 멤버는 해당 지점을 지나서 수정할 경우 예외를 throw합니다. 다른 멤버에서는 이를 수정할 수 있지만 그 결과는 예측할 수 없습니다.

마찬가지로 클라이언트에서 ServiceEndpointOnOpening을 호출한 이후에는 ChannelFactory 값을 수정해서는 안 됩니다. Credentials 속성은 해당 지점을 지나서 수정할 경우 예외를 throw합니다. 다른 클라이언트 설명 값은 수정해도 오류가 발생하지 않지만 결과가 정의되어 있지 않습니다.

서비스와 클라이언트 모두에 대해 Open을 호출하기 이전에 설명을 수정하는 것이 좋습니다.

기본 엔드포인트 사용

코드 또는 구성에서 엔드포인트를 지정하지 않으면 런타임이 서비스에서 구현되는 각 서비스 계약의 각 기본 주소에 대해 기본 엔드포인트를 하나씩 추가하여 기본 엔드포인트를 제공합니다. 기본 주소는 코드 또는 구성에서 지정할 수 있으며 기본 엔드포인트는 Open에서 ServiceHost을 호출하면 추가됩니다.

엔드포인트를 명시적으로 제공하는 경우에도 AddDefaultEndpoints을 호출하기 전에 ServiceHost에서 Open를 호출하여 기본 엔드포인트를 추가할 수 있습니다. 기본 엔드포인트, 바인딩 및 동작에 대한 자세한 내용은 단순화된 구성WCF 서비스를 위한 단순화된 구성을 참조하세요.

참고 항목