Jump to content
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr ×
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr

Recommended Posts

델파이 2009이후의 Com을 사용하지 않는 DataSnap 확장성의 핵심은 서버 메서드 인스턴스 수명 주기(Life Cycle) 관리이다. 

DataSnap 아키텍처에서 클라이언트는 서버 메소드 클래스의 Public 메소드를 원격으로 호출한다. 개발자는 서버 메소드 클래스 인스턴스를 생성하고 파괴하는 것에 대해 걱정할 필요가 없다. 서버 클래스의 유형과 해당 수명 주기만 알려주면 된다. 서버 메소트의 수면 주기는 아래와 같은 3가지 옵션이 있다.

  • Session 

           디폴트 옵션으로 즉, 연결된 모든 클라이언트에 대해 클라이언트가 연결할 때 생성되고 연결이 끊길 때 소멸되는 하나의 전용 서버 메서드

         인스턴스가 있음을 의미한다. 이것은 "상태 저장" EJB(Enterprise Java Bean)의 개념과 매우 유사하다.

  • Server

         이 경우 모든 클라이언트는 동일한 서버 클래스 인스턴스의 메서드를 호출한다.  해당 메소드는 여러 스레드에서 동시에 호출될 수 있다

  • Invocation

        이것은 아마도 가장 확장 가능한 가능성일 것입니다. 왜냐하면 서버 메소드 클래스 인스턴스는 메소드 호출 기간 동안만 생성되기 때문이다.

        요청이 도착하기 직전에 인스턴스화 되고 호출이 완료되면 소멸된다. 이것은 "상태 비 저장" EJB와 개념적으로 매우 유사하다.

즉 서버의 비지니스로직(메소드) 호출시 어떤  LifeCycle을 사용하는지에 따라 성능이 달라질 수도 있을것이다. 예를들어 조회만 하는 메소드라면 어떤 옵션을 사용하시겠습니까 ? 

서버 프로젝트 생성

  1. File > New > Other 메뉴를 클릭하고  DataSnap  범주에서 DataSnap Server를 두 번 클릭하여   DataSnap 서버 애플리케이션을 생성한다.

image.png

 

2.  아래 화면과 같이 옵션을 선택하면서 Next를 누르면서 진행한다.

image.png

3.  Form Application 선택->VCL Application 선택한다.

4. 아래와 같이 Server Methods Class는 선택하고 Sample Methods는 선택하지 않는다.

image.png

5. 포트를 테스트하고 아래와 같이 TComponent를 선택하고 Finish 버튼을 클릭한다.

image.png

6. 폼 이름, 유니트 이름, 프로젝트 이름을 각각 Form_Main(Main_Server.pas), LifeCycle_Server.dpr로 저장한다.

7. 데모를 위해 서버 메소드 클래스에 고유 식별자를 반환하는 GetId  메소드를 추가한다. 이러한 방식으로 클라이언트 프로그램은 통신하는 서버 내 부의 서버 메서드 클래스 인스턴스를 확인할 수 있다.

8. GUID(Globally Unique Identifiers)를 생성하는 기본 OS 기능을 호출하는 전역 기능을 제공하는 유니트를 생성하기 위해  File > New > New Unit를  선택하고 유니트 이름을 "GUID_utils"로 저장하고 아래와 같이 코드를 구현한다.

unit GUID_utils;

interface
function GetNewGUID: string;

implementation
uses
  ActiveX, SysUtils;

function GetNewGUID: string;
var aGUID: TGUID;
begin
  CoCreateGUID(aGUID);
  Result := GUIDToString(aGUID);
end;

end.

7. 기존의 TServerMethods1 클래스 안에 다음과 같이 코드를 구현한다. 

unit ServerMethodsUnit1;

interface

uses
  SysUtils, Classes, DSServer;

type
{$METHODINFO ON}
  TServerMethods1 = class(TComponent)
  private
    FID: string;
  public
    constructor Create(AOwner: TComponent); override;
    function GetID: string;
  end;
{$METHODINFO OFF}

implementation

uses GUID_utils;

{ TServerMethods1 }

constructor TServerMethods1.Create(AOwner: TComponent);
begin
  inherited;
  FID := GetNewGUID;
end;

function TServerMethods1.GetID: string;
begin
  Result := FID;
end;
end.

그렇다면 DataSnap은 TServerMethods1 클래스가  서버 메소드이고  공개 메소드가 클라이언트에  어떻게 노출될까? 이것은 주요 TDSServer 컴포넌트와 모든 서버 메서드 클래스 간의 링크 역할을 하는  TDSServerClass 컴포넌트의 역할입니다. 하나의 DataSnap 서버 애플리케이션에는 심장의 역활을 하는 항상 하나의 TDSServer 컴포넌트와 TDSServer가 클라이언트와 통신하는 여러 전송 콤포넌트, 프로그래머가 값을 할당할 수 있는 OnGetClass 이벤트를 제공하는 많은 TDSServerClass 컴포넌트가 있다. 클라이언트 요청이 도착할 때 인스턴스화해야 하는 서버 메소드 클래스의 유형입니다.

OnGetClass 이벤트 구현에서 수행해야 할 가장 중요한 부분은 프로그래머가 매개변수에 대한 인스턴스 참조가 아니라 유형 참조를 할당한다는 사실이다. DataSnap 아키텍처에서 프로그래머는 서버 클래스의 수명 주기를 직접 제어하지 않는다. 선언적으로 수명을 관리하는 TDSServerClass 컴포넌트의 Lifecycle 속성이 있다. DSServerClass1.LifeCycle 속성의 기본값은 Session이다.

9. 서버 어플리케이선을 실행한다.

클라이언트 어플리케이션 작성

1. 새로운 VCL Forms Application을 생성하고 Form_Client(main_Client.pas), LifeCycle_Client.dpr로 저장한다.

2. 아래와 같이 화면을 설계한다. (TButton, TLabel 컴포넌트 추가) 

image.png

3. 폼에 TSQLConnection 컴포넌트를 추가한다. Delphi 2009에서 DataSnap 서버에 대한 연결은 RDBMS 서버가 아닌 DataSnap 서버에 대한 연결을 제공하는 DBX4 드라이버의 형태로 구현되었있다. 클라이언트 관점에서 DataSnap 서버 인스턴스는 데이터베이스 인스턴스와 매우 유사하게 보이며 서버 메소드는 저장 프로시저와 매우 유사하다.

image.png

 

4. 아래의 속성을 다음과 같이 설정한다.

  • Driver            :  DataSnap
  • LoginPrompt : False
  • Connected    : True

5. SQLConnection1 컴포넌트를 마우스 오른쪽 버튼으로 클릭하고 컨텍스트 메뉴에서 "Generate DataSnpa Client Classes"을 선택한다.

6. 클라이언트  프로그램에서 서버 메서드를 호출하려면 Client가 추가된 서버 클래스와 이름이 같은 생성된 클라이언트 클래스를 인스턴스화해야 한다.

7. 생성된 유니트 이름을 Proxcy.pas로 저장하고 화면에서 uses절에 추가한다.

8. GetId 메소드를 호출하고 레이블 컴포넌트에 수신된 값을 표시하기 위해  OnClick 이벤트를 다음과 같이 구현한다.

procedure TForm_Server.Button1Click(Sender: TObject);
var aClient: TServerMethods1Client;
begin
  aClient := TServerMethods1Client.Create(SQLConnection1.DBXConnection);
  try
    Label1.Caption := aClient.GetID;
  finally
    aClient.Free;
  end;
end;

9. 프로그램을 실행하여 버튼을 클릭하면 원격 DataSnap 서버 애플리케이션 내에서 실행되는 서버 메소드 클래스 인스턴스의 고유한 전역 식별자가 표시 된다. 버튼을 더 많이 클릭하면 식별자가 변경되지 않는 것을 볼 수 있다. 윈도우 탬색기에서 클라이언트 응용 프로그램을 또 실행하면  다른 인스턴스를 시작한다. 버튼을 클릭하면 식별자가 다른 것을 볼 수 있다. 이는 두 클라이언트 응용 프로그램이 동일한 서버 클래스의 다른 인스턴스와 통신하고 있음을 의미한다.

image.png

Server 및 Invocation 당 수명 주기 테스트

TDSServerClass.LifeCycle 속성에 대해  다른 값들을 지정하여 테스트 해보자.  서버에 두 개의 TDSServerClass 컴포넌트를 더 추가하고  LifeCycle 속성을 각 각 다르게 지정하 세 개의 서버 메소드 클래스가 필요하다. 

1. 모든 클라이언트 프로그램과 서버 프로그램을 닫는다.

2. 서버 프로그램을 오픈하고 DSServerClass1 컴포넌트를 선택하고 Name 속성을 "DSServerClass_Session"으로 변경한다.

3. TDSServerClass 컴포넌트를 두 개 더 추가하고 각 각의  Name을 "DSServerClass_Server" , "DSServerClass_Invocation"으로 변경한다.

4. Lifecycle 속성도 각 각 Server, Session으로 변경한다.

image.png

5. 서버 메소드 클래스 유니트로 이동하여 "ServerMethodsUnitSession"으로 저장하고 서버 클래스 이름을 "TServerMethodsSession"으로 변경하나다.

6. 위의 소스를 복사한다.

7. 새로운 unit를 추가하고 "ServerMethodsUnitServer"로 저장하고 유니트에 6의 복사된 내용을 붙이기한다.

8. 클래스 이름을 TServerMethodsServer"로 변경한다.

9. 같은 방법으로  "ServerMethodsUnitInvocation.pas", "TServerMethodsInvocation"으로 변경한다.

10. 마지막 작업은 3개의 DSServerClass 컴포넌트에 대해 아래와 같이 OnGetClass 이벤트를 구현한다.

implementation

{$R *.dfm}

uses
   ServerMethodsUnitSession, ServerMethodsUnitServer,
   ServerMethodsUnitinvocation;


procedure TServerContainer1.DSServerClass_InvocationGetClass(
  DSServerClass: TDSServerClass; var PersistentClass: TPersistentClass);
begin
  PersistentClass := TServerMethodsInvocation;
end;


procedure TServerContainer1.DSServerClass_ServerGetClass(
  DSServerClass: TDSServerClass; var PersistentClass: TPersistentClass);
begin
  PersistentClass := TServerMethodsServer;
end;

procedure TServerContainer1.DSServerClass_sessionGetClass(
  DSServerClass: TDSServerClass; var PersistentClass: TPersistentClass);
begin
  PersistentClass := TServerMethodsSession;
end;

end.

11. 이제 서버가 준비되었다.  서버를 실행한다.

12. 클라이언트 프로젝트로 전환하여."SQLConnection1 컴포넌트의 Connected 속성을 false로 설정한 다음 다시 true로 설정하여 최신 버전의 서버에 연결되어 있는지 확인한다.

13. SQLConnection1 컴포넌트를 마우스 오른쪽 버튼으로 클릭하고 컨텍스트 메뉴에서 Generate DataSnap Client Class"을 선택하여 프록시 소스 코드를 재생성한다. 모든 서버 메소드 클래스에 대해 생성된 해당 클라이언트 클래스가 있으므로 이제  클라이언트  클래스3개가 있는것을 확인 할 수 있다.

14. 클라이언트 폼에  두 개의  버튼와 두 개의 레이블을 추가하고 아래와 같이  코드를 추가한다.

procedure TForm_Client.Button1Click(Sender: TObject);
var
aClient: TServerMethodsServerClient;
begin
  aClient := TServerMethodsServerClient.Create(
    SQLConnection1.DBXConnection);
  try
    Label1.Caption := aClient.GetID;
  finally
    aClient.Free;
  end;

end;
procedure TForm_Client.Button2Click(Sender: TObject);
var aClient: TServerMethodsSessionClient;
begin
  aClient := TServerMethodsSessionClient.Create(
    SQLConnection1.DBXConnection);
  try
    Label2.Caption := aClient.GetID;
  finally
    aClient.Free;
  end;

end;

procedure TForm_Client.Button3Click(Sender: TObject);
var aClient: TServerMethodsInvocationClient;
begin
  aClient := TServerMethodsInvocationClient.Create(
    SQLConnection1.DBXConnection);
  try
    Label3.Caption := aClient.GetID;
  finally
    aClient.Free;
  end;
end;

15. 두개의 프로그램을 실행하면 두 클라이언트 모두 변경되지 않는 동일한 "서버 수명 주기" 인스턴스에 연결된다.

클라이언트마다 세션 인스턴스가 다르며 변경되지 않는다.

"호출" 버튼을 클릭할 때마다 다른 식별자가 표시된다. 이는 요청을 처리하는 다른 서버 메소드 클래스 인스턴스가 항상 있음을 의미한다.

image.png

샘플 소스 datasnp_lifecycle.zip

 

 

 

 

 

 

이 댓글 링크
다른 사이트에 공유하기

이 토의에 참여하세요

지금 바로 의견을 남길 수 있습니다. 그리고 나서 가입해도 됩니다. 이미 회원이라면, 지금 로그인하고 본인 계정으로 의견을 남기세요.

Guest
이 토픽(기고/질문)에 답하기

×   서식있는 텍스트로 붙여넣기.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   이전에 작성한 콘텐츠가 복원되었습니다..   편집창 비우기

×   You cannot paste images directly. Upload or insert images from URL.

 공유하기

×
×
  • Create New...

중요한 정보

이용약관 개인정보보호정책 이용규칙 이 사이트가 더 잘 작동하기 위해 방문자의 컴퓨터에 쿠키가 배치됩니다. 쿠키 설정 변경에서 원하는 설정을 할 수 있습니다. 변경하지 않으면 쿠키를 허용하는 것으로 이해합니다.