Creative Commons License

Microsoft .NET

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

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

.

닷넷!스킬업

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

[리모팅] 닷넷 리모팅 서비스에 대한 이해 3 - 리모트객체의 종류

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

요약 설명 :
이전 두개의 아티클에서 호스트 방식을 달리한(사용자정의호스트,IIS) 리모팅서비스 구축을 알아 보았다.
우리는 MarshalByRefObject 상속받는 리모트 클래스를 정의하고 그 클래스의 인스턴스를 원격지 클라이언트에서 사용하는 방법을 알고 있다.
 
[개요]
이전 두개의 아티클에서 호스트 방식을 달리한(사용자정의호스트,IIS) 리모팅서비스 구축을 알아 보았다.
우리는 MarshalByRefObject 상속받는 리모트 클래스를 정의하고 그 클래스의 인스턴스를 원격지 클라이언트에서 사용하는 방법을 알고 있다.
 
앞서 살펴본 예제에서 우리가 정의한 리모트객체는 과연 어디에서 인스터스화 되었을까?
 
보통 클래스를 정의하고 그 클래스의 인스턴스를 생성(new 연산자를 통한)하면 실행 컴퓨터의 특정 메모리영역에 인스턴스가 올라가게 되고 그 메모리 주소가 참조를 잃기 전까지는 계속해서 그 인스턴스를 사용할 수 있는게 일반적이다. 또한 일정시간 이상 참조를 당하지 않는 객체는 가비지콜렉트로 넘겨져 GC에 의해 불특정한 시점에 메모리에서 사라지게 된다
 
그러면 리모팅 환경에서는 과연 어디(서버or클라이언트)의 메모리에 실제 클래스에 대한 인스턴스가 생성되며 그 객체의 수명은 어떻게 될까?
 
우선, 우리는 리모트객체의 두 가지 타입에대해 알아볼 필요가 있다.
물론 임대기반수명이라는 메커니즘도 존재하지만 이번 아티클에서는 리모트 객체의 타입에 따른 리모트객체의 생명주기와 개별 클라이언트에서의 상태공유를 알아 볼 것이다.
 
리모트객체의 종류
리모드 객체는 크게 두가지의 종류로 나누어 진다.
Ⅰ. 서버활성화 개체(Well-Known 개체) - 서버가 활성화 한 개체
   ①SingleCall 모드
   ②Signleton 모드
Ⅱ. 클라이언트활성화 개체 - 클라이언트가 활성화 한 개체
 
우선, 간략히 정리하자면 서버활성화 개체는 클라이언트에서 리모트 객체의 메서드를 호출할때 활성화 되며 클라이언트 활성화 개체는 클라이언트에서 new 연산자로 리모트 객체를 생성할때 활성화 된다.
 
주의할 것인 위의 서버/클라이언트 활성화 라는 말은 서버/클라리이언트 메모리에 인스턴스가 생긴다는 기준이 아니라. 서버/클라이언트에서 리모팅 객체를 활성화 한다는 말이다.
 
그럼 이제 차례대로 그 차이점을 알아보도록 하자
 
1. Well-Known(SingleCall) 개체에 대해서 알아보자.
   설정 파일의
   <service>
        <wellknown
            mode="SingleCall"
            type="RemotingServiceDemo.RemotingObject , RemotingObject"
            objectUri="RemotingObject" />               
   </service>
   이 부분에서 우리는 이미 개체의 종류를 명시하였다.
 
   -SingleCall 모드에서는 두가지를 기억 하여야 한다.
    ㉠ 클라이언트에서 리모트객체의 메서드를 호출할 때 마다 새로운 객체가 만들어 진다.
    ㉡ (데이터의)상태유지가 되지 않는다.
   
   - 예제를 통해 알아보자
 
   * RemotingObject.cs (리모트 객체)
    - 객체 생성 시점 확인을 위한 생성자와 데이터의 상태유지 확인을 위한 shareValue 라는 변수를 두었다. 
   using System;
   namespace RemotingServiceDemo{
    public class RemotingObject : System.MarshalByRefObject {
      private int shareValue = 0;
      
      public RemotingObject(){
        Console.WriteLine("원격객체가 새로 생성되었습니다.");
      }       
      public int ADD(){
          return this.shareValue++;
      }
    }     
   }
 
   * 서버 설정파일의 service 항목 - mode 를 SingleCall로..
   <service>
        <wellknown
            mode="SingleCall"
            type="RemotingServiceDemo.RemotingObject , RemotingObject"
            objectUri="RemotingObject" />               
    </service>
   
   * 클라이언트 실행 파일
     - 리모트객체 생성시점과 데이터 공유 유/무를 확인하기 위해 메서드를 세번 호출한다.
    using System;
    using System.Runtime.Remoting;
    using RemotingServiceDemo;
    class SimpleClient{
        public static void Main(){
          RemotingConfiguration.Configure("Client.exe.config");      
          RemotingObject remoteObject = new RemotingObject();                        
          for(int i=0; i < 3; i++)
            Console.WriteLine(remoteObject.ADD().ToString());              
        }
     }
 
   * 클라이언트 설정 파일은 이전과 동일하다.
 
   * 실행 결과



* 결론
실행화면을 보면 클라이언트에서 리모트 객체의 메서드를 호출할때마다 서버측 리모트객체의 생성자가 실행되며, 
각각이 별도의 객체이므로 데이터의 공유는 전혀 되고 있지 않음을 알 수 있다. 이처럼 Well-Known 개체의 SingleCall 모드로 리모트 객체를 생성하면 데이터의 공유는 기대할수 없다.
 
 
2. Well-Known(Singleton) 개체에 대해서 알아보자.
   설정 파일의 mode 부분만 바꿔주자   
     <wellknown
       mode="Singleton"
       type="RemotingServiceDemo.RemotingObject , RemotingObject"
       objectUri="RemotingObject" />
   
   * 클라이언트 실행파일
    - 클라이언트에 new 연산자를 두번 사용해서 새로운 객체를 만드는것처럼 했다              
   using System;
    using System.Runtime.Remoting;
    using RemotingServiceDemo;
    class SimpleClient{
        public static void Main(){
          RemotingConfiguration.Configure("Client.exe.config");      
          RemotingObject remoteObject = new RemotingObject();                        
          for(int i=0; i < 3; i++)
            Console.WriteLine(remoteObject.ADD().ToString());   
 
          RemotingObject remoteObject2 = new RemotingObject();                        
          for(int i=0; i < 3; i++)
            Console.WriteLine(remoteObject2.ADD().ToString());             
        }
     }
 
   -Singleton 모드에서도 두가지를 기억 하여야 한다.
    ㉠ 리모트개체는 클라이언트의 첫번째 메서드 호출시 리모트 객체가 단 한번 만들어 진다
       다음번 메서드 호출부터는 같은 객체를 쓴다
    ㉡ (데이터의)상태유지가 가능하다.       
 
   * 실행 결과



* 결론 
실행화면을 보면 리모트 객체는 클라이언트가 첫번째 메서드 호출시 단한번 생성되고 그 이후로는 이미 생성된 객체를 사용함을 알 수 있다. 하물며 RemotingObject remoteObject2 = new RemotingObject() 이 부분에서 클라이언트가 new 연산자로 새로운 리모트 객체를 생성하는 것처럼해도 같은 객체가 사용된다. 
이것은  Well-Known 개체는 클라이언트의 new 연산자가 아닌 메서드 호출시 실제로 생성됨을 확연히 알 수 있는 대목이다. 결론적으로 Well-Known 의 Singleton 모드의 리모트 개체는 클라이언트의 첫번째 메서드 호출시 단 한번 생성되고, GC에 넘어가기 각 클라이언트에서는 하나의 인스턴스를 사용하는 결과를 초래한다. 이것은 또한 각각의 클라이언트에서 데이타의 공유가 가능함을 의미하기도 한다.
 
 
 
3. 클라이언트 활성화 개체에 대해서 알아보자.
   - 이 개체는 우리가 일반적으로 프로그램을 짤때 클래스의 인스턴스를 생성하는 개념과 유사하다.
     즉 new 연산자를 통해서 인스턴스가 생성되고 각각의 new연산자로 생성된 인스턴스는
     서로 다른 메모리 주소를 가지는 즉 서로다른 인스턴스가 되는 것이다.   
  
   -Singleton 모드에서는 두가지를 기억 하여야 한다.
    ㉠ 클라이언트에서 리모트객체를 new 연산자로 생성할때 서버에서 객체가 생성된다.
    ㉡ (데이터의)상태유지 가능하다. 단, Signton과는 달리 new 연산자로 생성된 각각의 객체내에서만.
   
   - 예제를 통해 알아보자  
 
   * 서버 설정파일의 service 항목 - wellknown 를 activated 로..(종단점이 필요치 않다)
   <service>
        <activated           
            type="RemotingServiceDemo.RemotingObject , RemotingObject"
           />               
    </service>
   
   * 클라이언트 설정파일 - 역시 wellknown 를 activated 로..(역시 종단점이 필요치 한다)
     <client url="tcp://localhost:4989/ServerHosting">                  
        <activated
            type="RemotingServiceDemo.RemotingObject, RemotingObject"
            url="tcp://localhost:4989/ServerHosting" />      
      </client>      
 
   * 실행 결과



* 결론
실행화면을 보면 리모트개체는 클라이언트에서 new 연산자로 리모트개체를 생성할때 실제로 생성됨을 알 수 있다 
두번의 new 연산자로 두개의 리모트 객체를 생성한 셈이다. 
 여기서의 데이터 공유는 각 객체별로 공유가 가능하다.(일반적인 우리의 객체상식이다)
 
 
추가사항
리모트개체에 기본생성자 이외의 생성자 사용에 대해...
만일 리모트개체에 파라메타가 있는 생성자를 정의 했다고 하자.
 
그럼 클라이언트에서는 그 생성자를 호출 하기 위해서는 new 연산자로 파라메타를 넘겨줘야 한다.
 
그럼 Well-Known 과 클라이언트 활성화 개체 모두 기본생성자 이외의 생성자 사용이 가능할까??
이미 눈치를 채신분도 있으리라 본다.
 
답은 클라이언트 활성화 개체만 가능하다
 
상식적으로 생각해보자.
Well-Known 개체의 생성시점은 클라이언트의 new 연산자가 아닌 메서드 호출시 실제 리모트객체가 생성된다고 했다. 즉 파라메타가 있는 생성자에게 파라메타를 넘겨줄 방법이 없는 것이다. 그러나 클라이언트활성화타입의 개체사용시에는 new연산자로 넘겨주면 된느 것이고... (당연하죠? ^^;>
 
정리
이상 닷넷 리모팅서비스에서 리모트개체에 대한 타입과 그 타입에 따른 리모트개체 생성시점과
데이터 공유에 대해 알아 보았습니다. 감사합니다. 아래에는 간단히 비교한 표입니다.
 

 

Well-Known

클라이언트 활성화

 

SingleCall

Singleton

 

객체 생성시점

클라이언트이
리모트메서드
호출시 마다.

클라이언트의

첫번째 메서드

호출시 단한번.

(new 로 생성되지는 않음)

클라이언트의 new연산자

를 통한 리모트객체 생성시

마다.

데이터 상태유지

X

O

O

기본생성자 이외의
생성자 사용

X

X

O

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