2009년 2월 21일 토요일

XML을 GridView에 binding하기

XML을 Datasource로서 GridView에 binding하기 위해서는 아래와 같은 방식으로 처리가 가능하다.


DataSet ds = new DataSet();


XmlTextReader xtr = new XmlTextReader(
xeItemRoot.ToString(), XmlNodeType.Element, new XmlParserContext(null, null, null, XmlSpace.None));

ds.ReadXml(xtr);
GridView1.DataSource =
ds.Tables[1];
GridView1.DataBind();

위에서 사용한 XmlTextReader 생성자의 첫번째 인자에는 잘 구성된 Xml의 Element node나 Document자체가
지정이 가능하며 이는 두번째 인자에서 type을 설정한다. 위와 같은 방법으로 간단하게 처리가 되나 Xml의 구조에
따라 dataset의 table이 생성되는 것이 다르므로 이에 유의 한다.
!지정되는 Element에 attribute가 있으면 해당 attribute만으로 table이 하나 생성된다. 이는 각자의 Xml을 가지고
직접 수행을 해보면 실제적으로 처리되는 내용을 쉽게 알 수 있을 것이다.


간단한 xml을 가지고 샘플 코드로 테스트 한 결과는 아래와 같다.

[샘플코드]
space.xml
------------------------------------------------------------------------------------------------------
XDocument xd = XDocument.Load("D:\\space.xml");

XElement xe1 = new XElement(xd.Root.Element("STARS"));
XElement xe2 = new XElement(xd.Root.Element("DETAILINFOS"));
XElement xe3 = new XElement(xd.Root.Element("PLANETS"));

XmlTextReader xtr1 = new XmlTextReader(xe1.ToString(), XmlNodeType.Element, new XmlParserContext(null, null, null, XmlSpace.None));
XmlTextReader xtr2 = new XmlTextReader(xe2.ToString(), XmlNodeType.Element, new XmlParserContext(null, null, null, XmlSpace.None));
XmlTextReader xtr3 = new XmlTextReader(xe3.ToString(), XmlNodeType.Element, new XmlParserContext(null, null, null, XmlSpace.None));

DataSet ds1 = new DataSet();
ds1.ReadXml(xtr1);
GridView1.DataSource = ds1.Tables[0];
GridView1.DataBind();

DataSet ds2 = new DataSet();
ds2.ReadXml(xtr2);
GridView2.DataSource = ds2.Tables[0];
GridView2.DataBind();

DataSet ds3 = new DataSet();
ds3.ReadXml(xtr3);
GridView3.DataSource = ds3.Tables[0];
GridView3.DataBind();
------------------------------------------------------------------------------------------------------

[결과표]

STAR_Text
Sun
Proxima Centauri
Rigil Kentaurus
Barnard's Star
Wolf 359
Sirius A and B
NAMEDISTANCEFROMTHESUNLENGTHOFYEARROTATIONPERIODVELOCITYDIAMETER
Earth49,600,000 km365.26 days23.93 hours29.79 km/sec12,756 km
Mars228,000,000 km687 days24 hr 37 min24.14 km/sec6,792 km
PLANET_IdNAME
0Mercury
1Venus
2Earth
3Mars
4Jupiter
5Saturn
6Uranus
7Neptune
8Pluto

출처 : http://dialup.egloos.com/1299482

2009년 2월 17일 화요일

Enterprise Library 어플리케이션 블럭 사용하기 - Caching

Using Caching Application Block

캐시 기능을 사용하는 목적은 주로 어플리케이션 실행 시간 동안 또는 주어진 시간 동안에 원하는 데이터를 로컬 컴퓨터에 보관하여 둠으로써, 추후 동일한 데이터가 필요할 시 캐시에서 바로 사용할 수 있도록 하여 데이터 조회에 필요한 성능을 아끼려는 것입니다.
또한 오프라인 기능 구현시에 이 캐싱 기능은 필수적입니다. 왜냐면, 오프라인 시에 어플리케이션 기능을 그대로 제공하기 위해서는 필요한 데이터를 모두 서버에 의존적으로 가져오거나 처리(수정/추가/삭제) 할 수 없고, 이를 위해서는 반드시 로컬 캐시에 작업을 위한 데이터와 작업된 데이터를 저장해 두어야 합니다.
가령 우리가 인사 어플리케이션을 개발한다고 가정하면, 사용자 등록시에 사용하는 많은 양의 부서코드 데이터가 존재하여 이 부서코드 중 하나를 선택한 후 사용자의 부서를 결정해야 한다고 합시다. 이 부서코드 데이터는 사용자 수정 시에도 사용되어 지고 또한 다른 인사 관련 작업 수행시에도 사용되어 집니다.
이 경우에, 부서코드 데이터를 로컬 캐시에 저장해 둔다면, 한번 데이터 조회 후 어플리케이션 실행 동안 또는 정해진 기간 동안 서버로부터의 추가적인 조회작업 없이 어플리케이션에서 바로 사용가능하게 됩니다. 물론, 캐시에서 사용하는 동안 이 부서코드 데이터에 대한 변경(추가/수정/삭제)이 일어나지 않는다는 가정하에 가능합니다.
이런식으로 캐시를 통해 작업하는 동안 이러한 캐시된 데이터의 변경이 일어날 수 있으므로 만료정책을 사용하여 캐시 내 데이터가 언제까지 유효한지를 지정하여 사용하는게 일반적입니다.
만일 메모리 상에 존재하는 캐시(in-memory)를 사용한다면, 이 캐시는(이 캐시 내의 데이터는) 해당 어플리케이션이 실행하는(메모리 상에 존재하는) 동안만, 유효한 것이므로 어플리케이션 종료와 동시에 소멸 됩니다.

Enterprise Library Caching Application Block(CAB)은 어플리케이션 내에 쉽게 로컬 캐시기능을 사용할 수 있게 해줍니다.
CAB는 in-memory 캐시와 영구적인 저장소로의 캐싱을 모두 지원하고 있습니다. 영구적인 저장소로는 Isolated Storage, Database를 지원합니다.
CAB를 사용하여 캐시에 데이터를 추가/삭제/조회하는 기능을 구현할 수 있으며 여러 다른 Application Blocks에서 캐싱 기능을 위해 CAB를 사용하고 있습니다.

CAB 사용을 위해서 구성을 생성합니다.
Enterprise Library Configuration을 사용해서 아래와 같이 구성합니다.
Caching Application Block을 추가합니다.




기본적으로 Cache Manager라는 이름의 캐시관리자 노드가 생성되어 집니다.
가장 하위의 캐시 관리자 노드를 선택한 후 적절하게 속성을 변경할 수 있습니다.

ExpirationPollFrequencyInSeconds : 캐시 내 캐시 항목(데이터)의 만료기간 확인 주기(초)
MaximumElementsCacheBeforeScanvenging : 캐시 항목 정리가 일어나기 전 최대 항목의수, 이 수에 도달하면 캐시 항목 정리(만료된 캐시 정리)가 일어납니다.
Name : 원하는 이름으로 변경하면 되고, 이 이름은 추후 어플리케이션 코드에서 로깅 기능을 호출할 때 사용할 이름
NumberToRemoveWhenScavenging : 캐시 정리가 일어나는 동안 삭제되어질 캐시 항목의 개수

기본값은, 60초마다 캐시정리가 일어나고, 최대 1000개 이상의 캐시 항목이 존재할 수 있으며, 그 이상 존재시에 캐시 정리가 일어납니다. 그리고 한번의 캐시 정리로 10개의 캐시 항목이 삭제되어 집니다.
일단 위 처럼 기본적인 CacheManager를 추가하게되면 이는 in-memory 캐시를 의미합니다.
여기서 데이터베이스 또는 Isolated Storage를 캐시 저장공간으로 사용하고자 하면,
아래 처럼 캐시관리자에 저장소를 추가해 주어야 합니다.




테스트로 Isolated Storage를 추가하고 Partition을 Sample Cache로 설정하였습니다.




Isolated Storage는 사용자 별 저장공간으로 사용될 수 있는 저장소로서 Smart Client 어플리케이션 개발시 사용자 측 영구적 저장 공간으로서 유용하게 사용됩니다.
이 Isolated Storage에 대해서는 추후 별도 글로서 소개할 예정입니다.
이 Isolated Storage를 사용하면 사용자별로 구분된 저장공간으로 활용할 수 있다고 이해하면 될 듯 합니다. 그 실제 위치는 아래와 같습니다.
C:\Documents and Settings\UserAccount\Local Settings\Application Data\IsolatedStorage



이 폴더 하위의 구조는 시스템이 알아서 하는 부분이므로 신경쓰지 않아도 될 듯합니다. 그러나 위의 Sample Cache라는 PartitionName을 지정하게 되면 사용자의 해당하는 Isolated Storage 하위에 실제 Sample Cache라는 이름의 별도의 폴더가 생성되어 져서 캐시 정보가 관리 됩니다. 이는 여러 어플리케이션이 아마도 Isolated Storage를 사용할 수 있으므로, 이들 간에 서로 사용하는 공간을 구분해서 관리하고자 하는 목적일 것입니다.

어플리케이션 작성 과정

Microsoft.Practices.EnterpriseLibrary.Common.dll,
Microsoft.Practices.EnterpriseLibrary.Caching.dll
어셈블리를 찹조 추가 합니다.

그리고 아래의 Using 문을 삽입합니다.(Optional)
using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;

그리고, CacheManager 객체를 생성하고 적절한 메서드를 호출하면 됩니다.

캐시에 항목 추가하기

만일 동일한 키의 캐시 항목이 존재하면 해당 항목이 삭제 된 후 추가됩니다.

//Default CacheManager 객체를 생성합니다.
//CacheManager 이름을 명시해서 생성할 수 있습니다.
//CacheManager productsCache = CacheFactory.GetCacheManager("Cache Manager");

CacheManager productsCache = CacheFactory.GetCacheManager();

string id = "ProductOneId";
string name = "ProductXYName";
int price = 50;

Product product = new Product(id, name, price);

productsCache.Add(product.ProductID, product, CacheItemPriority.Normal,
null, new SlidingTime(TimeSpan.FromMinutes(5)));

- CacheItemPriority 는 캐시 항목의 우선선위로서 캐시 정리 동안에 해당 항목의 우선순위 속성에 따라 어떤 항목이 먼저 정리가 될지 결정됩니다.
- new SlidingTime(TimeSpan.FromMinutes(5)) : 캐시 항목의 만료시간을 지정하는 것으로서 이 값은 SlidingTime 객체를 사용해서 마지막 접근 시점에서 5분 후에 만료토록 지정하는 것입니다.

- Add 메서드는 productsCache.Add(product.ProductID, product) 호출할 수 도 있는데 이렇게 추가하게되면 기본 Normal 우선순위와 "만료되지 않음" 값으로 추가되어집니다.

- 세번째 파라미터로서 null이 지정되어 있는데 이 파라미터는 캐시의 해당항목이 삭제될 때의 이벤트를 받을 수 있는 객체를 지정함으로써 사용자 액션을 추가할 수 있도록 합니다.

아래처럼 IcacheItemRefreshAction 인터페이스를 구현한 클래스를 정의하고

[Serializable]
public class ProductCacheRefreshAction : ICacheItemRefreshAction
{
public void Refresh(string key, object expiredValue, CacheItemRemovedReason removalReason)
{
// Item has been removed from cache. Perform desired actions here, based on
// the removal reason (for example, refresh the cache with the item).
}
}

아래처럼 호출을 하여 캐시 항목을 추가하게 되면,
productsCache.Add(product.ProductID, product, CacheItemPriority.Normal, new ProductCacheRefreshAction(), new SlidingTime(TimeSpan.FromMinutes(5)));

해당 캐시 항목 삭제 시에 위의 정의된 Refresh() 메서드 내에 정의된 코드가 실행되게 할 수 있습니다.

캐시 로딩하기

로딩 하는 방법은 Proactive, Reactive 이렇게 두가지 방식이 있고,
Proactive는 한번에 미리 로딩을 하는 방식이고, reactive는 필요시 마다 로딩 하는 방식입니다.
Reactive 방식의 경우 캐시 내에 해당 항목이 존재하는 지 확인 한 후에 추가해야 합니다.

public Product GetProductByID(string anID)
{
// This returns a product object with the specified ID.
}

public Product ReadProductByID(string productID)
{
CacheManager cache = CacheFactory.GetCacheManager();

Product product = (Product)cache.GetData(productID);

// Does our cache already have the requested object?
if (product == null)
{
// The requested object is not cached, so retrieve it from
// the data provider and cache it for further requests.
product = this.dataProvider.GetProductByID(productID);

if (product != null)
{
cache.Add(productID, product);
}
}
return product;
}



캐시 비우기

캐시 내의 모든 항목이 삭제됩니다.
CacheManager productsCache = CacheFactory.GetCacheManager();

// Operations on the cache
productsCache.Flush();

캐시 내 항목 삭제하기
캐시 내의 특정 항목만을 삭제 합니다.
public void Remove(CacheManager cache, string key)
{
cache.Remove(key);
}

캐시 내 항목 가져오기
// Read the item from the cache. If the item is not found
// in the cache, the return value will be null.
public Product GetProduct(CacheManager cache, string key)
{
return (Product)cache.GetData(key);
}

더 상세한 많은 부분은 위대한 "도움말" 님이 알고 있습니다.
끝.



출처 :
http://www.ensimple.net/enSimple/

2009년 2월 9일 월요일

Edit WCF Configuration

출처 : http://blog.naver.com/saeparam/90025219905

WCF 서비스 설정을 쉽게 하기 위해서 VisualStudio 에서는 WCF Configuration Editor를 제공한다.
서비스 설정정보를 작성할 web.config(IIS호스팅) 혹은 app.config(셀프 호스팅) 파일을 마우스 오른쪽 버튼으로 클릭 하면 메뉴에 Edit WCF Configuration 이란 메뉴가 나타난다.
 
1. Edit WCF Configuration 실행
 
 
아무런 설정 정보가 없을 경우 위와 같은 화면이 나타나며 이미 설정정보가 config 파일에 있을 경우 해당 정보가 위의 화면에 나타난다.
 
2. 오른쪽 패널의 Create a New Service 클릭
 
 
새로운 서비스를 만들기 위해서는 Create New Service를 선택하면 마법사가 실행되며 처음엔 위와 같은 서비스 타입을 넣으라는 창이 나타난다. 여기서 타입은 서비스를 구현한 클래스를 의미하는 것으로 직접 네임스페이스와 클래스 명을 입력해도 되지만 Browse 버튼을 통해 서비스가 구현된 클래스를 포함하는 어셈블리를 선택하면 선택된 어셈블리의 클래스가 아래와 같이 나타난다.
 
 
위와 같은 화면에서 서비스를 구현한 클래스를 더블클릭하면 처음 화면에 선택된 클래스의 네임스페이스와 클래스명이 나타난다.
 
3. Contract
 
 
Service Type에서 클래스를 선택하면 Contract 화면에서는 자동으로 선택된 서비스가 정의된 인터페이스명을 찾아서 보여준다. 만약 이전 창에서 클래스명을 직접 입력하였다면 이번 창에서도 해당 인터페이스명을 네임스페이스와 함께 기입하면 된다.
 
4. Communication Mode
 
 
다음은 WCF에서 제공할 수 있는 프로토콜을 선택한다.
 
5. Method
 
 
선택된 프로토콜에 추가적인 선택사항이 있다면 해당 내용을 선택하는 창이 나타나게 된다. 위의 화면은 HTTP 프로토콜을 선택했을 때 나타나는 화면으로 Basic Web Service 를 선택하면 basicHttpBinding 이,  Advanced Web Service 에서 Simplex는 wsHttpBinding 이 Duplex는 wsDualHttpBinding 이 선택되게 된다.
 
6. Address
 
 
주소를 넣는 창에 아무런 내용도 넣지 않고 Next를 누르게 되면 확인 메세지가 나타나게 된다. IIS 호스팅의 경우 IIS의 가상 주소로 호스팅 되므로 주소의 내용을 모두 지운다.
 
7. Finish
 
 
설정이 모두 마쳐지게 되면 마법사는 선택된 설정정보를 보여준다.
 
8. 마법사가 종료되면 WCF Configuration Editor에서 마법사에서 설정된 내용이 다음과 같이 나타나게 된다.
 
 
9. New Service Behavior Configuration
 
 
WSDL정보를 HTTP-GET으로 제공하기 위해서는 에디터의 왼쪽 트리중 Advanced > Service Behaviors 를 선택 한 후 오른쪽의 New Service Behavior Configuration 을 클릭한다.
 
10. Behavior 설정
 
 
새로 추가된 Behavior는 기본적으로 NewBehavior 라고 Name 항목에 설정되며 이 이름이 서비스에서 사용할 Behavior 를 선택하는데 사용되어진다.
 
11. Add
 
 
Add 버튼을 클릭하면 확장 가능한 기능들을 보여주는 창이 나타나며 메타정보를 http-get으로 제공하기 위해서는 serviceMetadata를 선택하고 Add 버튼을 누른다.
 
12. HttpGetEnabled
 
 
메타데이터에 대한 확장을 선택하면 위와 같은 옵션 사항이 나타고 이때 HttpGetEnabled를 True 로 설정한다.
 
13. BehaviorConfiguration
 
 
NewBehavior 로 지정된 Behavior를 서비스에 적용하기 위해서는 왼쪽 패널에서 생성된 서비스를 클릭한 후 오른쪽 패널의 BehaviorConfiguration 의 리스트에서 NewBehavior를 선택한다.
 
Editor를 종료하면 처음에 선택된 config 파일이 갱신되고 새롭게 추가된 서비스의 정보들이 config 파일에 포함된 것을 확인 할 수 있다.
 

[WCF Step by Step] 02. WCF 서비스 호스팅 - 윈도우즈 호스팅

WCF 서비스를 호스팅하는 방법은 3가지가 있다.
 
1. IIS 호스팅

   IIS로 호스팅 하기 위해서 WCF 프로젝트를 새 웹페이지의 WCF 서비스 템플릿을 사용해되 되지만

   Chapter01 예제처럼 WCF 서비스 라이브러리로 작성한 후 Service definition file(svc) 을 이용하여

   IIS 가상 디렉토리에 호스팅하는 방법이 있다.

 

   개인적인 취향이겠지만 WCF 서비스 라이브러리로 작성하는것이 좀더 유연하게 사용할 수 있다고 생각된다.

   라이브러리로 작성된 서비스는 IIS 호스팅뿐 아니라 Self 호스팅, 그리고 Windows Service 호스팅에 모두 같이 사용할 수 있고

   해당 라이브러리를 불러와서 간단한 실행 테스트 프로그램도 만들수 있기에 WCF 서비스 라이브러리로 만들기를

   적극 추천한다.

 

2. Self 호스팅
   Chapter02 에서와 같이 별도의 응용프로그램에서 호스팅하는 방법이다.
 
3. Windows Service 호스팅
   Self 호스팅이지만 호스팅 응용프로그램을 윈도우즈 서비스 프로그램으로 작성하여 호스팅하는 방법으로
   서비스에 등록하여 실행하므로 시스템이 재부팅시 자동으로 실행되는지 여부와 시작/종료를 서비스에서 관리할 수 있다.
 
 
* Windows Service Hosting Application
 
1. 솔루션 >> 추가 > 새 프로젝트 > Windows 서비스 선택한 후 프로젝트 이름은 WindowsProductsService 로 새로운 프로젝트를 Chapter02 솔루션에 추가한다.
 
 
 
2. Service1.cs 파일을 ServiceHostController.cs 파일로 이름을 바꾼다.
 
 
 
3. 참조 >> 참조 추가 를 선택하여 Chapter01 에서 만들었던 서비스 라이브러리(ProductsService.dll)와 System.ServiceModel 을 참조에 추가한다.
 
 
 
4. 이전 예제에서 작선한 ProductsServiceHost 프로젝트에 포함된 app.config 를 추가한다. 같은 솔루션으로 만들었다면 ProductsServiceHost 프로젝트의 app.config 파일을 드래그&드롭 으로 복사할 수 있다.
 
5. App.config 파일의 내용을 Enterprise Library 의 DB 접속 정보를 제외하고 이전 서비스 내용을 모두 지워 다음과 같이 수정한다.
 
 <configuration>
  <configSections>
    <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
  </configSections>
  <dataConfiguration defaultDatabase="AdventureWorksConnection" />
  <connectionStrings>
    <add name="AdventureWorksConnection" connectionString="Database=AdventureWorks;Server=(local)\SQLEXPRESS;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>
 
   이번 예제에서는 Config 파일에서가 아니라 프로그램에서 endpoint 를 추가하는 방법을 살펴볼 것이다.
 
 
6. ServiceHostController.cs 파일에 네임 스페이스를 추가한다.
 
using System.ServiceModel;
using Products;
 
 
7. 서비스에서 사용할 ServiceHost 를 선언한다.
 
private ServiceHost productsServiceHost;
 
8. ServiceHostController 클래스 생성자에 Windows Service 에 등록할 이름을을 Products Service 로 지정하고 서비스 관리 메뉴에서 서비스를 시작/종료 할 수 있도록 옵션을 설정하고 서비스의 동작을 윈도우즈 이벤트 로그에 남기도록 설정한다.
 

        public ServiceHostController()
        {
            InitializeComponent();

 

            this.ServiceName = "Products Service";
            this.CanStop = true;
            this.AutoLog = true;

        }

 
 
9. 서비스 시작시 ServiceHost 인스턴스를 생성하고 endpoint 를 추가한다.
 

        protected override void OnStart(string[] args)
        {
            productsServiceHost = new ServiceHost(typeof(ProductsServiceImpl));

 

            NetNamedPipeBinding binding = new NetNamedPipeBinding();
            productsServiceHost.AddServiceEndpoint(typeof(IProductsService), binding, "net.pipe://localhost/ProductsServicePipe");


            productsServiceHost.Open();
        }

 
   새로 추가한 endpoint 는 NetNamedPipeBinding 을 사용하였다. NetNamedPipeBinding은 같은 컴퓨에서 프로세스간 서비스를 제공할때 높은 성능을 보여주는 바인딩으로 네트워크를 통해서는 서비스에 접근할 수 없다. 주소는net.pipe://localhost/ProductsServicePipe 로 설정하였다. (WCF 바인딩 종류)
 
 
10. 서비스 종료를 작성한다.
 

        protected override void OnStop()

        {
            productsServiceHost.Close();

        }

 

 

11. ServiceHostController.cs 디자인 화면 >> 설치 관리자 추가 를 선택하면 ProjectInstaller.cs 파일이 생성되며serviceInstaller1serviceProcessInstaller1이 생성된다.

 

 

 

12. serviceInstaller1 의 ServiceName 속성을 ProductsService 로 수정하고 StartType 은 Automatic 으로 변경한다.

 

 

 

13. serviceProcessInstaller1 의 Account 속성을 LocalSystem 으로 수정한다.

 

 

 

14. 프로젝트를 빌드한다.

 

 

15. 시작 메뉴 > 모든 프로그램 > Microsoft Visual Studio 2005 > Visual Studio Tools > Visual Studio 2005 명령프롬프트 를 마우스 오른쪽 버튼으로 클릭하여 관리자 권한으로 실행한다. 서비스를 등록할 때에는 관리자 권한이 있어야 한다.

 

 

16. 명령 프롬프트에서 WindowsProductsService 프로젝트 폴더의 bin > debug 폴더로 이동하여 installutil 을 실행한다.

 

installutil windowsProductsService.exe

 

 
17. 내컴퓨터 >> 관리 > 서비스 및 응용프로그램 > 서비스 를 선택 한 후 오른쪽 패널의 리스트에서 ProductsService 서비스를 시작한다.
 
 
 
* Client 수정
 
1. NetNamedPipeBinding 을 Client 프로젝트의 app.config 에 다음과 같이 추가한다.
 

            <endpoint address="net.pipe://localhost/ProductsServicePipe"
                binding="netNamedPipeBinding" bindingConfiguration="" contract="ProductsClient.ProductsService.IProductsService"
                name="NetNamedPipeBinding_IProductsService" />

 
 
2. 프록시 클라이언트를 생성할때 NetNamedPipeBinding_IProductsService 를 지정한다.
 

ProductsServiceClient proxy = new ProductsServiceClient("NetNamedPipeBinding_IProductsService");

 
 
Windows Service 의 ProductsService 를 실행한 후 클라이언트 어플리케이션을 실행하면 결과를 확인 할 수 있다.
지금까지 WCF 서비스를 호스팅하는 방법과 다양한 Binding으로 endpoint 를 추가하여(app.config수정 혹은 AddServiceEndpoint 로 추가) 서비스를 제공하며 클라이언트에서 서비스를 호출하는 방법을 살펴보았다.

참조 : http://blog.naver.com/saeparam/90025529582