본문 바로가기
프로그래밍

WCF(Windows Communication Foundation) 서비스 개발[1]

by minimax95 2020. 5. 14.

이전 포스팅에서 WCF의 기본 개념과 핵심 키워드, 계약 선언 부분을 살펴보았습니다.

이번 포스팅에서는 실제 WCF 계약 선언과 서비스 타입 구현부를 어떻게 호스팅 프로세스에서 사용하는지 살펴보겠습니다.

 

먼저 서비스 계약 부분은 아래와 같이 선언했습니다.

// 서비스 계약 선언

[ServiceContract]

public interface IHelloWorld

{

    [OperationContract]

    string SayHello{};

}

 

그리고 서비스 계약을 구현하는 클래스에서 아래와 같이 인터페이스를 상속받아 서비스 계약을 구현하였습니다.

 

// 서비스 타입 구현

public class HelloWorldWCFService : IHelloWorld

{

    public string SayHello{}

    {

        return “Hello WCF World”;

    }

}

 

이제 실제로 위에서 정의한 서비스 타입을 이용하는 WCF 서비스 호스트를 구현해 보겠습니다.

여기서부터는 이전 포스팅에서 핵심 개념으로 설명했던 주소와 바인딩이 사용됩니다.

 

먼저 WCF 서비스 호스트 구현에 대해서 살펴보겠습니다.

WCF 서비스 라이브러리를 참조하기 위해서 System.ServiceModel 어셈블리를 프로젝트에 참조시켜 줍니다.

HelloWorld 서비스를 구현해 놓은 HelloWorldService 라이브러리도 참조로 추가시켜 줍니다.

 

서비스 호스트는 ServiceModel 네임스페이스의 ServiceHost 클래스를 직접 사용하거나 이 클래스에서 파생된 클래스를 사용할 수 있습니다.

아래 소스코드가 기본 형태입니다.

public class ServiceHost : ServiceHostBase

{

    public ServiceHost(Type serviceType, params Uri[ ] baseAddress);

}

서비스 호스트는 자신이 호스트 할 WCF 서비스의 서비스 타입을 첫 번째 매개변수로 취하며, 두 번째 매개변수는 서비스가 사용할 주소의 베이스 주소입니다.

ServiceHost의 세부 정의는 메타데이터 이미지를 참조해주세요.

 

WCF 서비스는 서비스의 주소, 바인딩, 계약으로 구성된 서비스 종점을 1개 이상 노출해야 합니다.

이 서비스의 종점을 통해 클라이언트와 통신을 할 수 있게 되는 것이지요.

그럼 실제 소스 코드상에서 살펴보겠습니다.

 

static void Main(string [] args)

{

    // ServiceHost 클래스의 인스턴스 생성

    ServiceHost host = new ServiceHost(typeof(HelloWorldWCFService),                         // 앞서 구현한 서비스 타입

                                                    new Uri(“http://localhost/wcf/helloworldsevice”));  // 베이스 주소

 

    // 서비스의 종점을 서비스 호스트 인스턴스에 추가

    host.AddServiceEndpoint(

        typeof(IHelloworld), // 서비스 계약

        new BasicHttpBinding[], // 서비스에서 사용될 바인딩

        “ “);  // 종점에 주소 추가 가능(여기서는 생략함)

 

    host.Open();   // host 서비스 시작

    Console.WriteLine(“Press Any key to step the service”);

    Console.ReadKey(true);

    host.Close();

}

* 참고 : BasicHttpBinding은 HTTP 프로토콜을 사용하는 바인딩으로서 기존 ASP.NET 웹 서비스와의 호환성을 위해

           WCF가 기본적으로 제공하는 바인딩입니다. 바인딩의 종류에 따라 사용되는 URI 서비스 주소가 달라집니다.

 

서비스의 종점이 추가되면 실제로 클라이언트의 호출을 받을 준비가 끝난 것이고

ServiceHost 클래스의 Open 메서드를 호출함으로써 서비스 호스트는 리스너를 구동하고 클라이언트의 호출을 수신하기 시작합니다.

구동된 서비스는 ServiceHost 클래스의 Close 메소드 호출에 의해 종료되며 위 소스코드에서는 사용자가 키를 누르면 종료하도록 구현되어 있습니다.

 

다음으로는 WCF 서비스 클라이언트 구현입니다. 

마찬가지로  WCF 런타임을 위한  System.ServiceModel 어셈블리 참조시켜 줍니다.

HelloWorld 서비스를 구현해 놓은 HelloWorldService 라이브러리도 참조로 추가시켜 줍니다.

 

System.ServiceModel.Description 네임스페이스의 ServiceEndpoint 클래스는 서비스의 종점을 기술하는 데 사용되는 클래스로 서비스의 종점을 기술하는 계약, 바인딩, 주소를 모두 포함하는 정보를 가지고 있습니다.

아래의 소스코드를 통해 사용 방법을 살펴보겠습니다.

 

Uri uri = new Uri(“http://localhost/wcf/helloworldservice”);

ServiceEndpoint ep = new ServiceEndpoint(

                                       ContractDescription.GetContract(typeof(IHelloWorld)),

                                       new BasicHttpBinding(),

                                       new EndpointAddress(uri));

 

서비스에 대한 종점을 나타내는 ServiceEndpoint 객체를 구성했으면 다음은 WCF의 채널 팩토리를 생성해야 합니다.

ChannelFactory<T> 클래스는 서비스의 계약 인터페이스를 타입 매개변수로 취하여 WCF의 내부 채널들을 구성하고 이 채널들을 대표하는 프록시 객체를 생성하여 반환해 주는 역할 수행해 줍니다.

소스코드를 다시 살펴보면 아래와 같습니다. 

ChannelFactory<IHelloWorld> factoty = new ChannelFactory<IHelloWorld>(ep);

IHelloWorld proxy = factory.CreatChannel();

// 서비스 계약 인터페이스를 이용해 서비스 호출 가능

string result = proxy.SayHello( );

 

// 이후 서비스 자원 해제를 위해  Dispose 호출

(proxy as IDisposable).Dispose();

Console.WriteLine(result);

 

프록시 객체는 WCF 서비스 세션과도 연관이 깊어, 프록시 객체를 닫거나 해제하는 작업은 매우 중요합니다.

위에서 보는 바와 같이 실제 호출은 proxy 객체를 통해서 서비스에서 제공하는 함수를 호출할 수 있습니다.

실제 호출 시 콘솔에 아래와 같이 출력되겠지요.

 

 “Hello WCF World”;

 

WCF 서비스 클라이언트 최종 소스코드는 아래와 같습니다.

static void Main(string [] args)

{

    Uri uri = new Uri(“http://localhost/wcf/helloworldservice”);

    ServiceEndpoint ep = new ServiceEndpoint(

                                       ContractDescription.GetContract(typeof(IHelloWorld)),

                                       new BasicHttpBinding(),

                                       new EndpointAddress(uri));

 

    ChannelFactory<IHelloWorld> factoty = new ChannelFactory<IHelloWorld>(ep);

    IHelloWorld proxy = factory.CreatChannel();

    // 서비스 계약 인터페이스를 이용해 서비스 호출 가능

    string result = proxy.SayHello( );

 

    // 이후 서비스 자원 해제를 위해  Dispose 호출

    (proxy as IDisposable).Dispose();

    Console.WriteLine(result);

}

 

감사합니다.

 

댓글