Pat Martin
Microsoft Corporation
2003년 5월
적용 대상:
Microsoft .NET Framework
Microsoft .NET Remoting
요약: 이 기사는 분산 다중 계층 응용 프로그램 설계의 일부로서 .NET Remoting 사용을 고려하는 사용자를 대상으로 합니다. RPC 기술의 장단점으로 인해 편리함과 동시에 다소 불편함을 겪었던 개발자의 관점에서 이 기술의 성능을 설명하겠습니다. 독자가 .NET Remoting에 대한 실제 사용법은 아니더라도 개념적으로는 알고 있는 것으로 가정합니다.
제품 기능 절은 가능하면 Remoting을 사용해 무언가를 설계하려는 사람에게 유용합니다. 최적의 사용 절은 Remoting을 사용해 무언가를 작성하려는 사람에게 유용합니다. Remoting 및 웹 서비스 절에서는 어떤 기술을 언제 사용할지에 대한 일부 혼란을 없애 줍니다. 요약 내용에서는 전체 내용을 간략히 요약합니다.
목차
개요
제품 기능
최적의 Remoting 사용
Remoting 및 ASP.NET 웹 서비스
요약 내용
추가 리소스
개요
.NET Remoting은 응용 프로그램 도메인 간에 RPC를 관리하기 위해 선택된 기술로 설명되어 왔습니다. 응용 프로그램 도메인은 공용 언어 런타임의 독립적인 단위입니다. 도메인은 프로세스 내에서 만들어지고 실행됩니다. 이는 CLR과 비CLR 관리 프로세스의 프로세스 간 통신(Interop)과는 차이가 있습니다. 이러한 RPC 통신의 최근 유형은 특히 “웹” 상에서 웹 서비스의 도메인(일반적인 용어를 사용할 경우)처럼 보입니다. 아쉽게도 겉보기에 분명한 이런 차이점은 기사 An Introduction to Microsoft .NET Remoting Framework 에서 다음과 같이 언급되었듯이 IIS에서 .Net Remoting 서버가 호스팅될 수 있기 때문에 명확하게 구별되지 않습니다.
".NET Remoting objects can be exposed as a Web Service by hosting them in IIS..."
일부 Microsoft 고객에게는 .NET Remoting과 관련해 다소 혼란이 있을 수 있습니다. 흔히 받는 질문은 "언제 Remoting을 사용해야 합니까?", "Remoting이 언제 NTLM을 지원할 것입니까?", "어떻게 원격 대화를 확보할 수 있습니까?", "COM+은 어떻습니까?", "Remoting이 어떻게 트랜잭션을 관리합니까?" 등입니다.
이 기사에서는 이런 질문에 대한 대답과 더불어 최적의 .NET Remoting 사용법을 설명하고 현재 제공되는 기능에 대한 개요를 제공합니다. 요약 내용에서는 특별히 웹 서비스 및 새로 등장하고 있는 GXA(글로벌 XML 웹 서비스) 사양과 관련해 이 기술의 향후 비전을 제시합니다 .
제품 기능 절은 주로 TechED N.Z. 2002에 소개된 정보로부터 발췌했습니다. 이 프레젠테이션에서는 분산 솔루션에서 Remoting을 사용할 수 있는 여러 가지 방법을 강조하고 Remoting의 장단점에 대해 소개되었습니다.
최적의 사용 절은 다중 계층 .NET 응용 프로그램을 사용하는 동안 개인적으로 경험한 내용을 토대로 하고 있습니다. 개발하는 동안 간단하면서도 최적의 사용법을 여러 가지 찾아냈으며 이를 여기에 나열했습니다.
일부 절에 있는 자료는 Microsoft 내에서 이 기술과 그 발전에 대해 잘 이해하고 있는 사람들과 나눈 비공식 대화를 토대로 하고 있습니다. 여기 제시된 정보는 향후 제품 출시 계획이나 일정과는 관계가 없습니다.
제품 기능
이 절에서는 .NET Remoting이 제공하는 제품의 기능과 특징을 설명합니다.
클라이언트/서버 통신
.NET Remoting은 응용 프로그램 도메인에서 동기 및 비동기식 RPC 대화를 모두 관리하는 효과적인 방법을 제공합니다. 원격 개체 코드는 서버 활성 개체와 클라이언트 활성화 개체 모두의 경우에서와 같이 서버에서 실행되거나 원격 개체가 클라이언트/서버 연결을 통해 일련화된 클라이언트에서 실행됩니다. 어느 경우에도 간단한 초기화 과정과 구성이 완료되고 나면 프로그래밍 구문은 매우 단순하며 이를 위해 작성해야 할 코드량도 매우 적습니다. 원격 개체(참조에 의해 마샬링된 프록시)의 사용은 프로그래머에게 분명합니다. 예를 들어 초기 Windows RPC 메커니즘에서는 IDL 도구를 사용한 정교한 유형과 마샬링 지식을 요구하였고 RPC 클라이언트 및 서버의 스텁 관리를 개발자에게 부담시켰습니다. Remoting은 .NET에서 RPC를 훨씬 잘 제공하며 흔히 쉽게 이해되는 .NET 데이터 유형을 사용하면 초기 RPC 메커니즘에 존재했던 자료형 불일치 위험을 없애줍니다.
Remoting은 기본적으로 XML 인코딩 SOAP나 원시 이진 메시지 형식으로 HTTP나 TCP 프로토콜을 사용해 통신하도록 구성할 수 있습니다. 사용자 지정 프로토콜(채널)이나 메시지 형식(포맷터)은 개발자가 작성할 수 있으며 필요한 경우 Remoting 프레임워크에 의해 사용될 수 있습니다. 통신 프로토콜 선택과 마찬가지로 서버나 클라이언트 구성 요소 모두에서 포트를 선택할 수 있습니다. 여기서 큰 장점은 기본적인 통신을 연결하고 실행하는 것이 매우 쉽다는 것입니다.
하지만 상태 관리와 관련해 통신 유형을 선택해야 합니다. 이 절의 나머지 부분에서는 Remoting이 제공하는 여러 가지 선택 가능한 통신 및 이와 관련한 설계 정보를 설명합니다.
서버 활성 개체
서버 활성 개체는 서버에 의해 수명이 조절되는 개체입니다. 이 개체는 클라이언트가 개체의 메서드를 최초로 호출하는 경우 필요할 때에만 서버에 의해 만들어집니다. 서버 활성 개체는 기본 생성자만 지원합니다. 매개 변수화된 생성자를 가지고 원격 개체를 사용하려면 클라이언트 활성화 또는 동적 게시(아래 참조)를 사용하면 됩니다. 서버 활성 개체는 해당 위치(URL)가 미리 게시되어 알려지므로 잘 알려진 개체 유형으로도 간주됩니다. 서버 활성 개체를 위한 활성화 모드로 Singleton과 SingleCall 두 가지가 있으며 아래에서 설명됩니다. 서버로 활성화된 유형의 인스턴스를 만들려면 응용 프로그램을 프로그래밍 방식이나 정적 구성을 통해 구성하면 됩니다. 서버 활성화 구성은 매우 단순합니다. 예를 들어 다음 코드는
<service> <wellknown mode="SingleCall" type="Hello.HelloService, Hello" objectUri="HelloService.soap" /> </service>
SingleCall로 설정된 활성화 모드를 사용한 서버로 활성화된(잘 알려진) 유형을 기술하고 있습니다. 서버로 활성화되는 Remoting 구성에 대한 자세한 내용은 MSDN에서 .Net Framework Developer's Guide 'Server-Side Registration'을 참조하십시오.
Singleton
이런 개체는 어떤 시점에도 메모리에 둘 이상의 인스턴스가 없으며 모든 클라이언트를 해당 인스턴스가 처리한다는 점에서 기본 Singleton 설계 패턴을 따릅니다. 그러나 이러한 유형은 유형에 따른 기본 수명을 가집니다. 아래에 나오는 개체 수명 관리 절을 참조하십시오. 즉 클라이언트가 원격 클래스의 같은 인스턴스에 대한 참조를 항상 받는 것은 아닙니다. 이 사실은 상태 관리에 대해 흥미로운 정보를 부여하는 것으로서 Remoting 패턴이 고전적인 Singleton 모델(똑같이 하려면 개체 ID가 필요)의 어디로부터 갈라져 나왔는지를 밝혀 줍니다. 설계에서 고전적인 Singleton의 상태 관리 패턴을 필요로 하는 경우 두 가지 문제 해결 방법이 있습니다. 한 가지 방법은 호스트 응용 프로그램 도메인이 실행되는 한 개체가 메모리에 보관되도록 기본적인 개체 임대 동작을 다시 정의하는 것입니다. 다음 코드는 이러한 방법을 보여 줍니다.
public class MyClass : MarshalByRefObject { public override Object InitializeLifetimeService() { return null; } }
언급했던 대로 이 메커니즘은 개체를 메모리에 묶어 두어 개체가 재사용되지 못하게 하지만 이는 호스트 응용 프로그램이 실행되는 동안만 가능합니다. IIS 호스팅을 위해 IIS 또는 Remoting 세션을 호스팅하는 IIS 프로세스가 재활용될 경우(여러 가지 이유로 발생 가능) 개체는 소멸됩니다.
Remoting을 가지고 스레드에 안전한 Singleton 상태 데이터에 완전히 의존하려면 다음 세 가지를 수행해야 합니다.
- 위에서 설명한 대로 임대가 무제한인 임대 메커니즘으로 다시 정의합니다.
- 수명에 대해서 전적으로 통제할 수 있는 시스템 서비스처럼 자체 내부 프로세스 안에서 원격 서버를 호스트하십시오. 이 프로세스도 재활용될 수 있지만 재활용되고 있는 IIS 작업자 프로세스보다 좀 더 확연한 동작이라 발견될 확률이 높습니다. 이 메커니즘에 대한 자세한 내용은 아래에서 제품 기능 절을 참조하십시오.
- 클라이언트로부터의 동시 요청을 처리하기 위해 다중 스레드가 사용될 것이므로 스레드에 안전한 원격 서버를 개발하십시오. 이렇게 하면 공유 리소스에 대한 동시 쓰기를 관리하며 일반적으로 정적 메모리에 대한 공유 액세스를 처리할 수 있습니다.
SingleCall
SingleCall 원격 서버 유형은 항상 클라이언트 요청당 하나의 인스턴스를 가집니다. 다음의 메서드 호출에 대해서는 다른 인스턴스가 처리합니다. 설계 면에서 SingleCall 유형이 제공하는 기능은 매우 단순합니다. 이 메커니즘을 사용할 경우 상태 관리는 제공되지 않으므로 상태 관리를 필요로 할 경우에는 나쁘겠지만 필요로 하지 않을 경우에는 이상적입니다. 이 모드에서는 요청당 정확히 하나의 인스턴스만 얻으므로 상태보다는 로드 균형과 가용성만 중요할 경우 이를 선택하는 것이 좋습니다. 개발자가 원할 경우 SingleCall 개체에 대해 자신이 고안한 상태 관리를 제공할 수 있지만 새 개체의 식별 정보가 각각의 새 메서드 호출로 인스턴스를 생성하므로 이 상태 데이터는 개체 내에 상주하지 않습니다.
동적 게시
서버 활성화 방법에서 마지막으로 살펴볼 유형은 동적 게시입니다. 이 서버 활성화 유형은 프로그래밍 방식의 게시 메커니즘을 제공함으로써 개체 생성에 대한 보다 강력한 제어를 할 수 있습니다. 특정 개체를 특정 URL에 게시할 수 있으며 옵션으로 매개 변수화된 생성자를 사용할 수 있습니다. 구조적으로 동적 게시는 서버로 활성화되는 Singleton 유형이 다소 변형된 것이라고 볼 수 있습니다. 동적 게시 에 대한 정보는 .NET Framework Developer's Guide에서 찾을 수 있습니다.
클라이언트 활성화 개체
클라이언트 활성화 개체는 클라이언트가 new 또는 Activator.CreateInstance()를 호출할 때 만들어집니다. 클라이언트는 수명 임대 시스템을 사용하여 이러한 인스턴스의 수명에 관여할 수 있습니다. 이 활성화 메커니즘은 설계 유연성 면에서 최고입니다. 클라이언트가 개체를 활성화하려면 클라이언트 활성화를 사용해 활성화 요청을 서버로 보냅니다. 이 메커니즘을 사용하면 매개 변수화된 생성자와 고유한 클라이언트당 연결 상태 관리를 모두 사용할 수 있습니다. 클라이언트 활성화를 사용해 각 클라이언트는 자체의 특정 서버 인스턴스로 처리되며 이는 다중 호출에 대해 개체 상태를 절약하게 해 줍니다. 하지만 분산 처리되고 있다는 것과 개체가 실제로 외부 프로세스에서 실행될 뿐만 아니라 다중 계층 응용 프로그램의 경우 외부 시스템에서 실행된다는 것을 잊기 쉬우므로 이러한 개체 사용에 신중해야 하며 인터넷을 통해 속성을 설정하지 않는 것이 좋습니다. 여기서는 chatty 인터페이스보다는 chunky 인터페이스가 기준입니다. 성능을 위해서는 높은 응집성/낮은 결합도를 포기해야 할 수도 있습니다. 클라이언트로 활성화되는 유형의 인스턴스를 만들려면 응용 프로그램을 프로그래밍 방식으로 구성하거나 정적 구성을 사용하면 됩니다. 서버에서의 클라이언트 활성화 구성은 꽤 단순합니다. 예를 들어 다음 코드는
<service> <activated type="Hello.HelloService, Hello" objectUri="HelloService.soap" /> </service>
ClientActivated 유형을 기술하고 있습니다. 클라이언트로 활성화되는 유형에서는 유형 자체만으로도 활성화가 가능하므로 더 이상 URL이 필요하지 않습니다. 또한 wellknown 태그 대신 activated 태그가 사용되었습니다. 클라이언트로 활성화되는 Remoting 구성에 대한 자세한 내용은 MSDN에서 .Net Framework Developer's Guide 'Registering Remote Objects Using Configuration Files'를 참조하십시오.
확장성
원격 메서드 호출을 처리하는 동안 .NET Remoting은 포맷된 “메시지”를 Remoting “채널”을 통해 클라이언트로부터 서버로 보냅니다. 메시지 형식과 채널은 완벽한 확장성과 사용자 지정 기능을 가집니다. 기본 채널이나 포맷터를 사용자 지정으로 제작된 구성 요소로 교체할 수 있습니다. 메시지가 통과되는 동안 다양한 “싱크 지점”에서 인터셉트되거나 변경될 수 있어 메시지의 사용자 지정이 가능합니다. 사용자 지정 메커니즘은 .NET Framework 개발자 가이드(싱크 및 싱크 체인)에 설명되어 있으며 이미 인터넷에 수많은 사용자 지정 채널과 포맷터가 등장하고 있습니다(예: 명명된 파이프 채널 구현). 이런 확장성은 대체로 흥미를 끌지 못하는데 왜냐하면 이 기술로 제공되는 기본 포맷터와 채널이 이미 가장 넓은 범위(특히 SOAP 메시지 포맷터를 사용하는 TCP와 HTTP)를 목표로 하고 있기 때문입니다. 그러나 다양한 솔루션을 고려하게 되는 설계 초기 단계에서는 이러한 특징을 기억해 볼 만 합니다.
예외 전파
.NET Remoting은 Remoting 전체에 걸쳐 예외 전파를 지원합니다. 이는, 예를 들어 DCOM에서와 비교했을 때 오류 코드 사용에 대한 주요한 개선 사항입니다.
Remoting 예외에서 예외 클래스를 순차 가능화하고 ISerializable 인터페이스를 구현하는 것은 좋은 방법입니다. 이렇게 하면 예외가 Remoting 영역에 걸쳐 올바르게 일련화되며 생성하는 동안 사용자 지정 데이터가 예외에 추가됩니다. 원격화되고 일관성 있게 사용되어야 하는 예외를 위해 자체 예외 클래스를 정의하는 것이 좋습니다. 모든 예외는 이런 식으로 Catch되고 올바르게 전파되어야 하며 처리되지 않은 예외를 Remoting 영역에서 허용하면 안 됩니다.
개체 수명 관리
.NET Remoting은 원격 개체의 수명을 관리하기 위한 풍부한 메커니즘을 제공합니다. 서버 개체가 어떠한 상태도 대기시키지 않을 경우, 예를 들어 SingleCall 개체의 경우처럼 이 프로세스에 대해서는 염려할 필요가 없습니다. Remoting 인프라가 작업하는 대로 그냥 두면 개체는 필요할 때 가비지로 수집됩니다. 서버 활성화 Singletons든 클라이언트 활성화 개체든 상태를 대기시키면 수명 관리 프로세스, 즉 개체 임대에 관여해야 할 수도 있습니다. 이미 최소로만 관여하면 되는 단순하고 유용한 방법 한 가지를 살펴보았는데 이는 위 Singletons 설명에서와 같이 InitializeLifetimeService 메서드를 다시 정의하는 것입니다. 이렇게 하면 개체를 호스트하는 프로세스가 실행되는 동안에는 개체를 보유할 수 있습니다. 개체 수명 프로세스는 어떻게 작동할까요?
개체 관리를 위해 Remoting이 제공하는 메커니즘은 임대 원리를 기반으로 하고 있습니다. 개체를 소유하지는 못하지만 값을 치르는 동안에는 계속 사용할 수 있습니다. 이 프로세스는 나중에 자세히 설명하겠습니다. 우선 COM에서 개체 정리를 어떻게 처리하는지 잠시 설명하겠습니다. DCOM은 개체가 여전히 실행 중인지를 확인하기 위해 Ping과 참조 계수 메서드를 결합해 사용합니다. 둘 다 오류가 발생하기 쉬우며 네트워크 대역폭에 의존적입니다. 참조 계수의 전체 원리는 매우 이해하기 어려우며 제대로 사용한 경우에도 불안정합니다. 참조 계수로 작업하기 위해 적용해야 할 간단한 규칙이 여러 가지 있었으며 현재도 많습니다. COM 개체를 위한 IUnknown 인터페이스에는 AddRef와 Release 메서드가 포함되며 개발자는 이를 적절한 때에 호출해 주어야 합니다. 때로 프로그래머가 이를 잘못 처리해 개체가 제거되지 않고 관련 메모리가 누수되기도 합니다.
반면 Remoting의 임대 기반 수명 관리 시스템은 임대 개체, 스폰서, 임대 관리자를 결합하여 사용합니다. 응용 프로그램 도메인은 각기 임대 관리자를 포함하고 있어 Singleton 또는 클라이언트로 활성화된 각 개체를 위한 임대 개체 참조를 도메인 내에서 대기시킵니다. 각 임대는 0 이상의 관련 스폰서를 가지며 임대 관리자가 임대가 만료된 것을 확인할 경우 임대를 갱신할 수 있습니다. 이 임대 기능은 ILease 인터페이스를 통해 Remoting 인프라가 제공하며 이미 살펴본 InitializeLifetimeService 호출을 통해 얻습니다. ILease 인터페이스는 개체 수명을 관리하는 데 사용되는 수많은 속성을 정의합니다.
- InitialLeaseTime. 임대가 처음 얼마 동안 유효한지를 결정합니다.
- RenewOnCallTime. 각 메서드 호출 후 임대는 이 시간 단위에서 갱신됩니다.
- SponsorshipTimeout. 스폰서의 임대 만료 알림 후 Remoting이 기다리는 시간입니다.
- CurrentLeaseTime. 임대가 만료될 때까지의 시간입니다(읽기 전용).
임대가 만료되면 임대 관리자는 임대 스폰서에게 임대를 갱신할지를 묻습니다. 원하는 스폰서가 없을 경우에는 관련 개체 참조가 해제됩니다.
스폰서는 원격 개체에 대한 임대를 갱신할 수 있는 개체입니다. 스폰서가 되려면 클래스는 MarshalByRefObject로부터 파생되어야 하며 ISponsor 인터페이스를 구현해야 합니다. 임대 하나가 여러 스폰서를 가질 수 있습니다.
이러한 임대 관리 메커니즘은 인터페이스에 대한 프로그래밍 방식과 관련해 .NET Framework Developer's Guide의 수명 임대 에 설명되어 있으므로 여기서는 다루지 않습니다. 그러나 참고할 만한 것은 상태를 가지는 원격 개체의 수명 관리를 위해 이렇게 풍부한 메커니즘이 존재한다는 것입니다. 위에서 언급했던 대로 임대 메커니즘을 완전히 무시하거나 프로세스 컨테이너가 실행되는 동안 메모리에 개체를 대기시키기 위해 사용하거나 본격적으로 사용할 수 있습니다.
원격 서버 호스팅
.NET 원격 서버를 호스트하는 데에는 여러 가지 방법이 있는데 크게 두 개의 항목으로 나누어 볼 수 있으며 다음과 같습니다.
ASP.NET에서의 IIS 호스팅
사용 가능한 표준 기능으로 IIS에서 원격 서버 쪽의 개체를 호스트하는 기능이 있습니다. 이는 보안 및 스케일 가능에 대한 지원 등을 포함해 많은 장점을 제공합니다.
IIS에서 개체를 호스트하려면 다음을 수행하십시오.
- 원격 클래스를 개발하여 MarshalByRefObject로부터 상속받습니다. 또는 클래스를 순차 가능하도록 선언합니다.
- IIS 관리자를 사용하여 가상 웹 응용 프로그램을 만듭니다.
- 클래스를 포함한 어셈블리를 가상 웹 응용 프로그램의 하위 폴더 bin으로 복사합니다.
- Remoting 서버의 구성 정의를 대기시키기 위해 web.config 파일을 만들어 이를 웹 응용 프로그램의 가상 루트에 넣습니다.
이로써 작업이 완료됩니다. 그러나 숙지해야 할 몇 가지 제약이 있습니다.
- IIS 호스팅에 대한 응용 프로그램 이름을 지정할 수 없습니다. 가상 응용 프로그램 이름이 됩니다.
- httpchannel을 사용해야 합니다.
- Remoting 클라이언트가 웹 응용 프로그램이기도 한 경우 시작하는 동안 RemotingConfiguration.Configure를 호출해야 합니다. 이것은 보통 Global.asax 파일의 Application_Start 메서드에 포함시킵니다. <client> 태그를 사용해 클라이언트 웹 응용 프로그램을 자동으로 구성할 수 없습니다.
- IIS가 포트 할당을 담당하므로 포트를 지정하지 마십시오. 필요한 경우 가상 응용 프로그램을 위한 포트를 지정하기 위해 IIS 관리자를 사용할 수도 있습니다.
Remoting 응용 프로그램 도메인은 Aspnet_wp.exe 작업자 프로세스 내에서 호스트되며 기본으로 해당 프로세스의 존재를 가정합니다.
참고 현재 ASP.NET에 버그가 하나 있는데 Aspnet_wp.exe 작업자 프로세스의 프로세스 식별 정보를 "시스템"이나 로컬 컴퓨터 계정으로 설정해야 합니다. 기본 설정인 machine.config 내의 "machine"이 올바르게 구성되지 않아 IIS의 도메인 컨트롤러에서 호스트될 경우 ASP.NET 응용 프로그램이 오류 500, "내부 서버 오류"로 인해 실패합니다. 이 버그와 관련해 컴퓨터 계정을 올바르게 구성하는 방법에 대한 설명서가 부족한 게 사실입니다.
IIS에서 호스트할 경우 여러 가지 기능상의 혜택, 즉 스케일 가능, 스레딩, 감사, 인증 및 보안 통신 기능이 기본으로 제공됩니다. ASP.NET 작업자 프로세스는 항상 실행되며 machine.config 내의 <processModel> 요소를 사용한 스레드 및 폴트 관리와 관련한 미세 조정으로부터 영향을 받습니다. 요컨대 IIS에서 사용 가능한 장점과 기능은 원격 서버에 개방되어 있습니다.
하지만 단점도 많습니다. TCP보다 느린 HTTP를 사용해야 합니다. 또한 IIS는 Singleton 상태를 파괴하는 ASP.NET 작업자 프로세스를 순환할 수도 있습니다. 클라이언트의 다음 호출이 Singleton을 다시 시작하게 하므로 이 점은 설계 요구에 따라 문제가 될 수도 있고 안 될 수도 있습니다. 작업자 프로세스를 재활용하지 않게 IIS를 구성할 수 있지만 이 기능은 특히 IIS 5에서는 제한적이라 결국 광범위에 영향을 미칠 수도 있습니다. 요컨대 원격 서버의 보안이 필요한 경우에는 IIS 호스팅이 확실한 방법이라는 것입니다. 성능은 시스템 테스트/사용 중 실제로 문제가 발생하는 경우에만 문제가 되며 또한 이 문제는 하드웨어 상에서 반드시 해결 방법을 찾을 수 있습니다.
IIS의 인증 고려 사항
인증 옵션
.NET Remoting은 자체의 보안 모델이 없습니다. 인증 및 권한은 채널과 호스트 프로세스, 이 경우 IIS에 의해서 수행됩니다. Remoting을 위해 Windows 인증이 지원되며 <authentication mode="Windows"/>를 설정함으로써 web.config 내에서 구성됩니다. Remoting 클라이언트는 쿠키에 액세스할 수 없고 로그온 페이지에 리디렉션될 수 없으므로 폼(Forms)이나 Passport 인증을 지원하지 않습니다. 원격 서버는 비대화형 사용을 위해 설계되었습니다.
원격 개체에 자격 증명 전달
ASP.NET 작업자 프로세스 내에서 원격 개체가 호스트되고 Windows 인증을 위해 구성되고 나면 채널의 자격 증명 속성을 사용해 사용할 자격 증명을 지정해야 합니다. 이렇게 하지 않을 경우 자격 증명 전달 없이 원격 호출이 만들어집니다. 그 결과로 종종 http에 대한 액세스가 거부됩니다. 원격 개체 프록시(Remoting 클라이언트 프로세스)를 호스트하는 프로세스 자격 증명을 사용하려면 채널의 자격 증명 속성을 프로세스 자격 증명 캐시로 관리되는 DefaultCredentials로 설정하십시오. 이는 웹 클라이언트용 채널 요소, 즉 <channel ref="http" useDefaultCredentials="true"/> 사용하여 선언적으로 하거나 다음 코드를 사용하여 프로그램 방식으로 할 수도 있습니다.
IDictionary channelProperties; channelProperties = ChannelServices.GetChannelSinkProperties(proxy); channelProperties["credentials"] = CredentialCache.DefaultCredentials;
특정 자격 증명을 원격 개체 호출과 함께 전달하려면 기본 자격 증명, 즉 <channel ref="http" useDefaultCredentials="false"/> 설정을 사용 안 함으로 구성하고 다음 코드를 사용하십시오.
IDictionary channelProperties = ChannelServices.GetChannelSinkProperties(proxy); NetworkCredential credentials; credentials = new NetworkCredential("username", "password", "domain"); ObjRef objectReference = RemotingServices.Marshal(proxy); Uri objectUri = new Uri(objectReference.URI); CredentialCache credCache = new CredentialCache(); // "authenticationType"를 "Negotiate", "Basic", "Digest", // "Kerberos" 또는 "NTLM"로 대체하십시오. credCache.Add(objectUri, "authenticationType", credentials); channelProperties["credentials"] = credCache; channelProperties["preauthenticate"] = true;
참고 위와 같이 preauthenticate 속성을 TRUE로 설정하면 WWW-Authenticate 헤더가 초기 요청과 함께 전달됩니다. 이렇게 하면 웹 서버가 원래의 요청에 대한 액세스 거부를 중단하고 후속 요청에서 인증을 수행합니다.
IIS 외부에서 호스팅
IIS 외부에서 원격 호스팅을 하는 데에는 많은 옵션이 있습니다. 이러한 옵션은 다음과 같습니다.
콘솔 응용 프로그램 내에서 호스팅
개발자는 Remoting 인프라를 시작한 다음 “중단하지 않고 계속 작동하는” 콘솔 응용 프로그램을 작성할 수 있습니다. 이렇게 중단하지 않고 계속 작동하는 이유는 여기에 응용 프로그램 도메인이 들어 있어서 원격 호출을 호스트하기 때문입니다. 작성하기는 매우 쉽습니다. 원격 호스트 구성 파일 이름을 전달하면서 RemotingConfiguration.Configure 메서드를 호출한 다음 키 누르기나 특정 메시지 수신과 같은 이벤트가 프로세스를 제거하게 할 때까지 기다립니다.
이 방법은 중간 계층에서 IIS를 필요로 하지 않는다는 장점이 있지만 아직 프로덕션용으로는 준비되지 않았으며 데모, 개발, 테스트에 유용합니다. 즉 유용하지만 사용 범위가 매우 제한적입니다.GUI 응용 프로그램 내에서 호스팅
개발자는 Remoting 인프라를 시작한 다음 “물고 있는” Windows GUI 응용 프로그램을 작성할 수도 있습니다. 실행을 계속해야 하는 유일한 이유는 여기에 응용 프로그램 도메인이 들어 있어서 원격 호출을 호스트하기 때문입니다. 여기에서의 개발 방법은 콘솔 응용 프로그램 사용입니다. Remoting 호스트는 직접 시작하거나 사용자 조작으로 시작할 수 있습니다. 이 방법 역시 중간 계층에서 IIS를 필요로 하지 않는다는 장점이 있으며 데모와 테스트에 유용합니다. 이것의 변형은 채팅 유형의 응용 프로그램 같은 피어-투-피어(논리적으로) winforms 응용 프로그램입니다. 이것 역시 사용이 제한적입니다.
시스템 서비스 내에서 호스팅
시스템 서비스 개념 자체 만큼 Remoting 인프라가 기능을 제공하지 못한다는 점에서 이 가능성은 좀 더 흥미로워집니다. 시스템 서비스는 컴퓨터가 시작될 때 시작되어 중단하라고 할 때까지 계속되게 구성할 수 있으며 이 점이 원격 호스팅에 있어서 이상적입니다. IIS 응용 프로그램도 가상 응용 프로그램에 대해 “높은 고립 모드”를 설정함으로써 유사하게 작동하도록 구성할 수 있습니다. 이 기사에서 다룬 내용 외에도 이와 관련한 정보가 매우 많습니다. 고객들은 이 메커니즘에 대해 그 유용성을 의심하는 질문들을 해 왔습니다. 먼저 장점을 몇 가지 살펴보겠습니다. 서비스 자체의 장점에 대해서는 이미 언급했습니다. 또한 호스트 프로세스의 활성화에 대해 완벽히 통제할 수 있습니다. 예를 들어 동적 게시나 클라이언트 활성화를 사용하도록 선택할 수 있습니다. 사용자 프로필을 로드할 수 있고 이진 인코딩 메시지를 가지고 TCP를 통해 높은 성능을 얻을 수 있으므로 IIS가 필요하지 않습니다.
하지만 단점도 꽤 많습니다. 우선 필요할 경우 자신의 인증과 인증 메커니즘을 작성해야 합니다.
시스템 서비스 역시 Remoting 서버와 같이 유용하려면 스케일이 가능하고 재입력이 가능해야 하는데 이러한 기능은 다중 계층 분산 응용 프로그램에서 필요합니다. 예를 들어 IIS가 없다면 호스팅 서비스에서 자체 감사와 인증을 관리해야 하지만 IIS에서는 둘 다 표준으로 제공됩니다.
이러한 이유로 인해 시스템 서비스 호스팅 장치는 한 번 교환을 하기 위해 메시지가 대기열에 있거나, 보안 문제가 없거나, TCP를 통해 IPSec이 사용 가능한 환경 등과 같이 제한된 환경에서만 사용할 수 있습니다.
엔터프라이즈 서비스 관리
원격 구성 요소가 COM+ 환경에 참여하고 COM+ 컨텍스트에서 실행하려면 ServicedComponent로부터 상속받아야 합니다. System.EnterpriseServices 네임스페이스에 제공된 다른 기능과 함께 ServicedComponent는 CLR 구성 요소가 지시하는 트랜잭션 요구 사항 및 서버 프로세스 실행 속성 등 여러 COM+ 속성을 지정할 수 있게 합니다. 강력한 명명 및 regsvcs 명령 사용과 더불어 원격 구성 요소는 일반적인 COM+ 환경의 일부가 될 수 있습니다.
원격 구성 요소가 MarshalByRefObject로부터 상속받아야 하고 COM+ 구성 요소가 ServicedComponent 로부터 상속받아야 한다면 그리고 .NET 관리 코드에 다중 상속이 없다면 어떻게 하면 될까요? 다행히 ServicedComponent는 ContextBoundObject로부터 파생되며 이는 필요한 MarshalByRefObject로부터 파생됩니다. Remoting 위에 바로 COM+ 통합을 작성할 수 있으며 이로써 개체 풀링, 분산 트랜잭션 지원, 역할 기반 보안과 같은 엔터프라이즈 서비스가 제공하는 혜택을 제공해 줍니다. 그런데 이를 수행하는 방법과 향후 점검과 관련해 이런 방법이 구조적으로 이루어지는 방법에 대한 예가 빠졌습니다.
COM+ 컨텍스트 인프라와 Remoting 컨텍스트 인프라가 시간이 지나면서 유사해질 것이라는 예측이 맞을 것입니다. 정확히 언제 어떻게 이렇게 될지는 현재 확실하지 않습니다.
최적의 Remoting 사용
늘 그렇듯이 분산 구성 요소를 개발하고 테스트하는 데에는 프로젝트 비용과 개발자의 노고가 필요합니다. 다음 지침에서는 이러한 노력을 통해 얻은 정보를 제공합니다.
시작하기
기사 Basic Remoting Task List 에서는 Remoting을 처음 설정할 때 수행해야 하는 작업의 검사 목록을 잘 제시해 줍니다. 프로세스를 진행할 때 위 기사를 참고 자료로 사용하면 좋습니다. 다음은 수행해야 하는 단계를 간단히 요약한 것입니다.
호스트 작업
- 응용 프로그램 도메인, 활성화 모델, 채널, 포트 및 게시를 선택하여 서비스를 설계합니다.
- 호스트 응용 프로그램 도메인을 구성합니다(예: IIS / 시스템 서비스).
- 호스트 활성화, 채널 및 프로토콜 설정을 구성합니다. RemotingConfiguration.Configure를 호출하여 로드한 구성 파일을 사용하는 것이 좋습니다.
- 클라이언트가 사용하도록 인터페이스를 게시합니다. 자세한 내용은 아래에서 '인터페이스 게시 옵션' 절을 참조하십시오.
클라이언트 작업
- 응용 프로그램 도메인과 활성화 모드를 선택하여 클라이언트를 설계합니다.
- 채널과 포트의 등록 여부를 고려합니다.
- 원격 유형 메타데이터를 얻습니다.
- 클라이언트 응용 프로그램 도메인을 구현합니다.
- 클라이언트 활성화 모드와 더불어 응용 프로그램 이름, 채널 및 개체 URI와 같은 기타 유형 정보를 구성합니다. RemotingConfiguration.Configure를 호출하여 로드한 구성 파일을 사용하는 것이 좋습니다.
포맷 옵션
Remoting은 표준 방법으로 HTTP 채널에서 SOAP나 Binary 포맷터를 사용하거나 TCP 채널에서 Binary 포맷터를 사용하도록 구성할 수 있습니다. 이 구성은 일반적으로 클라이언트 구성 파일에서 적절한 항목을 만드는 것과 정적 RemotingConfiguration.Configure 메서드를 호출하는 것으로부터 영향을 받습니다.
예를 들어 HTTP에서 Binary 포맷터를 사용하기 위해 Remoting 연결을 구성하려면 다음과 같이 구성 항목을 만들어야 합니다.
<channel ref="http" useDefaultCredentials="true" port="0"> <clientProviders> <formatter ref="binary"/> </clientProviders> </channel>
여기서 "channel ref"는 HTTP 프로토콜을 식별하고 "formatter ref"는 채널(이 경우는 이진 채널)을 통해 보내는 메시지 형식을 식별합니다.
아쉽게도 개발 중 HTTP 채널에서 Binary 포맷터를 사용하면 서버에서 발생한 오류가 잘못 전달되어 예기치 못한 문제를 일으킵니다. 예를 들어 일반적인 서버 오류나 액세스 위반은 둘 다 클라이언트에 잘못 보고됩니다. 이는 Binary 포맷터를 사용하는 클라이언트 쪽 Remoting 구성 요소가 이진 형식의 메시지 반환을 기대하기 때문입니다. 일반 텍스트 오류 결과는 올바르게 해석되지 않으며 다음과 같이 보고됩니다.
처리되지 않은 예외 유형 'System.Runtime.Serialization. SerializationException'이 mscorlib.dll에서 발생했습니다. 추가 정보: BinaryFormatter 버전 비호환성. 예상 버전 1.0. 받은 버전 1008738336.1684104552.
이 오류는 대부분의 경우 버전 비호환성 때문이 아니라 클라이언트 쪽에서 텍스트 오류 응답을 분석하는 능력이 없기 때문에 발생합니다. 이 프로토콜 결함은 제품의 향후 버전에서 해결될 것으로 기대되며 개발 중에는 SOAP 포맷터를 사용할 것을 강력히 추천합니다. 성능에 유리한 것으로 입증이 되면 포맷터가 binary로 전환될 수도 있지만 이는 성능이 반드시 필요하고 성능 혜택이 큰 경우에만 해당될 것입니다.
인터페이스 게시 옵션
Remoting 서버를 설계해 작성하고 나면 클라이언트가 컴파일 시에 참조를 확인하고 동적 프록시 개체를 만드는 데 사용할 수 있도록 서버가 제공하는 인터페이스를 게시해야 합니다. 이를 위한 방법에는 여러 가지가 있습니다. 여기서 다루어야 할 내용은 많지만 몇 가지만 먼저 설명하겠습니다.
- 정적 필드와 메서드는 원격화되지 않으며 .NET Remoting은 항상 일부 형식의 인스턴스 구성원만 처리합니다.
- 개인 메서드 / 유형은 원격화되지 않습니다.
- MarshalByRef 유형은 참조에 의해 원격화되며 순차 가능한 유형은 값이 복사되고 코드는 클라이언트 프로세스에서 실행됩니다.
- Equals, GetHashCode, MemberwiseClone 등과 같은 개체의 가상 메서드는 로컬에서 실행됩니다.
이러한 설계상의 유의 사항과 함께 Remoting 서버가 내보낼 인터페이스 게시 옵션은 다음과 같습니다.
- 클라이언트가 컴파일 시 사용하도록 서버 쪽 어셈블리를 제공합니다. 클라이언트에서는 구현이 아닌 인터페이스만 필요하므로 이렇게까지 할 필요가 없으며 권장하지 않습니다.
- Remoting 서버는 웹 서비스로서 가능하지만 SOAP / HTTP 클라이언트용 Remoting 서버는 서버 개체와 해당 메서드를 기술하는 WSDL(Web Services Description Language) 파일을 제공할 수 있습니다. .NET Framework SDK와 함께 제공되는 SOAPSUDS 유틸리티는 메타데이터 역할을 할 WSDL 파일 생성에 사용될 수 있습니다. Remoting 인터페이스용 WSDL이 웹 서비스의 WSDL과 완벽히 호환되지 않으므로 이 방법은 Remoting보다는 즉, 엄격히 말하면 asmx 측면에서 웹 서비스에 적합합니다. .NET Framework Tools 문서의 Soapsuds Tool
에서 Soapsuds 유틸리티에 대해 자세히 설명합니다.
- 인터페이스를 별도 라이브러리에 선언하고 이 라이브러리를 클라이언트에 배포합니다. 인터페이스를 구현하는 서버 클래스를 게시하면 클라이언트는 이를 사용해 구현하는 인터페이스에 대한 프록시를 얻을 수 있습니다. 이는 구체적인 인터페이스로서 명확한 설계를 위한 지침이 되므로 매우 중요합니다. 이 방법에서는 인터페이스의 인스턴스를 만들 수 없으므로 서버 활성 개체를 위해서만 사용될 수 있습니다(제품 기능 절 참조).
- 클라이언트를 위해 메타데이터 역할을 하도록 SOAPSUDS를 사용해 대리 클래스를 작성합니다. Remoting 서버 어셈블리에 대해 SOAPSUDS를 실행할 수 있으며 메타데이터로서 즉시 사용이 가능한 출력 어셈블리나 응용 프로그램에 즉시 포함이 가능한 원본 파일을 생성할 수 있습니다. 이 메커니즘은 하나의 계층 안에 있는 개체가 다른 계층에 있는 원격 개체에 액세스하기를 원하는 다중 계층 응용 프로그램 작성에 유용합니다. 이는 매우 흥미로운 방법으로서 위 소개 절에서 언급한 다중 계층 응용 프로그램에서 사용됩니다.
다음 폴더에 대한 명령 창이 열려 있다고 가정해 봅시다.
$FRAMEWORKSDK\Samples\Technologies\Remoting\Basic\RemotingHello\Service
다음과 같이 작성할 수 있습니다. soapsuds -id:. -types:Hello.HelloService,Hello -oa:HelloInterface.dll
이렇게 하면 출력 어셈블리 HelloInterface.dll을 생성하는데 여기에는 현재 디렉터리의 Hello 어셈블리에서 찾은 Remoting 서버 Hello.HelloService에 대한 메타데이터가 들어 있습니다. 이 어셈블리는 즉시 클라이언트가 사용할 수 있습니다. Remoting 서버 위치는 표준 Remoting 구성 당 런타임에서 제공되는 구성 데이터를 기반으로 파생됩니다. 클라이언트 어셈블리를 위해 생성된 MSIL,
ldfld object [System.Runtime.Remoting]System.Runtime.Remoting.Services.RemotingClientProxy::_tp
는 Remoting 서버 구현을 사용하지 않고 SOAPSUDS로 생산된 메타데이터를 사용해 제작된 프록시 클래스를 사용하고 있음을 분명히 보여 줍니다.
SOAPSUDS는 Binary 포매팅과 작동하도록 보장/지원되지 않습니다. 출력 어셈블리 메타데이터에 있는 특정 SOAP "스텁"의 일부를 포함/매핑합니다.
Remoting 인터페이스는 가능한 한 단순하게 유지하는 것이 좋습니다. "chunky" 대 "chatty" 인터페이스를 사용하십시오. 즉 설계에서 원격 호출의 수를 제한하십시오. 이렇게 하면 어떤 상황에서 매개 변수를 중복해서 전달하게 할 가능성이 있습니다. 원격 인터페이스를 실제 구현으로부터 별도의 클래스에 유지하십시오. 이렇게 하면 필요할 경우 Remoting 계층을 쉽게 다른 기술로 대체할 수 있는 "facade" 유형 패턴을 사용할 수 있습니다.
오류 관리
이 절에서는 Remoting 솔루션 개발 및 사용 중 만날 수 있는 여러 가지 오류 시나리오에 대해 설명합니다. 모든 경우에 표준 계측 및 모니터링 방법이 여전히 적용된다는 것을 기억하는 것이 좋습니다. 이벤트 로그는 네트워크 모니터 등의 도구처럼 여전히 중요한 정보원입니다. 네트워크 모니터는 특히 클라이언트 / 서버 Remoting 대화를 자세히 살펴보는 데 사용될 수 있습니다. 중간 계층 Remoting 서버는 Visual Studio .NET과 함께 제공되는 표준 디버깅 도구를 사용하여 여전히 디버그할 수 있습니다. 예를 들어 Remoting 서버가 IIS로 호스트되는 곳에서 중단점은 디버그 세션을 ASP.NET 작업자 프로세스에 연결함으로써 설정될(소스 제공 가능) 수 있습니다(Visual Studio .Net | Debug | Processes | Attach). 그러나 Remoting은 자체의 고유한 오류 집합을 가지고 있으며 다음은 이 중 일부에 대한 설명입니다. 참고로 모든 오류는 .NET Framework SDK와 함께 제공되는 Basic Remoting Hello Sample 버전을 사용하여 발생시킨 것입니다. 서버와 클라이언트는 하나의 컴퓨터에서 실행되었습니다. 네트워크로 연결된 경우에도 증상은 같지만 http / TCP 제한 시간 설정때문에 실패하기까지 시간이 조금 더 걸립니다.
MarshalByRef 누락
참조에 의한 Remoting이 주어진 클래스를 위해 일하려면 해당 클래스는 한 가지 작업만 해야 하며 이는 MarshalByRefObject로부터 상속받은 것이어야 합니다. 개발자가 이것을 잊어버렸다고 가정해 봅시다. 그러면 System.Runtime.Remoting.RemotingException 예외 유형이 발생하며 여기에서 'Missing MarshalByReference'가 있음을 알려줍니다.
RemotingException을 발견하고 올바르게 처리하는 것은 프로그래머에게 달려 있습니다. 이 개발자는 기억해야 할 한 가지 사실을 잊었다는 것을 상기하십시오.
MarshalByRefObject로부터 상속 받는 것이 해결 방법임을 기억하십시오.
잘 알려진 서버 활성화에 대한 잘못된 서버 종점
서버 활성화를 위해(제품 기능 절 참조) Remoting 서버는 수신하고 있는 종점을 선언합니다. 종점은 일반적으로 개체 URI(원격 개체의 잘 알려진 이름), 프로토콜 및 포트 번호를 포함합니다. 물론 이들은 모두 올바르게 구성될 수 있습니다.
잘못된 URI
Basic Remoting Hello Sample 서비스가 제공하는 해당 URI는 HelloService.soap이며 관련된 web.config 파일 내에서 다음과 같이 지정됩니다.
<configuration> <system.runtime.remoting> <application> <service> <wellknown mode="SingleCall" type="Hello.HelloService, Hello" objectUri="HelloService.soap" /> </service> </application> </system.runtime.remoting> </configuration>
이 서비스는 IIS로 호스트됩니다. IIS 호스팅은 접미사로 .rem 또는 .soap를 사용하는 URI가 필요합니다. 서버에서 .rope를 사용해 봅시다. 이 경우 RemotingException이 발생하며 'Object </Hello.soap> has been disconnected or does not exist at the server'라는 메시지가 표시됩니다.
URI이 일치하는지 확인하십시오. IIS가 Remoting 서버를 호스트할 경우 URI는 .rem 또는 .soap로 끝나야 합니다.
불일치하는 프로토콜 / 포트
이 테스트를 위해 콘솔 호스트 서버로 전환하겠습니다. 구성 파일은 다음과 같습니다.
<configuration> <system.runtime.remoting> <application name="RemotingHello"> <service> <wellknown mode="SingleCall" type="Hello.HelloService, Hello" objectUri="HelloService.soap" /> </service> <channels> <channel ref="http" port="8000" /> </channels> </application> </system.runtime.remoting> </configuration>
서버는 프로토콜을 TCP로 변경하고 클라이언트는 http를 사용하게 둔다고 가정해 봅시다.
다시 RemotingException이 발생합니다. 이번에는 'The underlying connection was closed: An unexpected error occurred on a receive'라는 메시지가 표시됩니다.
포트를 잘못 사용해도 똑같은 예외가 발생하며 유일한 차이점은 실패하는 데 좀 더 시간이 걸린다는 것입니다. 서버와 클라이언트에서 포트와 프로토콜은 일치해야 합니다.
URI 누락
또 다른 가능성은 원격 서버가 실행되고 있지 않는 경우입니다. 예를 들어 서버는 IIS로 호스트되는데 가상 응용 프로그램이나 관련 어셈블리가 누락된 것입니다. Basic Hello Remoting 서버를 다시 한번 사용하여 가상 응용 프로그램 RemotingHello가 실행되기를 기대하지만 그렇지 않을 경우 호출 코드에 따라 처리되지 않은 예외를 받게 됩니다. 이번에는 'Cannot load type clr:Hello.HelloService, Hello'라는 예외가 표시됩니다.
이런 경우 가상 응용 프로그램이 실행 중이며 필요한 어셈블리가 관련 bin 하위 폴더에 올바르게 위치해 있는지 확인합니다.
요컨대 서버에서 정의되는 종점은 서버 활성화를 위해 클라이언트에서 올바르게 참조되어야 하며 따라서 포트, 프로토콜 및 URI이 모두 일치해야 합니다. 이와 관련해 실수하기가 매우 쉽습니다. 따라서 서버 위치는 다음 예와 같이 정의됩니다.
<service> <wellknown mode="SingleCall" type="Hello.HelloService, Hello" objectUri="HelloService.soap" /> </service>
그리고 클라이언트 설정은 다음과 같이 합니다.
<client url="http://localhost/RemotingHello"> <wellknown type="Hello.HelloService, Hello" url="http://localhost/RemotingHello/HelloService.soap" /> </client>
여기서 URL은 Remoting 서비스를 호스팅하는 IIS 가상 응용 프로그램을 표시하며 유형은 클래스와 어셈블리 이름을 표시합니다.
Remoting 및 ASP.NET 웹 서비스
IT 설계에서 가장 좋으면서 동시에 가장 나쁜 것 중의 하나는 선택할 수 있는 구조적 구성 요소가 매우 많을 경우입니다. 웹 서비스와 .NET Remoting도 이 경우에 해당하며 간혹 어떤 목적으로 어떤 기술을 사용할지를 결정하기가 어려울 때가 있습니다. 물론 정답은 문제 해결에 최적인 기술을 선택하는 것입니다. “항상 웹 서비스를 사용해라”든지 “웹 서비스는 Remoting의 하위 집합이니 Remoting이 최선이다" 등의 조언은 듣지 않는 것이 좋습니다. 이 절에서는 특정 시나리오에서 어떤 기술을 왜 선택해야 하는지에 관련해서 두 기술을 비교해 보겠습니다.
ASP.NET 웹 서비스 vs. .NET Remoting
웹 서비스란 '웹 상에서 사용 가능한 서비스다'라는 정의를 먼저 살펴봅시다. 별 도움이 되지 않는 정의지요? 이를 "SOAP와 HTTP를 통해 액세스되며 어드레스할 수 있는 처리 단위로서, 이 처리 단위는 WSDL을 통해 기술되고 UDDI를 통해 게시될 수 있다."라고 정의해 볼 수 있을 것입니다 이 정의는 HTML을 브라우저로 되돌려 보내는 웹 서버와 웹 서비스를 구분시키므로 좀 더 유용합니다. .NET Remoting과의 비교를 위해 웹 서비스의 정의를 웹 상에서 사용 가능한 프로그램 방식의 서비스라는 점에 특별히 중점을 두겠습니다. 정의에 따르면 예를 들어 WSDL을 사용해 클라이언트에서 HTTP로 액세스할 수 있는 원격 호스트가 웹 서비스입니다. 이를 염두에 두고 Microsoft ASP.NET 웹 서비스 구현에 중점을 두어 분산 솔루션에서 .NET Remoting 대신 ASP.NET 웹 서비스를 "접착제"로서 선택할 때 어떤 요소를 고려해야 할까요?
상호 운용성
Microsoft에서는 다른 유형의 시스템 간에 상호 운용성이 필요한 경우 개방형 표준(SOAP, XML, HTTP)을 사용하는 웹 서비스가 올바른 선택이며 .NET Remoting은 결코 상호 운용성을 위해 좋은 솔루션이 아니라고 반복해서 언급하고 있습니다. 모든 참가자가 CLR로 관리되는 유형이 같은 시스템에서는 .NET Remoting이 올바른 선택일 수도 있습니다. 꽤 광범위하지만 좀 구분해 두는 것이 유용하겠습니다. .NET 원격 개체의 클라이언트는 .NET의 클라이언트여야 합니다. 느슨하게 연결된 SOAP 클라이언트(예: Unix 프로세스)가 웹 상에서 여러분의 기능을 어드레스할 수 있어야 한다면(웹, 여기서는 인터넷으로) 웹 서비스가 올바른 선택일 것입니다. 인트라넷에서는 당연히 이와 같은 제약이 없습니다. 즉 모든 클라이언트는 .NET 클라이언트일 수 있으며 이 구성에는 .NET Remoting도 포함됩니다. 이와 유사하게 중간 (응용 프로그램) 계층이 방화벽 뒤에 있고 웹 계층과 직접 통신하는 환경에서도 .NET Remoting이 고려될 수 있습니다.
강한 유형 지원
.Net Remoting은 모든 관리 유형, 클래스, 인터페이스, 열거, 개체 등을 지원합니다. 이는 흔히 "풍부한 유형 충실도"로 분류됩니다. 여기서 핵심은 클라이언트 및 서버 구성 요소 모두 응용 프로그램 도메인에서 실행되는 CLR 관리 개체이며 데이터 형식과 관련된 상호 운용성은 중요하지 않다는 점입니다. 근본적으로 폐쇄형 시스템을 가지고 있습니다. 대화 양단은 서로 완벽히 이해되며 따라서 통신하는 데 사용하는 데이터 및 개체 유형과 관련해 이 점을 이용할 수 있습니다.
이기종 시스템이 있을 경우 이런 시스템 사이의 상호 운용성을 고려해 보아야 합니다. 상호 운용성 있는 데이터 유형과 관련해서는 신중을 기해야 합니다. 예를 들어 웹 서비스 데이터 형식 정의는 데이터 형식 의미론에 있어서 XSD(XML Schema Definitions)에 의존합니다. XSD를 사용하여 기술되고 SOAP에서 상호 운용되는 모든 데이터 형식을 사용할 수 있습니다. 그러나 일부 데이터 형식의 사용은 제외되는데 예를 들어 unsigned char나 열거형에 대한 W3C XSD 표시는 없으며 컬렉션은 예외나 데이터 집합과 같이 다른 웹 서비스 구현에서 다르게 처리됩니다. 또 하나의 문제는 내부 필드와 속성이 웹 서비스 호출을 통해 전달되지 않는다는 것입니다. 이는 자체적으로는 심각한 문제는 아니지만 다른 기술에서도 상호 운용이 필요한 시스템을 설계하고 테스트할 때에는 고려해봐야 할 요소입니다. 왜냐하면 송신이 가능하다고 수신을 보장하는 것은 아니기 때문입니다.
다른 유형의 시스템 간에 상호 운용성이 필요한 경우에는 이를 해결할 기술로 .NET Remoting을 고려해서는 안 됩니다. 폐쇄형 CLR 관리 솔루션에서는 고려해 볼 수도 있습니다.
상태 관리
클라이언트 활성화든 Singleton이든 활성화 모드를 기반으로 하는 .Net Remoting을 사용해 상태 관리를 수행하는 여러 가지 방법을 이미 살펴봤습니다. HTTP(제한 시간 없는 상태 비저장 프로토콜)로 클라이언트당 연결 상태를 관리하는 것은 .NET Remoting과 웹 서비스 모두에게 부담스럽고 비실용적인 방법입니다. 그럼에도 불구하고 상태를 유지해야 할 경우 Remoting은 각 개체별로 솔루션을 제공합니다. 웹 서비스는 이 클라이언트당 연결 상태 관리를 제공하지 않지만 ASP.NET 세션과 응용 프로그램 개체에 대한 연결은 여전히 제공합니다.
수명 관리
상태 관리와 관계된 것이 수명 관리입니다. 이미 살펴본 대로 Remoting은 원격 개체의 수명 관리를 위해 기능적으로 우수한 메커니즘을 제공합니다. 웹 서비스 개체는 웹 서비스 호출에 따라 오고 갑니다. 개념적으로 동기와 비동기 모두에 해당됩니다. 이런 점에서 웹 서비스는 Remoting과 비교해 볼 때 단일 호출 형식으로 수행됩니다. Remoting은 원격 개체의 활성화와 제거에 대해 훨씬 강력한 통제를 제공합니다. 이는 여러분 설계와 관련이 있을 수도 있고 없을 수도 있습니다.
값 호출 vs. 참조 호출
웹 서비스 호출로 전달된 개체는 일련화되어 값에 의해 전달됩니다. Remoting에 전달된 개체나 호출된 개체 자신은 값 또는 참조에 의해 전달될 수 있습니다. 일련화된 원격 개체 메서드는 클라이언트에서 처리됩니다. Remoting이나 웹 서비스를 선택할 때에는 이러한 의미론적 차이를 고려해야 합니다. 이와 같은 고려 사항은 여러분이 해결할 문제의 성격에 따라 중요할 수도 있고 중요하지 않을 수도 있습니다.
지원되는 프로토콜
웹 서비스 호출은 HTTP를 통해 SOAP로 인코딩된 XML에 제한됩니다. Remoting이 TCP 전송 모드를 사용하거나 인프라가 사용자 지정 프로토콜을 지원하도록 확장시킬 수 있습니다. 예를 들어 명명된 파이프를 사용한 Remoting 구현은 www.gotdotnet.com, jhawk 사용자 샘플 절에서 볼 수 있습니다.
다음은 NamedPipe 추가 정보에서 Remoting의 확장성을 보여 주는 예입니다.
플러그형 채널 아키텍처를 사용해 IChannel* 인터페이스를 구현함으로써 채널을 .NET Remoting에 연결합니다.
명명된 파이프 채널은 다음 기능을 지원합니다.
* 명명된 파이프를 통한 통신
* 동기식 메시지
* 비동기식 메시지
* 일방형 메시지
* 콜백
* 채널 싱크
* 채널 속성
* 파이프 이름 자동 생성
명명된 파이프가 필요할 경우 Remoting은 솔루션을 제공합니다. 그러나 SSPI NTLM 인증 솔루션과 마찬가지로 이 솔루션은 현재 Microsoft에서 지원하지 않습니다. Microsoft는 조만간 이 요구 사항을 해결할 것으로 보입니다.
성능
설계에서 성능이 중요할 경우 Remoting은 TCP에서 이진 메시지 형식을 사용해 몇 가지 중요한 성능상의 혜택을 제공합니다. 이 기사에 설명된 결과를 낳는 데 사용된 환경은 기사 Performance Comparison: .NET Remoting vs. ASP.NET Web Services에 모두 설명되어 있습니다.
다음은 위 기사로부터 요약한 성능 통계입니다.
범례: ASMX - 웹 서비스, 기타 모든 Remoting 솔루션
WS는 원격 구성 요소를 호스트하는 Windows 서비스를 지칭
그림 1. 성능 통계
기사에서는 성능과 관련한 수치에 대해서 다음과 같이 설명합니다.
“위에서 보여 주듯이 Windows 서비스의 역할을 하는 호스트와 함께 WS_TCP_Binary는 개체가 TCP 채널과 Binary 포맷터를 사용하도록 구성됩니다. 이는 다른 분산 기술보다 성능이 뛰어납니다. 이런 이유는 이진 데이터를 HTTP보다 더 효율적인 원시 TCP 소켓을 통해 전송하기 때문입니다. 데이터를 인코딩/디코딩하지 않아도 되기 때문에 처리 오버헤드가 더 적습니다. WS_TCP_Binary와 가장 느린 방법 사이에 60% 정도의 성능 차를 볼 수 있습니다.
IIS_HTTP_Binary에서는 WS_HTTP_Binary와 같이 동일한 이진 페이로드를 생성하지만 IIS(Inetinfo.exe)에서 Aspnet_wp.exe로 추가 프로세스 홉이 있기 때문에 더 느립니다. 같은 이유로 IIS_HTTP_SOAP와 WS_HTTP_SOAP 사이에 성능 차가 생깁니다.
WS_HTTP_Binary 및 WS_TCP_SOAP는 매우 유사한 성능을 제공합니다. 전자에는 HTTP를 구문 분석하는 추가 오버헤드가 있고 후자에는 SOAP를 구문 분석하는 추가 오버헤드가 있지만 이 경우 HTTP 구문 분석과 SOAP 구문 분석의 오버헤드는 같습니다.
ASP.NET XML 일련화는 .NET Remoting SOAP 일련화보다 더 효율적이기 때문에 ASP.NET 웹 서비스는 IIS_HTTP_SOAP 및 WS_HTTP_SOAP보다 성능이 더 좋습니다. 위에서 보여 주듯이 ASP.NET 웹 서비스는 성능면에서 IIS_HTTP_Binary와 매우 유사합니다.”
원시 속도가 최우선 순위일 경우 이 “60% 성능 차”는 중요할 수 있습니다. 여기서 단점은 TCP 프로토콜을 사용하기 위해 Windows 서비스 내에서 서버를 호스트해야 한다는 점입니다. 위의 원격 호스팅 절을 참조하십시오. 실제로 이는 보안과 성능을 맞바꾸는 것으로서 "인터넷이나 안전하지 않은 인트라넷에서는 권장되지 않는” 방법입니다.
요약
ASP.NET 웹 서비스는 XML 기반으로서 실용성을 위해 HTTP 사용을 필요로 하며(IIS로 호스트될 경우) 단순한 프로그래밍 모델과 강력한 상호 플랫폼 지원을 제공합니다. 이 서비스는 SoapExtensions를 사용하여 어느 정도의 확장성을 보장합니다(예: 데이터 스트림 암호화). Remoting은 좀 더 복잡한 프로그래밍 모델이지만 유형 충실도, 상태 관리 및 프로토콜과 메시지 형식의 확장성 면에서 분명히 장점을 제공합니다. Remoting은 .NET 클라이언트 외의 클라이언트는 사용할 수 없으므로 인트라넷 클라이언트는 원격 호스트로 직접 연결할 수 없습니다. Remoting은 IIS 외부에서 호스트될 경우에는 안전한 모델이 아닙니다. IIS로 호스트된 Remoting은 SSL 등의 보안 프로토콜 사용을 포함해 ASP.NET과 동일한 보안 기능을 제공합니다. 다른 플랫폼과의 상호 운용성을 고려할 필요가 없고 클라이언트와 서버 구성 모두 완전히 통제 가능한 경우에는 .NET Remoting을 고려해 보십시오. Remoting을 사용할 때에는 관련 보안과 스케일 가능 인프라의 장점을 얻을 수 있도록 비 IIS 호스팅보다는 HTTP 채널을 사용하는 IIS 호스팅을 선택하십시오. 이와 같이 하려면 물론 여러분은 자신의 솔루션으로 IIS를 통제할 수 있는 위치에 있어야 합니다. 이것이 불가능하다면 Remoting은 관리하기에 너무 힘들 수도 있습니다. 이 점은 해결할 문제의 특성에 따라 달라집니다. .NET Remoting은 .NET 클라이언트를 필요로 하므로 가장 빠른 포맷터를 사용해야 합니다. 따라서 SOAP보다 좀 더 나은 성능을 제공하는 Binary 포맷터를 선택하십시오. 위의 최적의 사용 절에서는 이 포맷터를 개발 단계가 아닌 릴리즈 시에 적용하도록 권고했습니다.
요약 내용
.NET Remoting은 특정 유형의 분산 솔루션에서 채택할 수 있는 유용한 도구입니다. 지원할 수 있는 프로토콜과 메시지 형식 면에서 확장성 있는 모델이며 특정 시나리오에서 우수한 성능을 제공합니다. .NET Remoting은 인트라넷에 직접 배포할 수는 없으며 서버 개체는 IIS로 호스트해야 IIS 통제 내에서 실행되는 프로세스에 ISS가 제공하는 보안 및 성능 혜택을 얻을 수 있습니다.
Remoting은 클라이언트와 서버 모두 CLR로 관리되는 프로세스인 “폐쇄형” 분산 솔루션을 대상으로 고려해봐야 합니다. IPSec 등의 보안 TCP 채널이나 HTTP를 통해 인트라넷 솔루션 내의 어떤 계층에 있는 구성 요소, 방화벽을 통해 .NET 웹 계층과 대화하는 중간 계층 응용 프로그램 구성 요소를 예로 들 수 있습니다. 이 경우 SOAP 포맷터를 사용해 솔루션을 증명하고 나면 HTTP 채널을 Binary 포맷터와 함께 선택해야 합니다.
CLR이 아닌 클라이언트와의 상호 운용성이 필요한 시스템에는 데이터 형식과 관련한 일부 위험을 방지해 주는 ASMX 웹 서비스를 사용하십시오. 강력한 유형 지원 절을 참조하십시오.
TCP를 사용한 IIS 외부 호스팅에는 성능상의 혜택이 있지만 대신 사용자 지정 보안이 필요합니다.
설계 및 구현
Remoting의 구현과 구성은 비교적 쉽습니다. 먼저 Remoting 호스트, 프로토콜 및 활성화 모델을 선택해야 합니다. 설계와 구현을 가능한 한 단순하게 유지하는 한편 어떤 인터페이스 게시 메커니즘이 여러분 솔루션에 가장 적합할지를 신중히 고려하십시오. 권장되는 방법은 인터페이스만 게시하는 것으로 가장 깔끔한 개념적 모델이지만 클라이언트 활성화 개체에는 사용할 수 없습니다. 디버거, 이벤트 로그 및 네트워크 모니터는 모두 유용한 개발 도구이며 이들 모두 원격 구성 요소 개발에 도움이 됩니다.
Remoting의 미래
Remoting은 언제 사용하고 웹 서비스는 언제 사용하느냐와 같은 질문은 용어 정의가 명확하지 않다는 점에서 어려운 질문입니다. 웹 서비스의 정의가 불분명한 한편 Remoting을 웹 서비스로 기능하도록 구성할 수 있기 때문입니다.
앞으로 Remoting과 ASMX 기술은 병합될 것으로 보입니다. 현재로서는 위에서 설명한 것과 같이 어떤 기술을 언제 사용할지에 대한 적당한 그림을 보여줄 뿐입니다.
현재 개발은 라우팅, 보안 및 트랜잭션을 지원하는 GXA 구현에 주력하고 있습니다. 이 지원은 SOAP 헤더의 사용을 기반으로 하여 현재 웹 서비스의 기능 확장을 목표로 하고 있습니다. 이 기사에서 설명한대로 고전적인 의미에서 GXA가 .NET Remoting에 접근하지는 못하지만 상태 관리, 트랜잭션 관리 등과 같은 많은 문제(일부는 문제 해결을 위해 Remoting을 선택하겠지만)를 해결해 줍니다. 현재 GXA 구현으로 웹 서비스가 당면한 많은 문제를 해결하기 시작했지만 가능한 한 기술 면에서 불가지론적인 태도로 이러한 문제를 해결하는 것이 원래 목표입니다. GXA의 발전이 웹 서비스와 .Net Remoting 모두에 끼치는 영향을 지켜보는 것은 매우 흥미로울 것입니다.
댓글 없음:
댓글 쓰기