.NET Framework
WCF와 .NET Framework 3.5를 사용한 HTTP 프로그래밍
Sunny's
2010. 3. 9. 15:03
이 기사는 Visual Studio 2008 시험판 버전을 기준으로 합니다. 여기에 포함된 모든 정보는 변경될 수 있습니다.
이 기사에서 다루는 내용:
|
이 기사에서 사용하는 기술: Windows Communication Foundation |
Microsoft® .NET Framework 3.0의 구성 요소의 하나로 처음 모습을 드러냈을 때 WCF(Windows® Communication Foundation)에는 다양한 전송 방식을 통한 SOAP 메시징 및 POX(Plain Old XML)에 사용되는 범용 개체 모델이 포함되어 있었습니다. WCF는 WS-* 웹 서비스 표준에 대한 심층적인 지원도 포함하고 있으므로 다른 최신 서비스 플랫폼과도 무리 없이 상호 운용할 수 있습니다. .NET Framework 3.0의 WCF는 확장성이 뛰어나며, 메시지 로깅, 작업 추적, 서비스 조정, 인스턴스 관리, 스레딩 제어 등의 강력한 관리 기능도 제공합니다.
.NET Framework 3.5의 WCF는 .NET Framework 3.0의 확장 지점을 기반으로 하여 웹 규칙에 부합하는 서비스 구축을 위한 최상의 지원을 제공합니다. 여기에는 사용하기 쉬운 HTTP 프로그래밍 모델, JSON(JavaScript Object Notation) 메시징 기능, 배포된 콘텐츠를 손쉽게 만들고 소비할 수 있게 해주는 새로운 배포 API가 포함됩니다. 이러한 기능 집합을 갖춘 WCF는 이제 ASP.NET AJAX 컨트롤, SilverlightTM 클라이언트, 그리고 브라우저까지 모든 종류의 웹 클라이언트에 서비스를 연결하는 데 있어 최적의 서비스 플랫폼입니다. 이러한 기능은 부분 신뢰 시나리오(예: ASP.NET 보통 신뢰)에서도 작동하므로 광범위하게 사용되는 호스팅 환경에서 WCF 서비스를 호스트할 수 있습니다. 또한 서비스 준비와 실행에 소요되는 시간을 크게 줄여 주는 새로운 도구가 Visual Studio® 2008에 통합되어 완성도를 더욱 높여 줍니다.
웹 중심 통신과 SOAP 및 WS-* 표준을 하나의 서비스 스택 및 개체 모델로 결합하는 기능은 .NET Framework 3.5에 포함된 WCF의 장점 중 하나입니다. 이는 SOAP 및 WS-*를 사용하여 엔터프라이즈 경계 내에서 또는 경계를 넘어 통신하는 서비스를 구축하고, 웹 프로토콜을 사용하여 외부적으로 통신하도록 이러한 서비스를 구성할 수 있음을 의미합니다. 실질적으로 WCF가 서비스의 복잡한 연결 구성을 도맡아 처리하므로 개발자는 서비스가 제공하는 기능에 더욱 주력할 수 있습니다.
이 기사에서는 .NET Framework 3.5에서 WCF가 제공하는 몇 가지 새로운 웹 중심 기능에 대해 설명합니다. HTTP와 웹의 중요한 아키텍처 원칙에 대한 기본적인 내용부터 시작한 후 WCF의 새로운 프로그래밍 모델을 살펴보고 마지막으로 새로운 배포 API에 대해 알아보겠습니다.
HTTP 메시지 기본 사항
여러분들은 아마 거의 매일 웹을 사용할 텐데, 웹이 움직이는 핵심 원리에 대해서는 얼마나 생각하십니까? 아키텍처 개념에 대한 이야기는 필자의 성격에 맞지 않지만 웹의 기반이 되는 핵심 개념 중에는 쉽게 이해하기 어려운 부분이 있습니다. 개인적으로 웹의 프로토콜에 부합하는 서비스를 구축할 때는 가장 먼저 이러한 원칙부터 이해해야 한다고 생각합니다. 많은 서적에서 이 주제를 전문적으로 다루고 있는 점을 감안하여 이 기사에서는 가장 핵심적인 부분만 언급하겠습니다.
HTTP는 웹의 전송 수단입니다. HTTP는 요청/응답 MEP(메시지 교환 패턴)를 요구합니다. 이 패턴은 브라우저에서 웹 페이지를 탐색할 때마다 발생합니다. 즉, 리소스를 요청하면 해당 리소스가 포함된 하나의 응답이 반환됩니다. HTTP 전송은 메서드라고도 하는 몇 가지 동사를 정의하는데, 이러한 동사는 요청/응답 MEP에 GET, POST, PUT, DELETE 등의 기능을 추가합니다. HTTP 동사 간의 몇 가지 차이점을 살펴보기 위해 HTTP POST를 예로 들어 보겠습니다. 다음은 단순화된 형태입니다.
POST /myservice/PostAlbum HTTP 1.1 HOST: www.cloudsample.net <albumInfo> <albumId>15</albumId> </albumInfo>
수신 응용 프로그램에 전송되는 것은 하나의 메시지입니다. 여기에서 메시지는 으로 전송됩니다. 이 메시지에는 albumId 필드의 값이 들어 있는 페이로드도 포함되어 있습니다. 요약하자면 HTTP POST는 수신 응용 프로그램에 페이로드를 전송하는 수단이라고 할 수 있습니다.
이 예의 페이로드는 간단하므로 15라는 숫자로 전체 페이로드를 나타낼 수 있습니다. 작동을 위해서는 숫자 15가 albumId 필드의 값에 매핑된다는 사실을 수신 응용 프로그램에서 인식해야 합니다. 이 기능은 HTTP GET에서 제공되는 핵심 기능 중 하나입니다. 예를 들어 앞의 HTTP POST에서 HTTP GET으로 전환한 결과는 다음과 같습니다.
GET /myservice/GetAlbum/15 HTTP 1.1 HOST: www.cloudsamples.net
HTTP GET은 최적화된 HTTP POST이며 페이로드의 필요성을 제거할 수 있습니다. 사실상 URI가 페이로드입니다. 이는 메시지 크기를 줄이는 효과를 가져오고 따라서 전송 시간도 단축됩니다. 크기가 작은 메시지와 URI 사용에 따른 또 하나의 이점은 프록시 또는 브라우저와 같은 다른 응용 프로그램에서 동일한 리소스에 대한 이전 HTTP GET 메시지의 결과를 캐시하기가 더 쉽다는 점입니다. 이러한 이유로 HTTP GET은 다른 HTTP 동사보다 훨씬 더 자주 사용됩니다.
본질적으로 HTTP GET은 리소스에 대한 요청입니다. 이해를 돕기 위해 웹 사이트에 있는 흥미로운 리소스를 친구에게 전자 메일로 보내려는 경우를 가정해 보십시오. 여러분은 전자 메일을 받은 친구가 링크를 클릭하여 여러분이 보는 것과 똑같은 페이지를 볼 수 있으리라 생각합니다. 따라서 의 리소스가 갑자기 MSNBC의 최신 기사로 바뀐다면 깜짝 놀랄 것입니다. 사실 HTTP GET에 사용되는 URI는 리소스의 표현이며, 일반적으로 리소스는 변경되지 않을 것으로 간주됩니다.
HTTP GET이 나타내는 의미에 대해서는 명확한 결론이 나오지만 다른 HTTP 동사의 경우에는 그렇지 않습니다. 수신 응용 프로그램에 HTTP DELETE 메시지를 보낼 경우의 영향을 생각해 보십시오. 수신 응용 프로그램은 상태를 바꾸거나 어떤 작업을 수행해야 할까요? HTTP DELETE는 대개 무언가를 감하는 상태 변경이나 작업과 연관되지만 해당 상태 변경의 구체적인 사항은 정의되지 않습니다. HTTP PUT의 경우도 마찬가지입니다. 일반적으로 HTTP PUT은 무언가를 더하는 상태 변경이나 작업과 연관이 있지만 구체적인 변경 형태는 응용 프로그램에 따라 다릅니다.
추가 정보 표현
HTTP GET을 수신하는 응용 프로그램은 URI에 포함된 정보를 사용하여 응답으로 보낼 리소스를 결정합니다. 예를 들어 다음 URI를 살펴보겠습니다.
contoso.com/artists/Flaming+Hammer/HitMe contoso.com/artists/Northwind/Overdone
이 예에서 Contoso Corporation에는 음악 관련 리소스를 서비스하는 응용 프로그램이 있습니다. 이러한 예를 통해 다음과 같이 음악가와 앨범의 이름이 URI에 매핑되는 방식을 추론할 수 있습니다.
contoso.com/artists/[artist]/[album]
응용 프로그램에서 http://contoso.com/artists/Northwind/Overdone에 대한 HTTP GET 메시지를 수신하면 Northwind의 Overdone 앨범과 관련된 리소스를 반환해야 합니다. URI에는 일정한 패턴이 있습니다. 즉, 기본 정보(contoso.com/artists)와 음악가 및 앨범의 값이 들어가는 URI 세그먼트(또는 "홀")로 구성됩니다.
같은 종류의 정보를 쿼리 문자열 매개 변수에 포함하는 경우도 많습니다. 형식은 이전 예제와 다르지만 최종 결과는 동일합니다. 다음은 쿼리 문자열 매개 변수를 사용한 몇 가지 URI 홀입니다.
contoso.com/artists/Flaming+Hammer?album=HitMe contoso.com/artists/Northwind?album=Overdone
이 예의 URI와 쿼리 문자열은 다음 구문을 사용합니다.
contoso.com/artists/[artist]?album=[album]
HTTP 전송은 추가 정보를 표현하기 위한 확장 가능한 헤더 집합도 사용합니다. 이 정보는 캐싱, 메시지의 데이터 형식, 전송 응용 프로그램의 이름, 콘텐츠의 길이, 호스트 운영 체제 등에 관한 정보일 수 있습니다. 그림 1은 몇 가지 일반적인 헤더가 포함된 HTTP GET 메시지(1-8행)와 응답 메시지(9-14행)를 보여 줍니다.

1 GET /PictureServices/Feed.svc/picture/Pictures;Bridge.jpg HTTP/1.1 2 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, application/x-silverlight, */* 3 Accept-Language: en-us 4 UA-CPU: x86 5 Accept-Encoding: gzip, deflate 6 User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0;SLCC1; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 1.1.4322; .NET CLR 3.5.20706; .NET CLR 3.0.590; MS-RTC LM 8) 7 Host: www.cloudsamples.net 8 Proxy-Connection: Keep-Alive 9 HTTP/1.1 200 OK 10 Content-Type: image/jpeg 11 Server: Microsoft-IIS/7.0 12 X-Powered-By: ASP.NET 13 Date: Sat, 15 Sep 2007 18:57:11 GMT 14 Content-Length: 106333
HTTP GET 요청의 Accept 헤더는 클라이언트에서 수신해야 하는 데이터의 형식을 나타냅니다. 긴 값 목록을 통해 볼 수 있듯이 클라이언트에서 수신할 수 있는 데이터의 종류는 다양합니다(이미지, Office 문서, Silverlight 응용 프로그램 등). HTTP GET에 대한 응답에는 Content-Type 헤더(10행의 image/jpeg) 값에 기술된 형식의 데이터가 포함됩니다. 이 간단한 메커니즘을 통해 전송 응용 프로그램과 수신 응용 프로그램은 데이터 형식을 조정할 수 있습니다. 헤더를 통한 데이터 형식 조정은 SOAP 웹 서비스의 WSDL(웹 서비스 기술 언어) 및 XSD(XML 스키마 정의) 문법만큼 명확하지는 않지만 웹에 사용하기에는 충분합니다.
REST와 웹
지금까지 HTTP 전송의 핵심적인 부분 일부를 연구하면서 웹을 느슨하게 연결하는 몇 가지 중요 원칙도 함께 살펴보았습니다. 지난 2000년 Roy Fielding이라는 학생이 박사 학위 논문에서 이러한 원칙을 다른 요소과 함께 REST(Representational State Transfer)라는 하나의 아키텍처 스타일로 체계화했습니다. Roy의 논문은 ics.uci.edu/~fielding/pubs/dissertation/top.htm에서 볼 수 있습니다.
REST 아키텍처 스타일은 지금까지 여러 서적과 소프트웨어 회의, 그리고 무수히 많은 블로그에서 세부적으로 다룬 주제입니다. 여기서 REST의 모든 측면에 대해 설명하긴 어렵지만 다음과 같은 세 가지 핵심 문장으로 요약할 수 있습니다.
- URI를 포용한다.
- HTTP GET은 특수하다.
- Content-Type은 데이터 모델이다.
이 기사에서는 설명을 위해 위의 세 가지 사항을 웹의 기본 원칙으로 간주하겠습니다. 응용 프로그램에 이 세 가지 원칙을 적용하면 상호 운용성과 응용 프로그램 기능의 대상 범위를 크게 향상시킬 수 있습니다. 상호 운용성과 대상 범위는 대부분의 웹 서비스 이니셔티브를 견인하는 핵심 요소입니다. 궁극적으로 웹 서비스는 구조화된 메시징 체계를 통해 기능을 제공하는 수단입니다. 사실 웹의 원칙(HTTP 요청/응답)은 가능한 메시징 체계의 하위 집합을 기술하는 것입니다. 거의 모든 플랫폼, 응용 프로그램, 운영 체제 및 사용자는 웹의 원칙을 이해하고 있으므로 웹 서비스 응용 프로그램에 이러한 원칙을 적용하면 대상 범위와 상호 운용성을 높일 수 있습니다.
REST와 WS-* 간의 선택은 상호 배타적이 아니므로 웹의 원칙은 WS-*에 별다른 영향을 미치지 않습니다. 둘 중 하나만으로는 모든 통신 요구 사항을 만족할 수 없으므로 구축하는 모든 서비스에 어느 하나를 일률적으로 적용하는 것은 좋지 않습니다. 예를 들어 REST는 중개자에 메시지를 전송하는 데에는 적합하지 않고, 이 부문에선 WS-*가 훨씬 더 뛰어납니다. 반대로 브라우저와 같이 단순한 클라이언트와 상호 작용하는 데에는 WS-* 응용 프로그램이 그다지 적합하지 않은 반면 REST 응용 프로그램이 빛을 발합니다.
WCF를 사용한 HTTP 프로그래밍
이러한 웹의 기본 사항을 기초로 .NET Framework 3.5에서 WCF를 사용하여 웹의 원칙에 부합하는 응용 프로그램을 구축하는 과정을 살펴보겠습니다. 먼저 HTTP 프로그래밍 모델과 프로세스의 몇 가지 새로운 구성 요소를 시스템 전반에 걸쳐 상향식으로 파악해 보겠습니다.
"URI를 포용"하려면 URI 작성과 구문 분석에 익숙해져야 합니다. 수동으로 처리할 경우 이 작업은 실수 발생 가능성이 높고 지루한 작업입니다. 다행히 WCF의 새 HTTP 기능을 위한 기본 구성 요소인 새로운 System.UriTemplate 및 System.UriTemplateMatch 형식이 URI를 생성하고 구문 분석하는 어려운 작업을 처리해 줍니다.
UriTemplate 형식은 앞서 설명한 URI 홀을 정의하는 기본 구성 요소입니다. UriTemplate 형식의 생성자는 URI의 홀을 나타내는 문자열을 받습니다. 인스턴스화된 UriTemplate 개체는 인스턴스화에서 정의된 홀에 텍스트 값을 바인딩하기 위한 두 개의 인스턴스 메서드를 제공합니다. 이 두 메서드는 홀에 값이 채워진 URI를 반환합니다.
UriTemplate 개체는 System.Uri 개체의 홀 값을 추출하는 Match라는 인스턴스 메서드도 제공합니다. Match 인스턴스 메서드는 두 개의 System.Uri 개체를 받습니다. 첫 번째 Uri는 기준 주소이며 두 번째 Uri는 일치시킬 대상입니다. System.UriTemplateMatch 개체는 Match 메서드에서 반환됩니다. UriTemplateMatch 개체에는 UriTemplate 인스턴스화 시점에 정의된 홀의 값 컬렉션이 포함되어 있습니다.
그림 2의 코드는 UriTemplate 및 UriTemplateMatch 형식을 사용하여 Uri를 왕복 전달하는 방법을 보여 줍니다. 이 코드의 결과는 다음과 같습니다.

// 템플릿으로의 URI 바운드 만들기 Uri baseAddress = new Uri(@"http://localhost:2000"); UriTemplate template = new UriTemplate("{artist}?album={album}"); Uri boundUri = template.BindByPosition(baseAddress, "Northwind", "Overdone"); Console.WriteLine(boundUri.ToString()); // 음악가 세그먼트 검색 UriTemplateMatch match = template.Match(baseAddress, boundUri); String bandName = match.BoundVariables["artist"]; Console.WriteLine("the name of the artist is {0}", bandName); (참고: 프로그래머 주석은 예제 프로그램 파일에는 영문으로 제공되며 기사에는 이해를 돕기 위해 번역문으로 제공됩니다.)
http://localhost:2000/Northwind?album=Overdone the name of the artist is Northwind
System.UriTemplate 및 System.UriTemplateMatch 형식에는 네임스페이스에 일반적인 WCF System.ServiceModel 모니커가 없습니다. WCF 응용 프로그램 내에서는 이 모니커의 기능을 사용할 필요가 없기 때문입니다. 이 모니커는 URI를 만들거나 구문 분석할 때 상당히 유용합니다.
UriTemplate 및 UriTemplateMatch 형식은 원래 사용하기 쉽지만 WCF 팀은 WCF 서비스에서 이 형식을 더욱 쉽게 사용할 수 있게 만들고자 했습니다. URI 세그먼트와 쿼리 문자열 매개 변수를 응용 프로그램 기능에 매핑하는 간단하고 직관적인 방법을 구현하는 것을 목표로 했습니다. 다음 코드의 모델이 이러한 조건에 부합합니다.
[ServiceContract] public interface IPictureService { [OperationContract] [WebGet(UriTemplate = "picture/{pictureId}")] Stream GetPicture(String pictureId); [OperationContract] [WebGet(UriTemplate = "picture/t/{pictureId}")] Stream GetPictureThumbnail(String pictureId); }
UriTemplate은 WebGetAttribute에 대한 인스턴스 속성으로 노출되고, WebGetAttribute는 다시 서비스 계약에 적용됩니다. 여기서 중괄호 사이의 토큰은 메서드 매개 변수의 이름에 매핑됩니다. 이 샘플에는 매개 변수가 하나밖에 나오지 않지만 여러 매개 변수를 추가하여 원하는 순서에 따라 정렬하고, 쿼리 문자열 매개 변수로 추가하거나 와일드카드를 사용할 수도 있습니다.
런타임에 UriTemplate 속성의 값이 UriTemplate 생성자에 전달됩니다. Client 런타임과 Dispatcher는 모두 이러한 방식으로 UriTemplate 속성을 사용합니다. Dispatcher는 들어오는 메시지를 작업에 연결하는 데 이 속성을 사용하고 Client는 프록시의 메서드가 올바른 URI에 전송되도록 하는 데 사용합니다. 이는 서비스에 "URI를 포용"하기 위한 쉽고 간단하고 효과적인 방법입니다.
WCF 계약의 HTTP 동사
.NET Framework 3.5의 WCF를 사용하여 HTTP 프로그래밍을 수행하면 서비스 계약의 작업을 HTTP 동사에 쉽게 매핑할 수 있습니다. 이름에서 쉽게 알 수 있듯이 WebGetAttribute를 작업에 적용하면 HTTP GET을 통해 해당 작업을 사용할 수 있습니다. 이전 코드 조각에서 살펴보았듯이 WebGetAttribute는 UriTemplate이라는 인스턴스 속성을 정의합니다.
WebGetAttribute 형식에는 다른 인스턴스 속성도 있습니다. 그 중 가장 중요한 속성은 RequestFormat과 ResponseFormat입니다. 이름이 암시하는 바와 같이 이 두 속성의 값은 작업에 대한 메시지 형식을 지정합니다. RequestFormat과 ResponseFormat 속성은 Xml과 Json, 두 개의 값을 갖는 열거 형식인 WebMessageFormat 형식입니다. WCF 인프라는 이 두 속성의 값을 사용하여 적절한 메시지 인코더로 채널 스택을 설정합니다. WebMessageFormat.Xml의 속성 값은 XML 인코더를 사용하는 채널 스택으로 이어집니다. 값을 WebMessageFormat.Json으로 설정하면 .NET Framework 3.5에 포함된 JSON 인코더를 사용하는 채널 스택이 설정됩니다. HTTP 메시지 교환의 양쪽 모두에 대한 속성이 모두 있으므로 응용 프로그램에서 XML 메시지를 수신하고 JSON 메시지를 반환하거나 그 반대로 할 수 있습니다.
HTTP 동사와 관련된 또 다른 특성은 WebInvokeAttribute입니다. 작업에 이 특성을 적용하면 HTTP GET을 제외한 모든 HTTP 동사를 통해 해당 작업을 사용할 수 있습니다. HTTP GET과 다른 모든 동사 간의 개체 모델 분리는 다른 HTTP 동사와 HTTP GET 간의 사용 빈도 차이를 반영합니다. WebInvokeAttribute 개체 모델은 WebGetAttribute와 유사하지만 Method라는 인스턴스 속성을 포함합니다. 이 속성의 값은 특정 HTTP 동사를 작업에 연결합니다. Method 속성은 String 형식이므로 값을 모든 표준 HTTP 동사는 물론 비표준 HTTP 동사로도 설정할 수 있습니다. 그림 3은 서비스 계약에 WebInvokeAttribute를 사용하는 방법을 보여 줍니다.

[ServiceContract] public interface IPictureService { [OperationContract] [WebGet(UriTemplate = "picture/{pictureId}")] Stream GetPicture(String pictureId); [OperationContract] [WebGet(UriTemplate = "picture/t/{pictureId}")] Stream GetPictureThumbnail(String pictureId); [OperationContract] [WebInvoke(UriTemplate="update", Method="POST")] void UpdatePictureInfo(PictureInfo info); }
UpdatePictureInfo 메서드에는 PictureInfo 형식의 매개 변수가 있습니다. 런타임에는 PictureInfo 개체의 직렬화된 버전이 HTTP POST 메시지의 페이로드입니다. 이 방법으로 데이터를 구문 분석하면 응용 프로그램에서 다른 방법으로는 URI에 표현할 수 없는 복잡한 데이터 형식을 제공할 수 있습니다.
.NET Framework 3.5의 WCF는 HTTP 헤더와의 상호 작용도 용이하게 합니다. 요청 및 응답 HTTP 헤더는 System.ServiceModel.Web.WebOperationContext 형식을 통해 제공됩니다. WebOperationContext 형식은 .NET Framework 3.0의 WCF에 도입된 System.ServiceModel.OperationContext 형식의 확장으로, 사용 패턴이 유사합니다. 이 두 가지 형식은 모두 서비스 개체의 구현에 사용하기 위해 도입되었습니다. WebOperationContext 형식이 제공하는 멤버는 HTTP 헤더 값의 읽기 및 설정을 간소화하고 서비스 개체에 액세스하는 데 사용되는 URI에 대한 정보를 검색합니다. HTTP 헤더는 컬렉션으로 저장되며 자주 사용되는 헤더는 개별 속성으로 제공됩니다. 다음 예에서는 웹의 데이터 모델을 따르기 위해 HTTP 응답에 대한 Content-Type 헤더를 설정하는 방법으로 WebOperationContext 형식을 사용하는 방법을 보여 줍니다.
public Stream GetPicture(string pictureId) { // 스트림 가져오기(생략됨) Stream stream; // 콘텐츠 형식을 image/jpeg로 설정 WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg"; return stream; }
바인딩 및 호스팅
지금까지 응용 프로그램 기능에 URI 세그먼트를 매핑하고 HTTP 동사에 작업을 매핑하고 HTTP 헤더와 상호 작용하는 방법을 살펴보았습니다. 이제 이러한 기능을 작동하는 하나의 서비스로 연결하는 방법을 알아보겠습니다. 이를 위해서는 WCF에 새로 추가된 몇 가지 형식에 대해서도 알아두어야 합니다.
.NET Framework 3.0의 WCF에는 끝점의 전송 및 프로토콜을 통한 추상화인 바인딩 개념이 도입되었습니다. .NET Framework 3.0에는 폭넓은 전송 및 프로토콜에 대한 지원이 포함된 여러 가지 바인딩이 제공되었습니다.
.NET Framework 3.5의 WCF에는 System.ServiceModel.WebHttpBinding이라는 새로운 바인딩이 포함되어 있습니다. 이 바인딩은 웹 원칙의 추상화이며 .NET Framework 3.0의 바인딩 형식과 동일한 사용 모델을 따르므로 다른 바인딩과 마찬가지로 끝점에 추가할 수 있습니다.
.NET Framework 3.0의 WCF에는 끝점 동작이라는 개념도 도입되었습니다. 동작은 메시징 인프라의 실행 경로를 확장하는 방법입니다. .NET Framework에서는 몇 가지 동작이 기본 제공되며 직접 만들기도 쉽습니다.
.NET Framework 3.5의 WCF에는 System.ServiceModel.Description.WebHttpBehavior라는 새로운 끝점 동작이 포함되어 있습니다. 이 동작은 여러 가지 작업을 수행합니다. 수신 응용 프로그램의 경우 이 동작은 수신된 메시지가 서비스 개체의 적절한 메서드에 발송되도록 하는 필터링 인프라를 설정하는 등의 역할을 수행합니다. .NET Framework 3.0에서 WCF는 SOAP 작업과 대상 주소의 조합을 발송 키로 사용했습니다. WebHttpBehavior에 의해 설정되는 필터링 메커니즘은 UriTemplate 일치 및 HTTP 동사의 키로 기존 메커니즘을 확장합니다.
그림 4는 WebHttpBinding과 WebHttpBehavior를 사용하여 웹의 원칙을 따르는 수신 응용 프로그램을 작성하는 방법을 보여 줍니다. 이 방식의 이점은 이러한 끝점 중 하나를 기존 ServiceHost에 추가할 수 있으며, 이를 통해 SOAP/WS-* 끝점과 REST 끝점을 모두 갖는 단일 ServiceHost를 만들 수 있다는 것입니다.

ServiceHost host = new ServiceHost(typeof(IPictureContract), new Uri("http://localhost:5000")); // WebHttpBinding 인스턴스화 WebHttpBinding binding = new WebHttpBinding(); // WebHttpBinding을 사용하여 끝점 추가 ServiceEndpoint ep = host.AddServiceEndpoint( typeof(IPictureContract), binding, String.Empty); // 끝점에 WebHttpBehavior 추가 ep.Behaviors.Add(new WebHttpBehavior()); // 수신 시작을 위해 ServiceHost 열기 host.Open();
전송 응용 프로그램도 동일한 사용 모델을 따르지만 ChannelFactory<T> 개체에 대한 끝점 동작 컬렉션에 WebHttpBehavior를 추가해야 합니다. 일반적인 WCF 사용법에 따라 이러한 옵션은 구성 파일에서도 제공됩니다.
.NET Framework 3.5의 WCF는 경우에 따라 WebHttpBinding 또는 WebHttpBehavior를 추가할 필요가 없도록 사용이 간편한 이 모델을 더 심층적으로 사용하기도 합니다. 새로운 API에는 이 용도로 사용되는 System.ServiceModel.Web.WebServiceHost와 System.ServiceModel.Web.WebServiceHostFactory라는 두 가지 형식이 있습니다. WebServiceHost 형식은 모든 끝점에 WebHttpBehavior를 자동으로 추가하고 런타임에 모든 끝점이 동작과 호환되는지 확인하는 추가 유효성 검사를 실행합니다. 덕분에 끝점에 WebHttpBehavior를 추가할 필요가 없습니다.
WebServiceHostFactory 형식은 IIS 호스트 시나리오에서 필수 또는 구성 파일 호스팅 정보의 필요성을 제거하도록 고안되었습니다. .NET Framework 3.0의 WCF에는 IIS에서 WCF 서비스를 호스트하기 위한 활성화 대상으로 .svc 파일이 추가되었습니다. 이러한 파일에는 ASP.NET의 페이지 지시어와 유사한 지시어가 포함되어 있습니다. .svc 파일 지시어의 Factory 속성에 WebServiceHostFactory를 추가하면 ServiceHost가 생성되고, WebHttpBinding에 적절한 계약을 사용하는 끝점이 추가되고, 해당 끝점에 WebHttpBehavior가 추가되고, ServiceHost가 열립니다.
<%@ ServiceHost Language="C#" Service="PictureService" Factory="System.ServiceModel.Web.WebServiceHostFactory" %>
서비스에 대한 web.config 파일에는 WCF 관련 항목이 없습니다.
새로운 배포 API
RSS 피드를 생각해 보십시오. 필자와 비슷한 독자들은 즉시 뉴스 피드나 블로그를 떠올릴 것입니다. 배포(RSS 및 ATOM은 배포 형식임)는 훨씬 더 많은 것을 표현할 수 있습니다. 개념적으로 말하면 배포된 콘텐츠는 데이터 집합을 표현하는 수단에 불과합니다. 이 데이터 집합은 시드니의 50마일 반경 내에 서식하는 웜뱃의 수, 100달러를 초과하는 최근 10건의 구매 주문, Contoso에서 지난달에 생산한 부메랑의 수 등 어떠한 정보라도 될 수 있습니다.
.NET Framework 3.5는 배포된 콘텐츠를 만들고 소비하기 위한 풍부한 지원을 포함하고 있습니다. RSS 2.0 형식과 ATOM 1.0 형식의 생성 및 소비, 배포 확장을 추가하기 위한 다양한 방법, 그리고 추가 형식을 구현하는 기능까지 지원합니다. 이 프로그래밍 모델에서는 개발자가 배포 형식의 세부 사항에 신경 쓸 필요가 없으므로 사용하기도 그만큼 더 쉽습니다.
버전 3.5 이전에는 .NET Framework로 배포된 콘텐츠를 만들거나 소비하는 표준화된 방법이 없었습니다. WCF 팀에서 새로운 배포 기능을 작성했지만 이는 WCF에 종속되지 않습니다. 사실 모든 배포 관련 형식은 System.ServiceModel.Web.dll 어셈블리에 포함되어 있기는 하지만 System.Syndication 네임스페이스의 일부입니다. AppDomain을 호스트하는 모든 프로세스(ASP.NET, WPF 응용 프로그램, NT 서비스 등)에서 .NET Framework 3.5의 배포 기능을 사용할 수 있습니다. 이는 HTTP뿐만 아니라 모든 전송 방식에서 배포된 콘텐츠를 서비스하고 소비할 수 있음을 의미합니다. 그러나 WCF의 HTTP 프로그래밍 모델과 함께 사용할 경우 기존 SOAP/WS-* 서비스에도 배포를 추가할 수 있습니다.
새 배포 API에는 개별 배포 피드와 피드의 항목을 추상화하는 형식과 해당 피드를 특정 형식으로 변환할 수 있는 형식이 포함되어 있습니다. System.Syndication.SyndicationFeed 형식은 배포 피드의 형식 중립적인 표현입니다. SyndicationFeed에는 SyndicationItem 개체의 목록이 들어 있습니다. SyndicationItem 개체는 피드의 항목에 대한 표현일 뿐이므로 SyndicationItem 개체 집합이 없는 SyndicationFeed는 빈 콩깍지와 같습니다.
SyndicationFeed에 SyndicationItem 개체 집합이 채워지면 SyndicationFeedFormatter<T>가 해당 피드를 특정 형식으로 변환할 수 있습니다. SyndicationFeedFormatter<T>에서는 Rss20FeedFormatter와 Atom10FeedFormatter, 두 가지 형식이 파생됩니다. 이름에서 짐작할 수 있듯이 이 두 형식은 SyndicationFeed 인스턴스를 각각 RSS 2.0 형식과 ATOM 1.0 형식으로 변환합니다.
SyndicationFeed 생성
SyndicationFeed 개체는 두 가지 방법으로 만들 수 있습니다. 인스턴스화한 후 멤버를 수동으로 채우거나, 기존 피드로 전체 SyndicationFeed를 채울 수 있습니다. 두 방법 모두 수행하기 쉽고 개발자는 특정 연결 형식에 신경 쓸 필요가 없습니다. 다음 코드는 SyndicationFeed 개체를 수동으로 만드는 방법을 보여 줍니다.
SyndicationFeed feed = new SyndicationFeed(); feed.Title.Text = "The Cybertopian Chronicle";
Title은 설정 가능한 여러 가지 속성 중 하나일 뿐이므로 더 자세한 내용은 설명서를 참조하십시오.
기존 피드를 읽어 해당 피드의 콘텐츠를 기반으로 특정 작업을 수행해야 하는 경우가 많습니다. 새로운 배포 API에서는 SyndicationFeed를 인스턴스화하고 기존 피드를 사용하여 자동으로 상태를 채울 수 있습니다. 기존 피드, 또는 이 피드를 읽도록 설정된 XmlReader의 URI만 시작하면 됩니다. 다음 코드는 웹의 기존 피드에 연결하여 일부 정보를 추출하는 방법을 보여 줍니다.
Uri feedUri = new Uri("http://blogs.msdn.com/justinjsmith/atom.xml"); SyndicationFeed feed = SyndicationFeed.Load(feedUri); Console.WriteLine(feed.Title.Text); // "The Cybertopian Chronicle" 출력
SyndicationItem 형식에는 35개 이상의 멤버가 있습니다. 이러한 멤버 중 다수는 항목 식별자, 마지막 업데이트 시간, 게시 날짜, 제목, 실제 콘텐츠 등의 필드를 설정 또는 검색하는 것과 관련된 속성입니다. SyndicationItem에 저장된 콘텐츠를 손쉽게 확장할 수 있게 해주는 멤버도 많이 있습니다. RSS와 ATOM에는 많은 확장이 있으며(Microsoft Simple List Extensions, Yahoo Media RSS, GeoRSS 등), SyndicationFeed와 SyndicationItem 모두 기존 RSS 또는 ATOM 확장을 포함할 수 있습니다.
피드에는 많은 항목이 포함될 수 있고, 이러한 항목들을 한 번에 로드하는 것은 대용량 피드에서 적절하지 않습니다. SyndicationFeed는 SyndicationItem 개체 집합을 IEnumerable<SyndicationItem>로 제공하여 이러한 문제를 해결합니다. 이러한 구현은 .NET Framework 2.0의 반복기 기능을 활용하므로 많은 수의 SyndicationItem 개체를 손쉽게 처리할 수 있습니다. 또한 LINQ를 사용하여 SyndicationItem 개체 집합을 반복할 수도 있습니다. 이렇게 하면 피드에서 정보를 추출하는 데 필요한 코드의 양이 대폭 감소됩니다.
배포 API는 SyndicationFeed를 RSS 2.0 및 ATOM 1.0 형식으로 변환하는 여러 가지 형식을 정의합니다. 사실 SyndicationFeed를 하나 만들어 SyndicationItem 개체로 채운 다음 RSS와 ATOM으로 제공할 수도 있습니다. 그림 5는 ATOM 1.0 피드를 검색하여 RSS 2.0으로 변환하고 새로운 RSS 표현을 콘솔에 출력하는 방법을 보여 줍니다.

// ATOM 피드 읽기 Uri feedUri = new Uri("http://blogs.msdn.com/justinjsmith/atom.xml"); SyndicationFeed feed = SyndicationFeed.Load(feedUri); // RSS로 변환 Rss20FeedFormatter formatter = new Rss20FeedFormatter(feed); XmlWriter writer = XmlWriter.Create(Console.Out, null); // 콘솔로 쓰기 formatter.WriteTo(writer); writer.Flush();
배포 API를 WCF의 HTTP 프로그래밍 모델과 함께 사용하면 사용자 지정된 URI의 피드를 제공하고 해당 URI의 구성에 따라 RSS 또는 ATOM을 반환할 수 있습니다. 그림 6은 수신된 HTTP GET의 쿼리 문자열 매개 변수를 사용하여 RSS 또는 ATOM 피드를 반환하는 작업을 서비스 계약에서 정의하는 방법을 보여 줍니다. 작업 계약에 SyndicationFeedFormatter<SyndicationFeed>가 사용된 것을 볼 수 있습니다. Rss20FeedFormatter와 Atom10FeedFormatter는 모두 SyndicationFeedFormatter<TSyndicationFeed>에서 파생됩니다.

[ServiceKnownType(typeof(Atom10FeedFormatter))] [ServiceKnownType(typeof(Rss20FeedFormatter))] [ServiceContract] interface IPictureService { [OperationContract] [WebGet(UriTemplate="Pictures?format={format}")] SyndicationFeedFormatter<SyndicationFeed> Feed(String format); } class PictureService : IPictureService { public SyndicationFeedFormatter<SyndicationFeed> Feed(String format){ // 배포 피드 만들기 SyndicationFeed feed = new SyndicationFeed(); // 피드에 항목 추가(생략됨) // 인수를 확인하고 올바른 형식으로 반환 if(format.ToLower() == "rss"){ return new Rss20FeedFormatter(feed); } return new Atom10FeedFormatter(feed); } }
결론
요약하자면, 지금까지 HTTP 전송에 대한 몇 가지 기본 사항, 이러한 기본 사항과 웹 원칙 간의 관계, WCF를 사용하여 이러한 원칙을 응용 프로그램에 적용하는 방법, 새로운 배포 API를 사용하여 RSS 및 ATOM 피드를 서비스하고 소비하는 방법 등을 살펴보았습니다. www.cloudsamples.net/pictureservices에서 PictureServices라는 샘플 응용 프로그램을 실행해 보면 이러한 새로운 기능이 실제로 어떻게 작동하는지 확인할 수 있습니다. 이 샘플을 온라인으로 실행하고 소스 코드를 탐색하고 전체 샘플을 다운로드할 수 있습니다. 그림 7은 작동 중인 PictureServices를 보여 줍니다.
.gif)
그림 7 The PictureServices Feed (더 크게 보려면 이미지를 클릭하십시오.)
간단히 말해, PictureServices는 로컬 컴퓨터 또는 Flickr 피드에서 사진을 검색할 수 있는 응용 프로그램입니다. 이 응용 프로그램은 단순한 공급자 모델을 사용하며, 현재 공급자는 Windows 데스크톱 검색, 파일 시스템의 폴더, 그리고 Flickr입니다. PictureServices는 공급자에서 파일을 검색하면 해당 사진을 배포하고 로컬로 서비스합니다. 사용자는 브라우저에서 피드를 클릭하고 개별 사진을 검색할 수 있습니다. 샘플에는 이 외에도 많은 내용이 포함되어 있으므로 잘 살펴보시기 바랍니다. 기사에 언급된 기술에 대한 자세한 내용은 이 기사의 "추가 리소스" 보충 기사를 참조하십시오.
Justin Smith는 Microsoft에서 웹 서비스 전문 기술 전도사로 일하고 있습니다. WCF 및 BizTalk 서비스가 전문 분야인 Justin은 Inside Windows Communication Foundation(Microsoft Press, 2007)의 저자이자 소프트웨어 개발 회의에 자주 서는 연설자이기도 합니다. 저자의 블로그 blogs.msdn.com/justinjsmith를 방문해 보십시오.
출처 : http://msdn.microsoft.com/ko-kr/magazine/cc135976.aspx
출처 : http://msdn.microsoft.com/ko-kr/magazine/cc135976.aspx