본문 바로가기

IT 살이/04. 기술 - 프로그래밍

IE 임베딩 방식 스마트클라이언트 애플리케이션의 도메인 중복 생성??

IE 임베딩 방식에서의 애플리케이션 도메인의 중복 생성 ??

현재 달봉이가 참여하고 있는 L 기업의 프로젝트에서는 Plumtree라는 EP 솔루션이 들어오기로 되어 있다. 시스템의 메뉴와 권한 관리는 이 EP 솔루션이 담당하고 업무 화면은 스마트클라이언트로 구현하겠다는 것이 대세가 되고 있는 분위기이다.

서버측 기술인 Plumtree 솔루션과 클라이언트측 기술인 스마트클라이언트를 같이 사용한다는 것 자체가 달갑지는 않다. 그러나 도입되는 솔루션과 기술을 결정하는 것은 다분히 기업들간의 영업적 성격이 강한 문제들이다. 이런 상황을 겪고 있자면 가끔 그런 유머가 생각난다. 펜대만 돌리는 경영자님께서 그랬단다. "왜 우리 회사는 오라클을 버리고 자바를 도입하지 않는거야? 통합성도 좋다는데!!"

하여튼 그런 식으로 간다면 가는 것이다. 결국 웹 페이지 하나에 스마트클라이언트 스마트클라이언트 컨트롤 하나씩을 임베딩 시키는 방식이 된다. 즉 최소한 메뉴 수만큼의 임베딩 페이지가 존재하게 되는 것이다.

그런데 어느 순간 달봉이의 뇌리를 스치는 question mark가 있었다. 끔찍한 생각이었다. 우선 그 끔찍한 의문이 나오기까지의 근거가 된 달봉이의 KB를 말한다.


■ 달봉이의 KB(Knowledge Base)

스마크클라이언트 컨트롤을 로딩하기 위한 <object> 태그의 형식은 다들 알고 있을 것이다

<OBJECT id="SmartClientControl"
classid="어셈블리명(경로포함)#네임스페이스를 포함한 클래스명" >

스마트클라이언트 컨트롤을 가지고 있는 웹 페이지가 호출되면 클라이언트측에서는 하나의 "애플리케이션 도메인(application domain)"이 생성된다는 것은 이야기 한적이 있다( 없나? ). 

2009/04/23 - [01. 기술-APP] - 애플리케이션 도메인과 속성들(베이스 디렉토리)

애플리케이션 도메인이 생성되고 나서 <object> 태그에서 지정한 어셈블리를 그곳으로 로딩시킨다. 그리고 나서 마지막으로 컨트롤의 인스턴스를 생성하는 것이다.

그리고 IE 임베딩 방식의 스마트클라이언트 애플리케이션에서는 생성된 애플리케이션 도메인은 IE 브라우저가 닫히기 전에는 언로드 되지 않는다. 즉 IE 프로세스가 끝나야 그곳에 포함된 애플리케이션 도메인도 없어진다.

또 한가지, 하나의 OS 프로세스에는 여러 개의 .NET 애플리케이션 도메인이 생성될 수 있다. 애플리케이션 도메인들은 각각 독립된 공간으로서 다른 도메인의 어셈블리에는 접근할 수 없다(다른 도메인의 어셈블리에 접근하는 것이 조치를 취하면 불가능한 것은 아니지만 이것이 기본적인 내용이다).

달봉이가 가지고 있는 KB를 좀 더 자세히 보고 싶다면 앞의 포스트를 읽어 보기 바란다.

Question

그렇다면 <object> 태그가 호출될때마다 애플리케이션 도메인이 생성되면 어떻게 되나? 그럼 동일한 메뉴를 클릭할 때마다 다른 애플리케이션 도메인이 생성되고 그리고 이미 동일한 어셈블리가 다른 도메인에 로딩되어 있는데도 다시 새로운 도메인으로 로딩되는 것은 아닐까? 그럼 메모리 사용량은? 순간 끔찍했다. 즐거운 토요일이었으나 바로 테스트를 해 봐야 했다.
다음은 간단한 테스트 내용이다. 정확히 하려면 애플리케이션이 생성될때 마다 로그를 남겨서 확인하는 방법을 택할 수도 있었지만 밖에서는 식구들이 쇼핑을 갈 준비를 하고 있었다. 애플리케이션 도메인 생성시 참여할 수 있는 방법에 대해서는 다음 포스트에서 다룰 생각이다.

2009/04/23 - [01. 기술-APP] - 기본 AppDomain 생성자 변경하기


테스트 1

테스트 #1

 

두개의 프레임으로 구성되어 있다. 좌측에는 두 개의 메뉴가 있다. 메뉴 1을 클릭해서 winform1.aspx를 호출했다. 이 aspx 페이지에는 그림처럼 두 개의 컨트롤이 각각의 <object> 태그로 로딩되어 있다. 그리고 위쪽 컨트롤의 "Set Value" 버튼을 클릭하면 다음과 같은 코드가 수행된다.

private void button1_Click(object sender, System.EventArgs e)
{
AppDomain.CurrentDomain.SetData("test", "value from domain1");
}

그리고 아래 컨트롤의 "Get Value" 버튼의 클릭 핸들러는 다음과 같다.

private void button1_Click(object sender, System.EventArgs e)
{
object o =AppDomain.CurrentDomain.GetData("test" );
if( o != null )
MessageBox.Show( o.ToString() );
else
MessageBox.Show( "원하는 값이 없습니다.");
}

"Set Value" 버튼을 클릭하면 CurrentDomain에 "test"라는 이름의 속성에 문자열 "value from domain1"이 값으로 저장된다. "Get Value" 버튼을 클릭하면 CurrentDomain의 "test" 속성값을 가져와서 출력한다. 만약 두 개의 컨트롤이 다른 애플리케이션 도메인에서 생성되어 있는 상황이라면 "Get Value" 버튼 핸들러가 제대로 작동하지 않아야 한다. "Set Value"버튼을 클릭했다. 그러나 제대로 출력되었다.

테스트결과#1

그렇다면 두 개의 <object> 태그로 어셈블리를 로딩해도 같은 도메인으로 로딩된 것이다.

메뉴 2를 클릭해서 winform2.aspx를 호출했다. 출력된 컨트롤의 "Get Value" 버튼을 클릭해도 도메인 저장소에서 값을 구할 수 있었다. 달봉이는 여기서 잠시 고민을 했다.

클라이언트측의 .NET 프레임워크에서는 어떻게 새로운 애플리케이션 도메인을 생성할지 말지를 결정하는 것일까? 조금 후 애플리케이션의 베이스 디렉토리값이 도메인의 고유 아이디로 사용될 수 있을 것이라는 추측을 하게 되었다. 즉 aspx에 설정된 베이스 디렉토리가 다르다면 어떻게 될까라는 생각을 하게 되었다. 추측대로라면 에러가 발생해야 한다. 테스트를 다시 수행했다.

테스트 2

테스트 #2

메뉴 2에 연결된 winform2.aspx에서는 베이스 디렉토리 값을 달리 줬다.

winform1.aspx 에서는
<link
rel=Configuration
href="http://localhost/AppDomainTestWeb/base1/controls.xml"/>

winform2.aspx 에서는
<link
rel=Configuration
href="http://localhost/AppDomainTestWeb/base2/controls.xml"/>

그런 다음 winform1.aspx의 "Set Value" 버튼을 클릭해서 문자열을 도메인의 공용 저장소에 저장하고 그리고 다시 winform2.aspx에서 "Get Value" 버튼을 이용해서 해당 이름의 값을 구하려고 했다. 그런 값을 찾을 수 없다는 에러였다.

 

테스트결과 #2 


이 결과를 다시 한번 더 확인하기 위해서 IEHost.dll이 남긴 로그를 검토해봤다. IEHost.dll가 로그를 남기도록 하는 설정은 디버깅 툴을 소개하면서 같이 설명했다.

2009/04/23 - [01. 기술-APP] - 스마트클라이언트 디버깅 툴 소개

 

다음은 winform1.aspx를 호출하면서 남긴 로그의 일부분이다. 먼저 WindowsControlLibrary1.UserControl1을 생성하면서 남긴 로그이다.

Microsoft.IE.SecureFactory:
Locating domain for http://localhost/AppDomainTestWeb/base1/
Microsoft.IE.IDKey: Created key
Microsoft.IE.Manager: The domain does not exist.
...
Microsoft.IE.SecureFactory:
Application base: http://localhost/AppDomainTestWeb/base1/
...
Microsoft.IE.SecureFactory:
Trying to create instance of type
http://localhost/AppDomainTestWeb/WindowsControlLibrary1.DLL
#WindowsControlLibrary1.UserControl1

베이스 디렉토리값 "http://localhost/AppDomainTestWeb/base1/" 에 해당하는 도메인을 찾을 수 없어 도메인을 생성한다는 내용이 있다.

다음은 WindowsControlLibrary2.UserControl1 컨트롤을 생성하면서 남긴 로그의 부분이다.

Microsoft.IE.SecureFactory:
Locating domain for http://localhost/AppDomainTestWeb/base1/
...
Microsoft.IE.SecureFactory: Do not have to create new domain

"http://localhost/AppDomainTestWeb/base1/" 에 해당하는 도메인이 이미 생성되어 있다는 내용이다.

다음은 베이스 디렉토리를 다르게 설정한 winform2.aspx에서 WindowsControlLibrary2.UserControl1를 생성하면서 남긴 로그의 부분이다.

Microsoft.IE.SecureFactory:
Locating domain for http://localhost/AppDomainTestWeb/base2/
Microsoft.IE.IDKey: Created key
Microsoft.IE.Manager: The domain does not exist.
Microsoft.IE.IDKey: Created key
Microsoft.IE.Manager: The domain does not exist.

베이스 디렉토리 값 "http://localhost/AppDomainTestWeb/base2/"에 해당하는 도메인이 없기에 새롭게 생성한다는 내용이다.

테스트 결과

정리하면 모든 웹 페이지의 베이스 디렉토리 설정만 같다면 웹 페이지 하나에 컨트롤 하나를 로딩시키는 구조로 가더라도 메뉴를 클릭할때 마다 애플리케이션 도메인을 생성하고 어셈블리를 도메인별로 중복해서 로딩시킬 일은 없을 것이다. 다행한 일이다.

그러나 이렇게 메뉴가 웹 페이지에 있는 구조가 마음에 든다는 것은 아니다. 이런 구조는 스마트클라이언트 컨트롤에서 웹 페이지를 제어하는 일 예를 들어 특정 메뉴를 디자인적으로 토글시킨다든가 하는 일은 여전히 힘들다.

하여튼 달봉이는 느긋한 마음으로 식구들과 함께 쇼핑을 하러 갈 수 있었다. 므흣~