Creative Commons License

Microsoft .NET

닷넷!시작하기
닷넷! Ver 2.0~
닷넷!스킬업
웹개발
윈폼개발
실용모듈개발
Tip & Tech
하루 한 문법

Microsoft .NET 개발자들을 위한 공간입니다. 기초강의에서 부터 고급 기술 정보 및 팁등을 다루도록 하겠습니다.

.

닷넷!스킬업

닷넷 기술을 조금 더 깊이 다루고자 합니다. 특정 주제를 정하지 않고 이슈 발생 시 마다 체계적으로 정리하여 공유하겠습니다. 이전 자료를 옮겨온 곳이기도 합니다.

[리모팅] 닷넷 리모팅 서비스에 대한 이해 1

작성자 : 박종명
최초 작성일 : 2008-05-26 (월요일)
최종 수정일 : 2008-05-26 (월요일)
조회 수 : 4718

요약 설명 :
분산환경에서의 서버/클라이언트간 정보공유의 여러 방식중 닷넷리모팅서비스에 대해 알아본다.
프로젝트의 규모가 커지고 B2B와 같은 기업간 협업형태의 솔류션 개발시 분산환경에서의 개발은 더 이상 이슈화가 될 수 없을정도로 보편화 되고 있다.
 
[.NET 리모팅 서비스]
 

개요
프로젝트의 규모가 커지고 B2B와 같은 기업간 협업형태의 솔류션 개발시 분산환경에서의 개발은 더 이상 이슈화가 될 수 없을정도로 보편화 되고 있다.초기에는 COM을 개발하고 각각의 분산서버에 물리적인 배포와 설치로 적당히(?) 해결해 왔었다. 그러나 COM의 버전변경등과 같은 이유로 재배포와 재등록의 과정에서 DLL HELL 과 같은 아주 지저분한 문제가 대두되었었다. (이 경험이 있는 사람은 얼마나 개발자를 짜증나게 하는지 다 알고 있을 듯 싶다)
COM의 배포문제는 DLL HELL 과 같은 문제가 아니더라도 여러가지 불편한 사항들이 많이 있었다.

서버/클라이언트간의 정보교환의 중요성과 필수성이 증가하고 보다 안정적이고 쉬운배포,생산성의 향상과 같은 요구사항을 만족시키기 위해 DCOM이나 RMI 같은 기술들이 나오게 되었다.(DCOM,RMI는 따로 설명하지 않겠습니다.)

이제는 더욱더 발전해 웹서비스라는 개념이 등장하였고 MS에서는 ASP.NET 웹서비스라는혁신적인 기술로 개발자에게 쉬운개발,쉬운배포,이기종 플랫폼 호환을 가능케 하였다.

또한 현재 많은 중대형 프로젝트에서 도입하고 있는 닷넷의 스마트 클라이언트 환경에서의 솔루션 개발시 ASP.NET의 라운드트립(포스트백)을 사용하지 않기에 서버와 통신하는 방법으로 웹서비스와 닷넷리모팅이 사용되어지고 있다.

이번 아티클에서는 이 웹서비스와 비슷한 기능을 가진 닷넷리모팅서비스에 대해서 간략하게 알아볼 것이다.

두 서비스 모두 네트워크나 인터넷을 통해 서버/클라이언트간 정보교환을 할 수 있게 하는서비스이지만 약간의 차이는 있다.

둘간의 차이는 깊이 들어가면 상당히 많은 부분이 있겠지만 간략하게 말을 한다면 웹서비스는 개방형 표준을 준수하여 이기종 플랫폼과 이기종 언어사이에서도 데이터교환이 가능하며, ASP.NET 웹서비스는 ASP.NET 런타임을 요구하며 호스팅을 위해 IIS를 반드시 필요로 하는 모델인 반면, 리모팅서비스는 SOAP와 같은 표준을 반드시 준수하지는 않으며 IIS와 같은 호스팅서버에 의존적이지 않으며  닷넷환경에 보다 빠르고 유연한 데이터 송수신을 보장한다.


아래는 리모팅 서비스의 실행구조에 관한 몇가지 다이어그램이다.





-웹서비스와 마찬가지로 클라이언트에 프록시가 존재하여 서버와 실제 통신을 한다.
 (웹서비스도 웹참조를 하면 프록시클래스가 자동으로 생긴다- Reference.cs)
-세번째 다이어그램과 같이 방화벽을 통과하기 위해서는 HTTP에 SOAP로 통신을
 해야 한다. (리모팅에서의 데이터 전송 프로토콜과 포멧은 개발자가 지정 가능하다)


보다 이론적인 배경은 저도 다 알지를 못하기에 실제 리모팅을 개발하는 개발자 입
장에서 소스코드와 함께 간략한 예제를 설명하도록 하겠습니다



* 리모팅 구축 순서

ASP.NET 웹서비스의 경우 IIS를 호스트로 사용하게 되어
클라이언트에서는 웹참조로 해당 IIS로 접근하여 서버측의 리소스를
호출하게 된다
.
( ASP.NET
웹서비스는 ASP.NET런타임을 요구한다)
그러나 닷넷 리모팅에서는 위와 같이 iis를 호스트로 사용할수도 있지만
사용자가 별도로 호스트를 만들어 서비스 할 수 있다.
IIS가 없어도 리모팅 서버 구축이 가능하다는 것이다.

아래에는 리모팅 서버구축 순서를 양측면에서 비교해본 것이다.

1. IIS
를 호스트로 사용할 시
  - 서버 측 -

    ⓐ 리모팅클래스(서버객체) 작성(컴파일후 웹응용프로그램폴더의 bin에 위치)

    web.config에 리모팅객체에 대한 설정 추가
  (iis로 호스팅을 하기 때문에 추가적인 채널설정(프로토콜,포트)이 불필요)

- 클라이언트 측 -

 ⓐ 리모팅객체 참조를 위한 클라이언트 구성파일 작성
 ⓑ 클라이언트 프로그램 작성

 ⓒ 리모팅클래스 어셈블리 파일을 참조하여 클라이언트 컴파일

2. 사용자 지정 호스트를 사용할 시.
- 서버 측 -
   ⓐ 리모팅클래스(서버객체) 작성
   ⓑ 호스트프로그램(서버응용프로그램) 작성(구성파일작성)
   (iis로 호스팅할때와는 달리 직접 채널을 관리 하여햐 한다)
- 클라이언트 측 -

      ⓐ 리모팅객체 참조를 위한 클라이언트 구성파일 작성
ⓑ 클라이언트 프로그램 작성

ⓒ 리모팅클래스 어셈블리 파일을 참조하여 클라이언트 컴파일

* 호스트방식에 따른 변화는 보는 바와 같이 크지 않다.
  단지 iis호스트일 경우 http 프로토콜과 해당 웹사이트의 포트를 사용하여
  호스트 를
하기에 별도의 채널 설정이 필요가 없는것뿐이다.

*
클라이언트측 ⓒ 항목을 보면 클라이언트 프로그램 컴파일시
  리모팅어셈블리를 참조해서
컴파일 해야 한다고 되어있다.
  즉 클라이언트에 리모팅어셈블리 파일이 있어야 한다는 것이다.
  그러나 이것은 클라이언트에서 원격객체 사용시 프록시 역할을 한다.
  실제로 호출되는 것은 서버에 있는 객체가 된다.

 



* 실제 작성할 리모팅 객체 및 설정파일(서버측)  
  
아래에는
IIS를 호스트로 사용하지 않고
  직접 채널을 관리하는 사용자지정 호스트를
사용한 예를 보겠다.
  또한 리모팅객체를 하나의 어셈블리에 두개의 객체를 두도록 하겠다.
  따라서 설정파일에서는 wellknown 요소가 두개가 되어야 한다
  (이것은 선택사항입니다. 리모팅객체가 하나든 두개든 상관이 없습니다.
   단지 객체수만큼의 객제정보설정파일을 맞춰 주시면 됩니다)


-
리모팅 객체 ?

원격 클라이언트에서 호출될 객체는 System.MarshalByRefObject 로부터
상속받아야 한다
.
(MarshalByRefObject는 프록시를 사용하여 메시지를 교환하는 방식으로 응용 프로그램 도 메인 경계를 넘어 통신하는 개체의 기본 클래스입니다.)

>> 아래의 파일을  csc /t:library RemotingObject.cs 로 컴파일

using System;

namespace RemotingServiceDemo{

  public class RemotingObject : System.MarshalByRefObject {    

    public string RemotingMethod(){

        return "서버측 메서드 실행1";

    }

  }

  

  public class RemotingObject2 : System.MarshalByRefObject {    

    public string RemotingMethod2(){

        return "서버측 메서드 실행2";

    }

  }

}


 

- 호스팅 프로그램(서버 프로세서) -
사용자 정의 호스팅의 호스팅을 담당할 프로세서를 직접 작성하여야 한다.
이 프로세서는 서버측 채널을 생성하고 리모팅객체를 원격서비스에 등록하며
클라이언트가 접속할수 있도록 리스팅 모드로 돌입하는 역할을 한다.
구현 방법은 두가지로 프로그래밍 방식과 구성파일을 사용하는 방식이 있다.
각각이 장단점이 있지만, 우선 구성파일을 따로 두면 채널과 리모팅 객체의 관리를
리컴파일 없이 변경 가능하다는 것이다.
(
이번 아티클에서는 구성파일을 사용하는 예를 보겠습니다)

>>아래의 파일을 csc ServerHosting.cs 로 컴파일

using System;

using System.Runtime.Remoting;

namespace RemotingServiceDemo{

  class ServerHosting{

    static void Main(string[] args){

      RemotingConfiguration.Configure("ServerHosting.exe.config");

      Console.WriteLine("서버프로그램 실행중..(원격객체 등록및 채널설정 완료)");

      

      Console.ReadLine();

    }

  }

}
 
 
-
호스팅을 위한 서버측 구성 파일 -

<configuration>

  <system.runtime.remoting>

    <application name="ServerHosting">

      <service>

        <wellknown

            mode="Singleton"

            type="RemotingServiceDemo.RemotingObject , RemotingObject"

            objectUri="RemotingObject" />

        <wellknown

            mode="Singleton"

            type="RemotingServiceDemo.RemotingObject2 , RemotingObject"

            objectUri="RemotingObject2" />

      </service>

      <channels>

        <channel ref="tcp server" port="4989" />

      </channels>

    </application>

  </system.runtime.remoting>

</configuration>

*
각 요소 설명
<application name="SimpleServer"> : 서버이름 지정.
<wellknown>
요소 : 클라이언트에 노출되는 리모팅 객체 설정.
                    다수의 wellknown 요소 사용 가능.
                    mode : 참조로 마샬링되는 리모팅객체의 활성화 유형 지정.
                    type : 리모팅 객체의 타입(namespace.class)과 어셈블리명을 정의.
                    objectUri : 리모트 객체의 종단점 이름.
                    (개체가 IIS에 호스팅된 경우에는 요청이 .NET Remoting              
                     IHttpHandler로 라우팅되도록 objectUri의 확장명은 .soap     
                     또는 .rem이어야 함)
<channels> 요소 : 서버의 채널 정의.
                  하나의 <application> 요소에 하나의 <channels>만 정의 가능.
                  machine.config에 사전정의된 채널(tcp channel)을 참조(ref)하여 사용 

  

 



* 실제 작성할 클라이언트측 구설파일및 코드(클라이언트측)  
서버가 열어놓은 채널로 통신을 하기 위한 설정파일과 그 설정파일에
기반해서 원격객체를 사용한다


- 서버 채널접속을 위한 클라이언트 설정 파일 -
 

<configuration>

  <system.runtime.remoting>

    <application name="SimpleClient">

      <client url="tcp://localhost:4989/ServerHosting">

        <wellknown

            type="RemotingServiceDemo.RemotingObject, RemotingObject"

            url="tcp://localhost:4989/ServerHosting/RemotingObject" />

        <wellknown

            type="RemotingServiceDemo.RemotingObject2, RemotingObject"

            url="tcp://localhost:4989/ServerHosting/RemotingObject2" />

      </client>

      <channels>

        <channel ref="tcp client" />

      </channels>

    </application>

  </system.runtime.remoting>

</configuration>

딱히 설명할 것이 없어 보인다.
서버측 구성파일에 명시한 프로토콜과 어셈블리 경로를 맟춰주기만 하면된다.
[ url = 프로토콜://호스트이름(or IP):포트번호/서버이름/리모팅객체이름 ]

 

- 원격객체를 사용하는 클라이언트 코드 -

 

using System;

using System.Runtime.Remoting;

using RemotingServiceDemo;

class Client{

    public static void Main(){

      RemotingConfiguration.Configure("Client.exe.config");

      

      RemotingObject remoteObject = new RemotingObject();

      Console.WriteLine(remoteObject.RemotingMethod());

      

      RemotingObject2 remoteObject2 = new RemotingObject2();

      Console.WriteLine(remoteObject2.RemotingMethod2());

    }

}

 

 



결과 화면


참고사항
위에서 클라이언트측 프로그램(Client.cs)를 컴파일 할때 리모트객체의 어셈블리를 참조하여야한다고 했다.
위에서도 언급했었지만 클라이언트에 참조된 어셈블리는 단지 프록시 역할을 할 뿐이다.

참조했다고 해서 그 어셈블리의 객체를 생성하는것이 아니라는 것이다.
확인 방법은 클라이언트에가 컴파일시 참조하는 RemotingObject 의 메서드안에 리턴값을 다른 글자로 변경해서 재컴파일후 Client.cs를 재컴파일된 RemotingObject.dll 을 참조해보자.
이렇게...
public string RemotingMethod(){

        return "클라이언트가 바꿔버린 문자";
}
그러면 컴파일을 정상적으로 되고 실행을 해보면 여전히 서버에 있는 RemotingObject.dll이 호출될 것이다.(당연하겠지만 -.-;) 하지만 변경시 네임스페이스명,클래스명, 메서드 시그너처 같은 것은 바꾸면 Client컴파일시 에러가 난다(이것도 당연하겠죠)

 
정리
어디서나 구할수 있을법한 예제를 가지고 설명을 하였습니다. 하지만 중요한것은 리모팅서비스의 제대로된 이해와 그 이해를 바탕으로 한 응용이라고 봅니다. 리모팅 서비스를 구축할때 알아야 할 것은 이것이 모두가 아닙니다. 앞으로 여건이 된다면 리모팅 서비스의 다른 사항들도 확인해 보겠습니다.

감사합니다.

이름
비밀번호
홈페이지
PI <- 왼쪽의 문자를 오른쪽 박스에 똑같이 입력해 주세요