IIS에 WCF 서비스 호스팅하기
지금까지 WCF의 가장 기본적인 개념들인 서비스 종점, 계약, 주소, 바인딩, 호스트, 채널, 클라이언트 프록시 등을 살펴보았다. 또한 관련된 예제 코드들 역시 WCF의 기본적인 사항들을 이해할 수 있을 정도로 충분히 살펴보았다. 이 정도만 알고 있다면 WCF에 관련된 기본적인 프로그래밍 기초는 닦았다고 할 수 있다. 하지만 이것으로는 충분하지 않다. WCF 기반의 실제 프로젝트를 진행할 때 서비스는 많은 클라이언트에 의해 호출될 것이며 또한 오랫동안 안정적으로 서비스를 제공해야 할 것이다. 다시 말하자면 서비스 호스트 프로세스는 안정적으로 다수의 클라이언트로부터 동시 호출을 수용해야만 한다. 이러한 서비스의 가용성(availability)과 안정성(stability)에 직결되는 것은 서비스 호스트 프로그램을 얼마나 안정적으로 작성할 것 인가이다.
퍼뜩 떠오르는 것은 호스트 프로그램을 Windows 서비스(혹은 NT 서비스)로 작성하면 되지 않을까 생각할 수 있을 것이다. 하지만 Windows 서비스도 죽지 않는 불사신 같은 존재는 아니다. 안정적으로 작동하면서 오류를 잘 견디며, 검증된 호스트 프로그램은 없을까? 그렇다. 바로 IIS(Internet Information Service)가 바로 그런 호스팅 환경을 제공한다. IIS는 오랫동안 웹 어플리케이션의 호스트로서 빠른 성능과 안정된 수행환경을 자랑해 왔다. 특히, IIS 6.0이 제공하는 웹 가든(web garden), 프로세스 재생(recycling) 등의 기능은 최상의 웹 어플리케이션의 안식처로 평가 받아 왔다. 이러한 최상의 호스팅 환경을 WCF 에서도 사용할 수 있다. 즉, WCF 서비스의 호스트로서 IIS를 사용할 수 있다는 말이다.
WCF가 설치되면 IIS에 ISAPI Extension 및 ASP.NET 확장자(extension) 매핑을 통해 .svc 확장자를 가진 URL이 특별히 처리되도록 설정을 수행한다. 즉, 확장자가 .svc 인 파일이 액세스되면 이 파일이 WCF의 서비스로서 인식되도록 한다는 말이다. WCF에서 제공하는 ASP.NET의 HTTP 핸들러는 .svc 파일의 내용과 web.config 파일의 내용을 참조하여 ServiceHost 객체를 스스로 생성하고 서비스를 구동시켜 클라이언트 호출을 받을 수 있도록 구성되어 있다. 이제부터 구체적으로 WCF 서비스를 IIS에 호스팅 하는 방법을 살펴보도록 하자.
먼저 [그림 5]과 같이 솔루션에 ASP.NET 웹 어플리케이션 프로젝트를 추가하도록 한다. 물론 “웹 사이트 추가” 기능을 사용해도 되지만, 공동 작업, 배포, 빌드 등 여러 가지 이유로 웹 어플리케이션 프로젝트가 더 많이 사용되곤 한다. 프로젝트 생성 후, Default.aspx는 필요하지 않으므로 과감히 지워버리자. 그리고 [그림 6]과 같이 서비스의 계약이 선언되고 구현된 HelloWorldService 프로젝트를 “참조” 하도록 하자. 기억할지 모르겠지만 1장에서 Hello World 서비스의 계약을 선언하고 구현할 때 굳이 별도의 DLL 프로젝트를 만든 이유가 여기에 있다. 달랑 서비스 호스트 EXE 프로젝트에 서비스를 구현해 버렸다면 IIS에 호스팅 하기 위해 소스 코드를 복사하거나 코드를 다시 구현해 주어야 했을 것이다. 서비스를 별도의 어셈블리로 만들어 놓으면 이처럼 독립 EXE 어플리케이션이나 IIS 상에서 호스팅 하거나 Windows 서비스에서도 호스팅 하는 다양한 시나리오를 적용할 수 있어서 유리하다.

그림 5. 웹 어플리케이션 프로젝트 추가

그림 6. HelloWorldService 프로젝트 참조
이제 [그림 7]과 같이 텍스트 파일 아이템 템플릿을 이용하여 WCF 서비스에 대한 정보가 포함된 HelloWorld.svc 파일을 생성한다. Visual Studio에는 WCF 서비스를 위한 아이템 템플릿을 제공하지만 이 아이템 템플릿은 .svc 파일 뿐만 아니라 서비스 구현에 관련된 .cs 파일들도 생성해 버린다. 웹 프로젝트 내에 서비스 구현을 포함시킬 것이라면 이 아이템 템플릿이 편리하지만 우리의 Hello World 서비스 예제처럼 외부 어셈블리에 서비스 구현을 가지고 있는 경우 적합한 아이템 템플릿이 아니다. 따라서 텍스트 파일 아이템 템플릿을 사용하도록 하자.
HelloWorld.svc 파일은 ASP.NET 웹 서비스의 .asmx 파일과 매우 비슷하며 그 용도와 역할마저 같다. HelloWorld.svc 파일에는 ServiceHost 객체가 호스팅 할 서비스 타입을 명시하는 것이 가장 핵심적이다. 그리고 .asmx 파일과 마찬가지로 디버깅 여부 등의 잡다한 속성을 명시할 수 있다. 다음은 HelloWorld.svc 파일의 전체 내용이다.
<%@ServiceHost language=c# Debug="true"
Service="HelloWorldService.HelloWorldWCFService" %>

그림 7. HelloWorld.svc 파일 추가
HelloWorld.svc 파일에 명시된 @ServiceHost 지시자(directive)는 WCF 런타임이 생성할 ServiceHost 객체를 초기화 하는데 사용한다. 앞서 여러 번 살펴본 서비스 호스트 코드들([리스트 5]와 같이)에서 ServiceHost 클래스의 인스턴스를 생성할 때 생성자의 매개변수로 사용한 서비스 타입 정보를 기억하는가? 이 서비스 타입 정보를 @ServiceHost 지시자의 Service 속성을 통해 명시하는 것이다. 위 .svc 파일의 @ServiceHost 지시자 내용을 억지로 코드로서 표현해 보자면 다음 정도가 되겠다. 여기에서 서비스의 베이스 주소가 .svc 파일의 주소가 되었음을 주목하자. 이러한 코드가 WCF 런타임에 의해 자동적으로 수행된다고 보면 된다 .
ServiceHost host =
new ServiceHost(Type.GetType("HelloWorldService.HelloWorldWCFService"),
new Uri("http://localhost:1687/HelloWorld.svc"));
.svc 파일의 내용에 의해 서비스 호스트를 생성할 준비가 되었으므로 이제 남은 것은 이 서비스가 사용할 서비스 종점(endpoint)에 대한 사항이 남았다. 즉, @ServiceHost의 Service 속성에 의해 명시된 서비스 타입이 구현하는 서비스 계약(contract), 그리고 서비스의 주소와 서비스가 사용할 바인딩을 WCF에게 알려야 하는 것이다. 서비스 종점에 대한 설정은 web.config 에 <system.ServiceModel> 섹션을 추가하면 된다. Configuration을 사용하는 방법은 이미 살펴 보았으므로 web.config 의 내용을 곧바로 살펴보도록 하자.
리스트 21. WCF 서비스 호스팅에 관련된 web.config 파일 내용
<?xml version="1.0"?>
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="true" />
<authentication mode="Windows" />
</system.web>
<system.serviceModel>
<services>
<service name="HelloWorldService.HelloWorldWCFService"
behaviorConfiguration="HelloWorldService">
<endpoint contract="HelloWorldService.IHelloWorld"
address=""
binding="basicHttpBinding" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="HelloWorldService">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
[리스트 21]의 web.config 설정은 ASP.NET을 위한 섹션들이 존재할 뿐이지 [리스트 2]의 configuration과 크게 다를 바 없다. 서비스의 계약은 당연히 IHelloWorld 인터페이스가 될 것이며, 서비스 주소는 베이스 주소를 그대로 사용하도록 설정하였다. IIS에 호스팅 되는 서비스의 베이스 주소는 .svc 파일의 주소가 됨을 명심하자. 마지막으로 바인딩은 BasicHttpBinding을 사용하였다.
IIS에 호스팅 되는 서비스의 바인딩은 트랜스포트로서 반드시 HTTP 프로토콜을 사용해야만 한다. 이는 IIS가 웹 서버이기 때문에 너무나도 당연한 제약으로서 받아 들어야 할 것이다. 이 제약은 Windows 2000 및 Windows XP에 포함된 IIS 5.x 버전과 Windows Server 2003에 포함된 IIS 6.0에만 해당된다. Windows Vista와 Windows Server 2008에 포함되는 IIS 7.0 은 Windows Process Activation Service(WAS)를 통해 TCP 혹은 명명된 파이프 트랜스포트를 사용하는 WCF 서비스도 IIS의 작업 프로세스(worker process) 내에 호스팅이 가능하다.
자…… 이제 .svc 파일을 생성하였고 web.config 파일에 관련 설정도 했으면 테스트를 해볼 차례이다. 솔루션에 생성한 웹 프로젝트는 기본 설정 상 ASP.NET Development Server 라 불리는 웹 서버 상에서 수행된다. 이 개발용 웹 서버를 이용하여 테스트를 수행 할 수도 있고 개발된 웹 사이트를 IIS 상에 배포하여 테스트할 수도 있다. 혹은 웹 프로젝트의 설정을 바꾸어 가상 디렉터리를 통해 항상 IIS를 사용하도록 할 수도 있다. 이 책이 ASP.NET에 대한 책이 아니므로 더 이상 길게 설명하진 않겠다. 관련 서적이나 관련 자료를 MSDN 도움말에서 찾아보기 바란다.
필자는 개발용 웹 서버를 통해 간단히 테스트 해 보았고, 그 결과를 [그림 8]에 보인다. 웹 서비스의 URL 을 주목할 필요가 있으며 또한 WSDL을 위한 주소 역시 눈길 한 번 줘야 한다. 서비스의 URL은 앞서 언급한 대로 .svc 파일의 URL이 되었으며 WSDL을 위한 URL은 쿼리 문자열로서 ?wsdl 이 추가 되었음을 확인 하자.

그림 8. IIS에 의해 호스팅 된 Hello World 서비스
테스트가 끝났으니 이제 WCF 서비스는 IIS 상에서 호스팅 되어 서비스를 제공할 수 있게 되었다. 앞서 작성해 놓은 클라이언트의 코드 혹은 app.config 파일에서 서비스의 주소를 적절히 바꾸어 주면 클라이언트는 IIS 상에서 호스팅 되는 서비스를 호출 할 수 있게 된다.