'개발/Communication'에 해당되는 글 11건

  1. 2011/01/19 매쉬업 인증, OAuth 사용하기 by dalbong2
  2. 2009/12/31 [메모] WCF 호출시 병목현상 관련 by dalbong2
  3. 2009/04/23 [연재 06] 서비스 컨트랙트 정의하기 by dalbong2
  4. 2009/04/23 [연재 05] WCF 관련 용어들 by dalbong2
  5. 2009/04/23 [연재 04] Hello world WCF 버전 3 by dalbong2
  6. 2009/04/23 [연재 03] Hello world WCF 버전 2 by dalbong2
  7. 2009/04/23 [연재 02] Hello world WCF 버전 1 by dalbong2
  8. 2009/04/23 [연재 01] WCF 연재를 시작하면서... by dalbong2
  9. 2009/04/23 Soap 익스텐션(SoapExtension)을 고한다. by dalbong2 (1)
  10. 2009/04/23 HTTP1.1 압축 이해하기 by dalbong2
  11. 2009/04/23 .NET Remoting 확장하기 by dalbong2
매쉬업 인증에 사용되는 OAuth( Open Authentication )에 대한 개념을 설명합니다.
OAuth
View more presentations from 인균 황.
저작자 표시
Posted by dalbong2
TAG mashup, oath

WCF 서비스를 호출할때, 클라이언트 수에 따라서 병목 현상이 일어날 수 있다. 이에 대한 이해 및 설정 내용을 다루는 포스트에 대한 링크들이다.

 

How to throttle a Wcf service, help prevent DoS attacks, and maintain Wcf scalability

 

Throttling in WCF  InstanceContextMode, ConcurrencyMode, and Server-side Threading

Posted by dalbong2

혹시 여러분은 Windows Live Writer라는 프로그램을 아시나요?  브라우저를 통해서 블로그에 직접 로그인하지 않고도 이 프로그램에서 포스트를 작성해서 바로 블로그로 글을 올릴 수 있습니다. 호오 정말 편합니다. 한번 이 프로그램을 검색해서 알아보세요. 마이크로소프트에서는 이 프로그램에 대한 SDK를 배포하고 있습니다. 직접 애플리케이션에서 이런 기능을 구현할 수 있다는 것이죠. 호오...지금 이 포스트도 이 프로그램으로 작성해서 올리고 있습니다.

서비스 컨트랙트를 정의한다는 것은 외부로 노출되는 전체 서비스에 대한 왁구(토목 현장에서 많이 쓰는 말이다 -_-;)를 만드는 일이라고 볼 수 있다. 메타 정의(?)라고나 할까. 구현(implementation)과는 구분되는 단계이다.  서비스 컨트랙트는 WCF에서는 ServiceContractAttribute로 정의되어 있다. ServiceContractAttribute는 전체 서비스를 정의하는 인터페이스(또는 클래스)에 붙어서 외부로 서비스가 가능한 타입임을 나타낸다.

서비스 컨트랙트는 다시 여러 하위 컨트랙트로 구성되어 진다.

하위컨트랙트     어트리뷰트정의
오퍼레이션컨트랙트     OperatinContractAttribute
데이터컨트랙트     DataContractAttribute
메세지컨트랙트     MessageContract

오퍼레이션 컨트랙트에서는 "메소드 호출과 관련"한 사항을 정의할 수 있다.  예를 들어 어떤 메세지 교환 방법(Message Exchange Pattern, MEP)을 사용할 것인가를 이곳에서 정의할 수 있다. WCF의 메세지 교환 방법에는 Request/Reply 패턴, OneWay 패턴, Duplex(two-way) 패턴등이 지원된다.

서비스 컨트랙트에는 Input, Output 파라미터나 리턴값에 대한 정의를 할 수 있는 데이터 컨트랙트를 표현할 수 있다. 앞에서 본 "Hello World, WCF 버전"에서는 리턴값으로 String 타입을 사용했다. 그러나 복잡하고 다양한 사용자 정의 타입의 객체를 리턴해 줄 수 있다. 클라이언트로 직렬화될때 객체의 특정 멤버만을 포함하도록 설정할 수도 있고, 직렬화 방법도 데이터 컨트랙트에서 지정할 수 있다.

데이터 교환은 SOAP 메세지를 통해서 교환된다. 즉 메세지의 헤더나 바디등에 데이터가 포함되어 오고가게 된다. 메세지를 통해서 데이터(파라미터, 리턴값)가 전달되는 모습을 그림을 그려보면 다음과 같을 것이다.
1060355043

대부분의 WCF 애플리케이션에서는 데이터의 구조나 직렬화 방법등이 이슈가 되지만 어떤 경우는 그 데이터를 포함하는 메세지 구조를 제어하는 것이 중요한 경우도 있다. 예를 들어 메세지 레벨에서의 보안 문제(Security issue)를 다룰려고 할 때는 파라미터나 리턴값을 직접 메세지로 직렬화하는 메세지 컨트랙트를 정의할 수 있다.

정의되어 있는 이런 컨트랙트를 이해하고 사용하는 방법을 하나씩 알아가는 것이 WCF를 이해하게 되는 것이 아닐까 싶다. 다음 포스트부터 본격적으로 이런 컨트랙트 관련 내용의 아티클을 번역해볼 려고 한다.

Posted by dalbong2

앞에서는 "Hello world WCF 버전"을 제작해 봄으로써 WCF 애플리케이션을 작성하는 단계를 하나씩 짚어봤다. 그 과정에서 나온 용어들을 몇개 정리해 보고자 한다.

  l      
엔드 포인트(endpoint)


엔드 포인트들은 메세지를 주고 받는 종점으로서 메세지 교환에 필요한 정보를 정의한다. WCF 서비스는 하나 또는 이상의 애플리케이션 엔드 포인트를 노출시킨다. 클라이언트는 서비스가 노출시킨 엔드 포인트와 상호작용할 수 있는 엔드 포인트를 사용해야 한다.


l       
바인딩(binding)

바인딩(binding) "엔드 포인트(endpoint)에 연결하는데 필요한 것들을 지정하기 위해서 사용되는 객체들"이라고 정의할 수 있겠다. 바인딩은 엔드 포인트가 어떻게 바깥 세계와 통신을 하는지를 정의한다.  바인딩을 구성하는 바인딩 요소(binding elements)라는 것이 있어서 여러 바인딩 요소들이 차례로 쌓여서 바인딩을 정의한다고 보면 된다. 예를 들어서 전송(transport, TCP or HTTP)를 정의하는 요소가 있고 인코딩 방식(텍스트 or 바이너리등)을 정의하는 요소가 있다. 그외 보안, 데이터 무결성 등을 결정하는 바인딩 요소들을 추가할 수 있다.

바인딩에 포함된 정보는 복잡하다. 그리고 어떤 요소들은 같이 사용될 수 없는 경우도 있다. 이런 이유로 해서 WCF에는 미리 정의된 바인딩(System-provided bindings)가 있다. 대부분의 애플리케이션에서는 이런 미리 정의된 바인딩을 사용해도 무리가 없을 것이다. 미리 정의된 것이 마음에 안들면 나름대로 정의할 수 있다는 말이기도 하다.

바인딩은 코드 또는 환경 설정을 통해서 정의되거나 설정될 수 있다. 만약 바인딩이 코드와 환경 설정을 이용하여 동시에 정의된다면, 코드에 의한 정의가 환경 설정 파일에 의해 설정된 내용을 오버라이트하게 된다.

WCF 서비스가 IIS의 호스팅을 받게 된다면 환경 설정 파일로 web.config를 사용하게 된다. 그리고 VS.NET을 사용하여 클라이언트 애플리케이션을 제작하는 경우는 익히 하는 대로 app.config를 이용하게 된다.


l       
서비스 컨트랙트

컨트랙트 하면 얼른 인터페이스가 떠오를 것이다. 맞다. 서비스 컨트랙트를 정의하면 이것은 인터페이스로 표현하게 된다( 클래스를 이용해서 서비스 컨트랙트를 표현해도 되지만 주로 인터페이스를 권장한다)
서비스 컨트랙트에서는 서비스의 요구 조건을 표시만 하고, 어떻게 그 조건이 충족되어야 하는지는 말하지 않는다.
서비스 요구 조건이라하면 다음과 같은 것들이 있을 수 있다. 예를 들어, 메세지 암호화 , 메세지 타입, 데이터 타입, 메세지 교환 패턴, 세션 지원등. 이런 요구을 구체적으로 어떻게 충족시켜야 하는지는 서비스의 구현 단계에서 환경 설정, 바인딩 설정을 통해서 표시하게 된다. 그리고 마지막으로 호스트 애플리케이션에서는 서비스의 환경설정이나 바인딩을 통해서 제시한 요구 조건을 지원할 수 있어야 한다.

예를 들어, 서비스 컨트랙트에서 세션을 지원할 필요가 있다는 것을 표시했다면, 그 서비스의 요구 조건을 충족시킬 수 있도록 바인딩을 설정해야 한다. 그렇지 않으면 서비스는 작동하지 않을 것이다. 만약 IIS를 호스팅 애플리케이션으로 사용하는 서비스가 윈도우 통합 인증(Windows Integratred Authentication)을 요구한다면, 서비스가 실행되는 웹 애플리케이션의 윈도우 통합 인증이 활성화되고 익명 액세스 가능 옵션이 언체크되어야 한다.

요약을 하면 다음과 같다.

1. 서비스 컨트랙트에서 요구 조건을 표시한다.

2. 환경설정과 바인딩을 통해서 요구 충족을 위한 구체적인 방법을 표시(또는 코딩)한다.

3. 호스팅 애플리케이션에서는 제시한 요구 조건에 대한 방법을 제공한다.


l       
데이터 컨트랙트

서비스 컨트랙트를 정의하는 것에는 서비스의 오퍼레이션의 파라미터값과 리턴값을 통해서 오가는 데이터 타입을 정의하는 것이 포함된다. 이런 타입에 대한 정의를 데이터 컨트랙트라고 한다. 오퍼레이션의 파라미터와 리턴값으로 사용된다는 것은 그 타입이 모두 직렬화가 가능해야 한다는 의미를 포함하고 있다. 즉 타입의 객체에서 바이트 스트림으로 그리고 바이트 스트림에서 다시 타입의 객체로 변환이 가능해야 한다는 것이다.

이 데이터 컨트랙트에 대한 내용이 다음 포스트 주제가 될 것이다.
Posted by dalbong2

4. WCF 클라이언트 프락시 클래스 및 config 파일 생성

WCF 서비스가 만들어졌으니 이제 Service Model Metadata Utility (Svcutil.exe)을 이용하면 앞에서 말한 것처럼 클라이언트측 프록시 클래스와 설정 파일을 만들수 있다. /config 스위치를 사용하면 생성되는 설정 파일의 이름을 지정할 수 있다.

먼저 서비스 프로그램을 실행시킨다.

그런 다음, VS.NET을 설치하면 함께 설치되는 명령 프롬프트에서 다음 명령을 실행시킨다.

svcutil /language:C# /config:app.config http://localhost/HelloService


<
그림5>

C 드라이브의 루트 폴더를 보면 프락시 클래스 파일과 환경 설정 파일이 생성되어 있을 것이다.


<
그림6>

프락시 클래스파일은 기본적으로 현재 서비스되고 있는 서비스명과 동일한 이름으로 생성된다.

using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService)))

필요하다면 /out 스위치를 사용해서 파일명을 변경할 수 있다. 클라이언트측 설정 파일을 보면 클라이언트에서필요한 바인딩 설정과 서비스 엔드 포인트에 대한 내용이 들어있다.

<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <system.serviceModel>

       <bindings>

           <wsHttpBinding>

               <binding name="WSHttpBinding_IHelloService" closeTimeout="00:01:00"

                  openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"

                   bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"

                   maxBufferPoolSize="524288" maxReceivedMessageSize="65536"

                   messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"

                   allowCookies="false">

                   <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"

                      maxBytesPerRead="4096" maxNameTableCharCount="16384" />

                   <reliableSession ordered="true" inactivityTimeout="00:10:00"

                       enabled="false" />

                   <security mode="Message">

                      <transport clientCredentialType="Windows" proxyCredentialType="None"

                           realm="" />

                       <message clientCredentialType="Windows" negotiateServiceCredential="true"

                           algorithmSuite="Default" establishSecurityContext="true" />

                   </security>

               </binding>

           </wsHttpBinding>

       </bindings>

       <client>

           <endpoint address="http://localhost/HelloService" binding="wsHttpBinding"

               bindingConfiguration="WSHttpBinding_IHelloService" contract="IHelloService"

               name="WSHttpBinding_IHelloService">

               <identity>

                   <userPrincipalName value="ighwang@lottenxg.com" />

              </identity>

           </endpoint>

       </client>

  </system.serviceModel>

</configuration>

5. WCF 프록시 파일 사용하기

다음은 앞에서 생성한 설정 파일과 프락시 클래스를 사용할 클라이언트 애플리케이션을 만든다.

컨솔용 프로젝트를 추가해서 그림처럼 앞에서 생성한 두 파일을 추가한다. 그리고 “HelloClient”라는 파일을 추가한다. System.ServiceModel.dll 에대한 참조도 추가한다.


<
그림7>

HelloClient.cs 파일에 다음 코드를 복사해 넣는다.

using System;

using System.ServiceModel;

namespace WCFClient

{

  class HelloClient

  {

       static void Main()

       {

           HelloServiceClient helloService = new HelloServiceClient();

           try

           {

               //서비스를 호출해서 값을 리턴받는다.

               string strHello = helloService.Hello();

               //출력

               Console.WriteLine(strHello );

               // 프락시의 Close()를 호출하면, 커넥션과 리소스를 우아하게 해제시킬 수 있다.

               helloService.Close();

           }

           catch (TimeoutException timeout)

           {

               Console.WriteLine(timeout.Message);

               Console.ReadLine();

               helloService.Abort();

          }

           catch (CommunicationException commProblem)

           {

               Console.WriteLine(commProblem.Message);

               Console.ReadLine();

               helloService.Abort();

           }

           Console.WriteLine("<ENTER>를 치면 종료됩니다.");

           Console.ReadLine();

       }

  }

}

코드는 단순하다. 서비스의 프락시 클래스에 대한 인스턴스를 생성해서 서비스의 Hello() 오퍼레이션을 호출해서문자열을 하나 리턴받고 바로 컨솔로 출력하고 있다.

서비스를 먼저 실행시키고, 클라이언트 애플리케이션도 실행시켜보자.


<
그림8>

썰렁한 결과가 출력된다.

6. 요약

지금까지의 단계를 잘 보면 Communication 컨셉에 있어서는 기존의 기술과 유사하다는 것을 알 수 있다. 앞으로는 다른 Communication 방식과 비교해서 WCF에서만 가지고 있는 특징들을 하나씩 이해해 나가는 과정만이 남아있을 것이다.
Posted by dalbong2

3.  WCF 서비스 구동하기

그림처럼 config 파일을 추가한다.


<
그림3>

추간된 config 파일에 다음 내용을 복사해 넣는다.

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<system.serviceModel>

  <services>

  <service

       name="WCFService.HelloService"

       behaviorConfiguration="HelloServiceBehavior">

     <host>

       <!-- 베이스 주소 http://localhost/HelloService로 엔드 포인트가 노출된다.  -->

       <baseAddresses>

         <add baseAddress="http://localhost/HelloService"/>

       </baseAddresses>

     </host>

    

     <endpoint address=""

               binding="wsHttpBinding"

               contract="WCFService.IHelloService" />

     <!-- mex 엔드 포인트는  http://localhost/HelloService/mex 로 노출된다.-->

     <endpoint address="mex"

               binding="mexHttpBinding"

               contract="IMetadataExchange" />

  </service>

  </services>

  <!--디버깅을 위해서, includeExceptionDetailInFaults 어트리뷰트를 true로 설정한다.-->

  <behaviors>

  <serviceBehaviors>

     <behavior name="HelloServiceBehavior">

       <serviceMetadata httpGetEnabled="True"/>

       <serviceDebug includeExceptionDetailInFaults="False" />

     </behavior>

  </serviceBehaviors>

  </behaviors>

</system.serviceModel>

</configuration>

config 파일에는 베이스 주소와 엔드 포인트를 설정하는 내용이 있다.

3.1 베이스 주소 설정하기

베이스 주소는 http://localhost/HelloService로 설정을 하고 있다. 클라이언트에서는 이 주소를 이용해서 서비스를 찾아오게 된다.

<baseAddresses>

         <add baseAddress="http://localhost/HelloService"/>

       </baseAddresses>

3.2 엔드 포인트 설정하기

엔드 포인트(endpoint)들은 메세지를 주고 받는 종점으로서 메세지 교환에 필요한 정보를 정의한다. WCF 서비스는 하나 또는 이상의 애플리케이션 엔드 포인트를 노출시킨다. 클라이언트에서는 서비스에서 노출시킨 엔드 포인트에 맞는 엔드 포인트를 만들어야 한다.

<endpoint address=""

               binding="wsHttpBinding"

               contract="WCFService.IHelloService" />

<endpoint>요소에서 binding 어트리뷰트값을 "wsHttpBinding"으로 설정하고 있는데, 이것은 엔드 포인트의 바인딩으로 시스템이 제공하는 WsHttpBinding을 사용하겠다는 것이다. 이 바인딩은 HTTP를 이용해서 전송한다. 바인딩과 더불어서 엔드 포인트 컨트랙스값으로 IHelloService를 지정하고 있고, address 어트리뷰트값으로 빈 문자열("")을 지정하고 있다. 최종 엔드 포인트의 주소는 앞에서 설정한 베이스 주소와 이곳에서 설정한 주소의 합으로 결정된다.  이 서비스는 상대 주소가 빈 문자열이므로 베이스 주소가 최종 엔드 포인트의 주소가 된다.
상대 주소가 "mex"로 되어 있는 엔드 포인트가 하나 더 설정되어 있다. 이 엔드 포인트는 최종 경로가 http://localhost/HelloService/mex로 노출된다.
.

<!-- mex 엔드 포인트는  http://localhost/HelloService/mex 로 노출된다.-->

     <endpoint address="mex"

               binding="mexHttpBinding"

               contract="IMetadataExchange" />

이 설정은 서비스에 대한 메타 데이터를 노출시키는 메터 데이터 교환(metada exchange, MEX) 엔드 포인트에 대한 것이다. 이 엔드 포인트를 이용하면 클라이언트에서 사용할 수 있는 프록시 클래스와 환경 설정 파일을 얻을 수 있다. 어떻게 이런 파일을 얻게 되는지는 다음 단계에서 보겠다.
3.3 컨솔 호스팅 프로그램 작성하기

다음으로는 서비스를 구동시킬 컨솔 프로그램을 하나 작성한다.
 

<그림4>

그림처럼 HostApplication.cs 파일을 하나 추가하고 다음 코드를 복사해 넣는다.

using System;

using System.Configuration;

using System.ServiceModel;

using System.ServiceModel.Activation;

using System.ServiceModel.Description;

using System.Diagnostics;

namespace WCFService

{

  class HostApplication

  {

       static void Main()

       {

           // 서비스 타입에 맞는 ServiceHost인스턴스를 생성한고, 베이스 주소를 제공한다.

           using (ServiceHost serviceHost = new ServiceHost(typeof(HelloService)))

           {

               try

               {

                   // ServiceHostBase를 오픈하면 리스너를 생성하고 메세지를 리스닝하기 시작한다.

                   serviceHost.Open();

                   // The service can now be accessed.

                   Console.WriteLine("서비스 작동중");

                   Console.WriteLine("서비스를 종료하려면 <ENTER>를 치세요.");

                   Console.WriteLine();

                   Console.ReadLine();

                   // 서비스를 닫기 위해서 ServiceHostBase를 닫는다.

                   serviceHost.Close();

               }

               catch (TimeoutException timeProblem)

               {

                   Console.WriteLine("서비스 오퍼레이션 타임 아웃 예외 " + timeProblem.Message);

               }

               catch (CommunicationException commProblem)

               {

                   Console.WriteLine("통신 문제가 있었습니다. " + commProblem.Message);

               }

           }          

       }   

  }

}

Posted by dalbong2

, 바로 샘플 얘기로 들어가자. WCF(Windows Communication Foundation)가 뭔지, 장점이 뭔지 하는 얘기는 MSDN 등 기타 사이트에 “WCF”를 키워드로 해서 검색을 해 보면 수두룩하게 쏟아져 나온다. 간단히 얘기하자면, .NET3.0에서의 새로운 Communication 프로그래밍 모델로서, 웹 서비스나 .NET 리모팅을 대신할 수 있는 기술이다.

어떤 통신 프로그래밍에서든지 Communication 기능을 작성하기 위해서 하는 공통된 절차가 있다. 초 간단하게 절차를 얘기하자면 다음과 같을 것이다. “서버 프로그램을 작성하고, 서비스를 제공할 수 있는 환경을 구성하고 그런 다음 그것을 인식할 수 있는 클라이언트 프로그램을 작성한다는 것이다.

“Hello world” WCF 버전을 만들어 봄으로써, 그 첫 경험을 시작해볼려고 한다. 먼저 WCF 서비스를 작성해서 활용하는 절차를 요약한다.(물론 Visual Studio.NET을 사용하면 훨씬 더 간단해진다. )

l        WCF 서비스 컨트랙트(Service Contract)[각주:1]용어정의 참조 : 서비스 컨트랙트'>정의하기  
 
-         WCF contract는 서비스에서 필요로 하는 타입과 메시지 패턴[각주:2]서비스 메소드를 호출하는 방식으로서, request-reply 방식 , one-way 방식, duplex callback 등이 있다. 이것에 대해서는 다음에 포스트를 올릴 기회가 있을 것이다. '>을 정의한다. 서비스 컨트랙트를 정의한다는 WCF 서비스를 설계하는 첫 단계가 된다.

l        WCF 서비스 컨트랙트 구현하기

-         서비스 컨트랙트가 정의되었으니, 다음은 그것을 구현하는 단계이다.

l        WCF 서비스 구동하기

-         서비스를 제공할 수 있게 되려면, 서비스를 생성하고 그 라이프 사이클을 제어할 수 있는 런타임 프로그램의 호스팅을 받고 환경 설정이 필요하다. 여기서는 컨솔 프로그램을 이용해서 서비스를 호스팅[각주:3]WCF 서비스를 호스팅하는 방법은 다양해졌다. IIS를 이용할 수도 있고, 윈도우 서비스를 프로그램을 제작해서 사용할 수도 있다. 이외에 새로운 방법으로 Self-Hosting 방법과 WAS(Windows Process Activation Service) 방법이 있다. 우리가 만들 예제에서는 Self-Hosting 방법을 이용해서 서비스를 호스팅하게 된다. 이런 호스팅 방법에 대해서도 다음에 정리할 수 있는 기회가 있을 것이다.'>하고 엔드 포인트(endpoint)[각주:4]용어정의 참조: endpint '>를 설정하는 방법을 알아볼 것이다.

l        WCF 클라이언트 프락시 클래스 및 config 파일 생성

-         자기 호스팅(self-hosted) WCF 서비스에서 WCF 클라이언트 프록시 클래스를 만들기 위해서 사용할 수 있는 메타데이터를 얻게 된다.

l        클라이언트용 config 설정 내용 리뷰

-         Config에 설정하는 항목들에대해서 리뷰하는 단계이다.

l        WCF 프록시 파일 사용하기

-         클라이언트 애플리케이션에서 프록시 클래스를 사용하는 코드를 본다.


다음 예제를 따라하기 위해서는 .NET 3.0이 설치되어 있어야 한다. PC 세팅에 대해서는 지난 포스트를 참조한다.

1. WCF 서비스 컨트랙트 정의하기

프로젝트 형식 : Visual C# -> 템플릿 : WCF Service Library 를 선택해서 새 프로젝트 추가한다.

<그림1>


<
그림2>

using System;

using System.ServiceModel;

namespace WCFService

{

  // Service Contralct 정의하기

  [ServiceContract(Namespace = "http://dalbong.ServiceModel.Samples")]

  public interface IHelloService

  {

       [OperationContract]

       string Hello();

  }

}

2.  WCF 서비스 컨트랙트 구현하기

using System;

using System.ServiceModel;

namespace WCFService

{

  // Service Contralct 정의하기

  [ServiceContract(Namespace = "http://dalbong.ServiceModel.Samples")]

  public interface IHelloService

  {

       [OperationContract]

       string Hello();

  }

  // Service Contract를 구현하는 서비스 클래스

  public class HelloService : IHelloService

  {

       public string Hello()

       {

           return "Hello World";

       }

  }

}


  1. '[본문으로]
  2. '[본문으로]
  3. '[본문으로]
  4. '[본문으로]
Posted by dalbong2

오랜만에 포스트를 올립니다. 이번에는 WCF( Windows Communication Foundation)에 대한 연재를 올려보려고 합니다. 달봉이도 지금 공부하고 있는 중이여서, 혹시나 틀린 부분이 있다면 코멘트 부탁드립니다. 이번 연재는 달봉이의 생각대로 재정리하는 것이 아니라 해외 아티클을 번역하는 방식으로 할 생각입니다. 나름대로 쉽게 배워갈 수 있는 순서와 절차에 입각해서 아티클을 배치하도록 하겠습니다. 그럼 시작하겠습니다.

다음 아티클들이 연재될 예정입니다. 그러나 지금 투입된 프로젝트 때문에 다 끝낼 수 있는 여력이 될 지 모르겠습니다.

WCF “Hello world”버전 만들기 (MSDN)


What You Need To Know About One-Way Calls, Callbacks, And Events

Juval Lowy

MSDN Magazine 2006. 10월호

Serialization in Windows Communication Foundation   

Aaron Skonnard

MSDN Magazine 2006. 8월호


Security in Windows Communication Foundation   

Keith Brown

MSDN Magazine 2006. 8월호


Discover Mighty Instance Management Techniques For Developing WCF Apps

Juval Lowy

MSDN Magazine 2006. 5월호


Harness The Power Of P2P Communication In Windows Vista And WCF

Justin Smith

MSDN Magazine 2006. 10월호


WCF
서비스 호스팅

Posted by dalbong2

클라이언트와 서버와의 통신에 웹 서비스를 사용하고 있는 스마트클라이언트 애플리케이션을 제작하면서 처음 Soap 익스텐션이라는 것을 알게 되었다. 이 녀석을 사용하면 개발자의 코드를 거의 수정없이 웹 서비스 기능을 추가, 확장활 수 있게 된다.  Soap 익스텐션은 클라이언트측에서는 웹 서비스에 대한 프락시 클래스의 메소드가 호출될때 그리고 서버측에서는 웹 서비스 메소드가 호출될때마다 활성화되어 추가적인 역할을 수행하게 된다. 웹 서비스에 대한 요청 또는 응답시 웹 서비스의 기능을 확장할 수 있는 수단이라는 점에서는  ASP.NET의 Http Handler, Http module과 유사한 개념이라고 볼 수 있다. 

Soap익스텐션을 사용할 수 있는 예로는 웹 서비스 호출 전 후에 로깅을 한다든지 또는 SOAP 메세지를 압축해서 전달한다든지 하는 작업들이 있을 수 있다.

■ SOAP의 XML모습

네트워크 선을 따라서 오고 가는 SOAP 요청/응답의 XML형태를 좀 자세히 들여다 보겠다. 예를 위해서 웹 서비스에서 "add"메소드를 하나 노출시키자. 두 정수를 받아서 합을 리턴하는 간단한 웹 서비스 메소드이다. :

[WebMethod]

public int add( int a, int b)

{

  return a + b;

}

클라이언트측의 웹 서비스 프락시가 add 메소드를 호출할때 실제로 서버로 보내지는 SOAP 요청 메세지를 다음과 같다:

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <soap:Body>

    <add xmlns="http://tempuri.org/">

      <a>10</a>

      <b>20</b>

    </add>

  </soap:Body>

</soap:Envelope>

이 요청에 대해서 서버는 다음과 같은 응답을 내려보낸다:

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <soap:Body>

    <addResponse xmlns="http://tempuri.org/">

      <addResult>30</addResult>

    </addResponse>

  </soap:Body>

</soap:Envelope>

■ 웹 서비스 라이프 사이클

SOAP 익스텐션을 사용하면 이런 SOAP 메시지의 헤더나 바디 부분을 적절한 순간에 가공할 수 있다. ASP.NET SOAP 익스텐션 프레임워크는 개발자들로 하여금 이런 순간들에 참여하여 SOAP 메세지를 가로채서 가공한 후 메세지를 이후의 전달 경로로 다시 전달할 수 있도록 적절한 기회와 API를 제공한다. SOAP 익스텐션 프레임워크를 통해서 개발자들은 객체로 역직렬화할때 접근할 수 있고 다시 그 객체를 SOAP 메세지로 직렬화할때도 참여할 수 있다.

이 포스트에서는 웹 서비스 호출시 그리고 응답을 받는 동안 개발자가 참여할 수 있는 단계들을 설명하고, 그리고 각 순간들 개발자가 접근할 수 있는 API와 인자들의 특징을 설명하고자 한다. 첫번째 주제는 많은 아티클들에서 설명하고 있다. 다음 그림은 MSDN에서 볼 수 있는 것으로 웹 서비스의 라이프 사이클과 그리고 메세지가 직렬화/역직렬화되는 각 단계를 보여주고 있다.

웹 서비스의 라이프 사이클 #1 - 개요 그림

메세지가 클라이언트측의 프락시를 떠나서 서버의 웹 서비스 메소드에 전달되기까지의 단계는 다음과 같다.

프락시의 호출 인자들 -> BeforeSerialize( at Client) -> AfterSerialize ( at Client ) -> SOAP 요청 메세지

----네트워크---->

SOAP 요청 메세지 -> BeforeDeserialize( at Server) -> AfterDeserialize( at Server)-> 메소드로 인자 전달

서버측에서 클라이언트로 메세지가 전달되기까지의 단계는 그 역으로 된다.

메소드의 리턴값 및 아웃 인자들-> BeforeDeserialize( at Server) -> AfterDeserialize( at Server )->SOAP 응답 메세지

----네트워크---->

SOAP 응답 메세지 -> BeforeDeserialize( at Client ) -> AfterDeserialize( at Client )->프락시의 리턴값

■ SoapExtension 클래스

개발자들이 네트워크로부터 들어오는 SOAP 메세지 스트림, 네트워크로 나가는 메세지 스트림에 각 단계별로 접근하고 싶다면 SoapExtension 클래스를 상속해서 구현해야 한다. 상속 클래스에서 구현할 필요가 있는 주요 메소드들로는 다음과 같은 것들이 있다: GetInitializer, ChainStream, Initialize, and ProcessMessage. 다음 그림은 클라이언트측과 서버측에서 메소드가 호출되는 순서를 잘 보여 주고 있다. 이 그림은  주목해서 이해할 필요가 있다.

웹 서비스의 라이프 사이클 #2 - 상세 이해용

GetInitializer, Initialize 메소드는 초기화(initialization)할 수 있는 기회를 제공한다. 초기화는 메소드가 호출될때마다 클라이언트측, 서버측에서 한번씩 수행할 수 있는 기회가 있다.  ChainStream 메소드는 SOAP 메소드를 호출하는 메세지, 결과로 반환되는 메세지에 해당하는 스트림을 캡쳐할 수 있는 기회를 준다. ProcessMessage는 개발자가 추가 작업을 할 수 있는 익스텐션의 핵심적인 부분이다.

■ 메세지 스트림 전달하기  

ChainStream 메소드를 오버라이딩함으로써 앞에서 말한것처럼 메세지 스트림이 전달되는 경로상에서 그 스트림을 가로챌 수 있는 기회를 제공해준다. 익스텐션이 설치되면 ASP.NET은 ChainStream 메소드를 호출해서 SOAP 메세지를 포함하고 있는 또는 포함하게 될 스트림에 대한 레퍼런스를 넘겨준다. 다음 코드는 대부분의 경우에 ChainStream에서 구현되는 전형적인 코드이다:

Stream oldStream;

Stream newStream;


public override Stream ChainStream(Stream stream)

{

  oldStream = stream;

  newStream = new MemoryStream();

  return newStream;

}

이 코드는 이전 단계에서 넘어온 메세지에 대한 스트림과 그 스트림을 가공할 수 있는 별도 공간의 스트림에 대한 레퍼런스를 로컬 변수에 저장해두고 있다. 인자로 넘어오는 stream이 이전 단계에서 건너오는 스트림이고, newStream이 인자로 넘어온 이전 스트림을 가공(지지고 볶고)할 수 있는 공간이다.

■ 메세지 처리하는 단계

SOAP 익스텐션에서 개발자가 참여하게 되는 것은 바로 오버라이딩된 ProcessMessage 메소드에서이다. ProcessMessage 메소드는 그림에서 보듯이 각 단계에서 여러번 호출된다.

// Process the SOAP Message

public override void ProcessMessage(SoapMessage message)

{

  // Check for the various SOAP Message Stages

  switch (message.Stage)

  {


  case SoapMessageStage.BeforeSerialize:

     BeforeSerialize(message);

    break;


  case SoapMessageStage.AfterSerialize:

     AfterSerialize(message);

    break;


  case SoapMessageStage.BeforeDeserialize:

     BeforeDeserialize(message);

    break;


  case SoapMessageStage.AfterDeserialize:

     AfterDeserialize(message);

    break;


  default:

    throw new Exception("invalid stage");

  }

SOAP 메세지의 단계에 따라 적절한 메소드를 실행시킨다. BeforeSerialize단계가 서버측에서도 발생하고 클라이언트에서도 발생하는데 어떤 쪽의 단계인지는 인자로 넘어오는 SoapMessage가 구체적으로 어떤 타입인지를 보면 알 수 있다.

private void BeforeSerialize(SoapMessage message)

{

  SoapClientMessage clientMessage = message as SoapClientMessage;

  SoapServerMessage serverMessage = message as SoapServerMessage;

  if (clientMessage != null)

  {

      BeforeSerializeAtClient(clientMessage);

  }

  if (serverMessage != null)

  {

      BeforeSerializeAtServer(serverMessage);

  }

}

다른 단계에서도 같은 방법으로 해서 서버측에서 발생하는 것인지 클라이언트에서 발생하는 것인지를 구분할 수 있다. 이렇게 직렬화/역직렬화단계의 before, after순간에 SOAP 메세지에 접근해서 수정을 할 수 있다는 것이다. 달봉이도 정말 그 수준까지만 알고서는 SOAP 익스텐션 제작을 쉽게만 생각했었다. 그런데 이런 일반적인 얘기 뒤에는 또다른 진실들이 있었다. 다음은 달봉이가 SOAP 익스텐션을 제작하면서 알게 된 사실들이다. 인터넷 어디가에 있을 지도 모르겠지만, 달봉이는 다음 사실들을 알아 내기 위해서 적잖은 시행착오를 겪어야만 했다.

■ 달봉이의 오해들

달봉이가 ChainStream과 관련해서 오해한 부분이 2 가지 있었다. 하나는 ChainStream이 언제 호출되는가였다. 직렬화와 역직렬화의 단계가 변화되는 때만 호출된다. 이 그림을 보기전에는 8개의 Before/After 이벤트가 발생할때마다 호출된다고 생각했었다. 이 오해로 인해 많은 시행 착오를 겪어야만 했었다. 달봉이의 두번째 오해는 로컬 변수로 레퍼런스를 저장해 놓고 있는 oldStream과 newStream에 대한 것이다. 앞의 그림에도 나오지 않은 중요한 내용이 있었던 것이다. 달봉이가 그것을 알기까지 참으로 많은 시행착오가 있었다. 중단점이 빼곡히 찍히 프로그램을 계속 반복해서 실행시켰다 종료시켰다 해야만 했었다. 그러면서 여러가지 상상을 해야만 했고 그런 다음 여러가지 추론을 이끌어 내서 가장 알맞은 시나리오를 만들어냈다. 그 시나리오는 아직까지도 잘 적용되고 있다. 달봉이는 이전 단계에서 넘어오는 스트림이 oldStream이였다면 새로운 단계로 넘어가는 스트림은 newStream이라고 생각했었다. 그래서 oldStream의 내용을 가공해서 newStream으로 채워야 한다고 이해했었다. 그러나 그렇게 생각하고 작성된 프로그램은 계속 예외를 뱉어 냈다.  많은 에러가 여러가지형태로 난다. 하나를 수정했다고 생각하면 다른 문제가 솟아나고. 근본적인 이해가 잘못되었던 것이다. 그러고 있는 도중에 다음과 같은 코드를 만나게 되었다. 인터넷에서 찾아낸 예제 중에서 클라이언트의 AfterSerialize단계에서 다음과 같은 코드가 있었다.

//이곳에서 먼저 newStream의 내용을 가공하는 작업을 했다.

//그런 다음 최종적으로 newStream의 내용을 oldStream으로 복사를 하고 AfterSerialize단계를 마쳤다.

Copy(newStream, oldStream);

Copy 메소드의 시그너쳐를 찾아 보니까 다음과 같았다.

void Copy(Stream from, Stream to)

클라이언트의 AfterSerialize단계를 마치고 나면 서버측으로 스트림이 전달된다. 그런데 스트림 가공후의 최종 결과를 oldStream으로 복사하는 것이다. 다시 말하면 서버로 전달되어야 하는 스트림이 oldStream이라는 말이다. 이게 무슨 말인가? 달봉이는 한참이나 고민했다. 분명 다음 단계로 전달되는 스트림은 newStream이라고 생각하고 있었다. 그래서 from, to에 해당하는 스트림의 위치를 다음처럼 바꿔봤다

Copy(oldStream, newStream)

에러였다. oldStream은 읽을 수가 없다는 것이다. 그래서 다음은 이 메소드를 주석처리해봤다.

//Copy(newStrream, oldStream);

또 에러였다. 그제서야 각각의 스트림에 대한 속성을 알아보기 시작했다. 그림을 보면 알 수 있듯이 클라이언트측에서 BeforeSerialize, AfterSerializ 단계 이전에 ChainStream 메소드가 한번 호출되는데, 이때 ChainStream 메소드로 넘어오는 stream 객체는 읽을 수가 없었고(CanRead=false) 대신에 쓸수만 있는(CanWrite=true) 스트림이었다. 이 스트림이 쓰기 전용이라는 것은 결국 newStream에서 작업한 스트림 내용을 oldStream으로 복사한다는 앞의 코드와 이전 스트림을 새로운 스트림으로 복사하는 코드에서 에러가 발생하는 이유를 알 수 있었다. 그러나 문제는 또 있었다. oldStream에서 읽을 수가 없다면 newStream에는 조작할 기존 데이터는 어떻게 구하는가였다. newStream에 기존의 내용을 부어줄 수 없다면 어떻게 BeforeSerialize, AfterSerialize단계에서 이전 내용을 가공해서 다음 단계로 넘겨줄 수 있는가이다. 인터넷에 있는 코드들을 보아도 클라이언트측의 BeforeSerialize, AfterSerialize의 어떤 코드에서도 newStream에 기존의 데이터를 채워주는 코드는 없었다. 그래서 추측을 했다. 개발자가 직접 newStream에 기존 메세지 내용을 채우지 않아도 ChainStream 메소드에서 리턴해준 스트림를 이용해서 웹 서비스 프레임워크가 채워주는 것은 아닐까? 만약 그렇다면 언제 newStream이 채워지는 것일까? 테스트 결과 첫번째 추측은 정말 맞았다. 즉 newStream에는 웹 서비스 익스텐션 프레임워크에 의해 자동으로 채워졌던 것이다.!. 그리고 채워지는 시기는 테스트결과 BeforeSerialize에서는 빈 스트림으로 있었고, AfterSerialize단계에서 기존의 메세지 내용으로 채워지는 것을 확인할 수 있었다. 이 사실을 추측할 수 있게 되기까지란 -_-;; 더불어 한 가지 더 알게 되었다. 클라이언트측의 BeforeSerialize단계에서는 ProcessMessage의 인자로 넘어오는 SoapMessage 타입의 message 객체를 통해서 메세지의 헤더값들을 변경할 수 있지만, 직렬화가 되고 나서의 AfterSerialzie 단계에서는 헤더값을 변경할 수 없었다.

클아이언트측의 ChainStream, BeforeSerialzie, AfterSerialize단계에서 일어나는 일들을 요약하면 다음과 같다.

▶ChainStream의 인자로 넘어오는 oldStream 객체는 쓰기전용의 빈 스트림이다.

▶ChainStream이 반환한 스트림객체 newStream에는 AfterSerialize단계 직전에 서버로 전달될 기존 메세지 내용이 채워지게 된다.

▶기존 메세지 내용을 변경하고 싶다면 newStream의 내용을 변경하고 그리고 최종 결과는 oldStream에 복사해 놓으면 된다.

▶AfterSerialize단계가 끝나고 나면 웹 서비스 익스텐션 프레임워크는 oldStream에 채워진 메세지 내용을 서버로 전달할 것이다.

▶직렬화전인 BeforeSerialize 단계에서는 message의 헤더 속성을 변경할 수 있다. 그러나 직렬화가 일어난 후에는 message 헤더를 변경할 수 없다.

지금까지가 클라이언트측에서의 직렬화단계의 메소드들에 대한 인자들에 대해서 알아 본 것이다. 서버측의 역직렬화 단계(Deserialize)에서는 반대로 전개된다. 바로 그 특징을 정리하면 다음과 같다.

▶ ChainStream의 인자로 넘어오는 oldStream에는 클라이언트에서 올라오는 메세지 내용이 이미 채워져서 올라온다.

개발자는 oldStream의 내용을 변경해서 그 변경된 내용을 newStream으로 복사해 놓는다.

AfterDeserialize단계가 끝나고 나면 웹 서비스 익스텐션 프레임워크는 newStream에 채워진 내용을 웹 메소드를 호출하는 곳에 사용하게 된다.

다음은 서버측의 웹 메소드가 호출되고 나서 그 결과를 다시 직렬화(Serialize)하는 단계에서의 특징들이다.

▶ 서버측의 Deserialize단계, 웹 메소드 호출 단계 그리고 반환값의 Serialize단계는 모두 하나의 익스텐션 인스턴스 내에서 일어난다. 무슨 말인가하면 만약 Deserialzie단계에서 클래스 전역 변수로 어떤 값을 저장해 뒀다면 그 값은 Serialize단계에서 접근할 수 있다는 것이다. 앞에서 보여준 두번째 그림을 보면 Deserialzie단계, Serialize단계가 하나의 박스로 묶여져 있다는 것은 그같은 사실을 표현한 것이다.

▶ 그러나 웹 서비스 메소드가 호출되고 나서 그 익스텐션 인스턴스의 ChainStream이 호출된다. 이 메소드에서는 익스텐션에 캐시되어 있는 oldStream과 newStream을 다시 생성하게 된다.

▶ BeforeSerialize단계에서는 oldStream과 newStream은 비어있게 된다.

▶AfterSerialize단계 직전에 프레임워크에 의해 클라이언트로 반환될 메세지 내용이 newStream에 채워진다.

▶newStream의 내용을 조작한 후 oldStream에 복사해 놓는다.

▶프레임워크는 AfterSerialize단계가 끝나고 나면 oldStream의 내용을 네트워크로 흘려보내게 된다.

▶클라이언트에서와 마찬가지로 BeforeSerialize단계에서는 ProcessMessage 메소드의 인자로 넘어온 SoapMessage 객체를 통해서 헤더 값을 변경할 수 있다. 그러나 AfterSerialize단계에서는 변경할 수 없다.

마지막으로 클라이언트측의 Deserialize단계의 내용을 보면 다음과 같다.

▶ 그림을 보면 ChainStream이 호출되는데, 이곳에서 읽기 전용의 oldStream과 쓰기 전용의 newStream이 생성된다.

▶oldStream에는 서버에서 내려온 응답 메세지 내용이 채워지게 된다. oldStream의 내용을 읽어와서 조작한 다음 newStream으로 복사해 놓는다.

▶ AfterSerialize단계까지 끝나고 나면 응답 메세지를 웹 서비스 호출 프락시로 건네주고 최종 클라이언트 프로그램으로 전달되게 된다.

휴우~~ 힘들었다. 어떻게 보면, 알고 나니까 당연한 사실처럼 여겨지지만 이 사실을 구체적으로 알려주는 곳을 찾지 못해서 아주 힘들었었다.

구체적인 샘플 코드들은 다음 문서들을 참고하기 바란다. 특히 아래의 Using SOAP Extension in ASP.NET문서를 잘 참고하길 바란다.

아들놈이 자꾸 옆구리를 찔러서 더이상 글을 진행하지 못하겠다.

야튼 남은 문제는 Soap익스텐션을 제작했으니 이제 이것을 어떻게 웹 서비스 및 클라이언트에 설치해야 할지를 알아야 할 것이다. 결론만 얘기하면 config 파일을 이용하는 방법이 있고, SOAP 익스텐션 어트리뷰트를 이용하는 방법을 이용할 수도 있다. 이 방법에 대해서는 아래 문서들을 보면 자세히 설명하고 있다.

■ 결론

웹 서비스에 대한 Soap 익스텐션을 사용하면 개발자 코드와는 상관없이, 웹 서비스 기능을 추가하거나 확장할 수 있다. 이 방법을 이용하면 여러 단계를 거치면서 SOAP 요청/응답을 중간에 가로채서 필요한대로 전처리, 후처리 하거나 또는 메세지 내용은 변경하지 않더라도 각 단계를 이용해서 로깅작업등을 할 수 있을 것이다.  그리고 마지막으로 짚고 가고 싶은 것은 Soap익스텐션은 서버측만 또는 클라이언트측만 또는 양쪽 모두에 설치될 수 있다는 것이다.

더이상 안되겠다. 아들놈이 계속 책을 덮쳐 오고 있다.


Creating Custom SOAP Extensions - Compression Extension

- http://www.mastercsharp.com/article.aspx?ArticleID...

압축 라이브러리

- http://icsharpcode.net/OpenSource/SharpZipLib/Defa...

Using SOAP Extensions in ASP.NET

- http://msdn.microsoft.com/msdnmag/issues/04/03/ASP...

SOAP Message Modification Using SOAP Extensions

- http://msdn2.microsoft.com/en-us/library/esw638yk....

  

Posted by dalbong2
■ 웹 어플리케이션 압축에 사용
ASP.NET2.0 어플리케이션을 개발할때 대용량 데이터에 대한 압축이 필요가 경우가 있다. 다음 링크는 이런 경우 참조할 수 있는 페이지이다.
Compression Support in ASP.NET2.0 (http://www.microsoft.com/belux/msdn/nl/community/columns/desmet/compression.mspx#Implementing%20a%20compression%20HttpModule)
압축은 IIS 웹 서버 설정을 통해서도 가능하지만 이렇게 하면 가상 디렉토리별로 압축 설정을 할 수 없다. IIS설정을 이용하면 해당 IIS에 설치된 전체 어플리케이션에 대해서 압축이 수행된다는 것이 단점이다.
디렉토리별로 압축이 가능하게 하려면 직접 압축 모듈을 작성해야 한다. 그러나 어렵지는 않다. HttpModule을 제작 방법을 이용하면 쉽게 압축 모듈을 추가할 수 있다. 이런 방식으로 작성한 압축 모듈은 클라이어언트 브라우저가 HTTP1.1을 지원하고 있어야 한다. 이런 자세한 이야기와 구현의 구체적인 방법은 링크 페이지를 보면 자세히 나와 있다.

■ 웹 서비스 압축에 사용
Web Service 어플리케이션에서 압축을 사용하려면 추가로 고려해야 하는 문제들이 있다. WSDL이 생성하는 프락시는 압축을 모른다는 것이다. 그래서 클라이언트가 압축 데이터를 받아들일 준비가 되었다는 적절한 헤더값을 서버로 보내지도 않고, 서버측으로부터 오는 압축 표시를 알아보지도 못한다는 것이다.  이런 문제들을 다음 링크 페이지에서 해결하고 있다.
Retrieving Data from Web Services using Standard HTTP 1.1 Compression
(http://dotnetjunkies.com/Tutorial/90D3B3E0-6544-4594-B3BA-E41D8F381324.dcik)

웹 서비스의 메세지 압축은 .NET 프레임워크에서 제공하는 압축 클래스와 SoapExtension을 이용해서도 간단히 구현할 수 있다. 이에 대해서는 추후 포스트가 있을 것이다.
Posted by dalbong2

.NET 커뮤니케이션 기술을 확장(Extension)하는 방법에 대해서 들어본 적이 있을 것입니다. 이런 확장하는 기술을 이용하면 공통되는 기능을 여러 개발자가 반복적으로 구현하지 않아도 됩니다. 또한 기존의 운용되고 있는 어플리케이션을 수정하지 않고도 그 서비스나 기능을 추가할 수도 있게 됩니다. 예를 들어 로깅, 압축, 암/복호화 같은 모듈을 작성하는데 이런 확장 기술을 이용할 수 있습니다. 이런 확장 기술은 새로운 기술은 아닙니다. .NET 프레임워크가 나오면서 이미 지원되었던 기술입니다.

ASP.NET에서는 HTTP 핸들러(HttpHandler) 또는 HTTP 모듈(HttpModule)을 이용해서 확장하는 방법을 아는 사람은 이미 알고 있을 것입니다. 그리고 ASP.NET 웹 서비스에서는 Soap 익스텐션을 이용해서 웹 서비스 기능을 확장하는 방법도 있습니다. Soap익스텐션을 이용해서 웹 서비스 기능을 확장하는 방법에 대해서는 지난 포스트(http://dalbong2.net/search/Soap%20Extension)를 통해서 알린적이 있습니다. .NETRemoting 을 이용해서 커뮤니케이션을 하는 어플리케이션에서도 클라이언트 또는 서버에 특정 모듈을 삽입해서 어플리케이션의 기능을 확장하는 방법이 있습니다. 

.NET Remoting 기술을 확장하는 예제도 직접 작성해서 함께 포스팅하고 싶었지만 요즘 시간도 없고 체력도 없어서 그냥 출처에 대한 정보만을 올립니다. 관심있는 분들은 직접 참조하시기 바랍니다. .NET Remoting 확장하는 것과 관련한 문서는 많이 있습니다. "Extend .NET Remoting"으로 구글링해보면 많은 정보를 볼 수 있습니다.

Extend .NET Remoting

-Randy Holloway

http://www.ftponline.com/vsm/2003_06/magazine/features/holloway/


그리고 2002년에 출판된 오래된(?) 책이기는 하지만 다음 책을 한 권 추천해 드립니다.

Essential .NET, Volume I: The Common Language Runtime (Microsoft .NET Development Series) (Paperback)
by Don Box (Author), Chris Sells (Author)

1343063943

.NET Remoting 기술을 확장하는 자세한 설명이 있습니다. 그리고 이 책은 .NET 프레임워크의 전반적인 설명이 탁월한 책입니다.

Posted by dalbong2