SimpleIsBest.NET

유경상의 닷넷 블로그
이 글은 오래된 전에 작성된 글입니다. 따라서 최신 버전의 기술에 알맞지 않거나 오류를 유발할 수 있습니다. 저자는 이 글에 대한 질문을 받지 않을 것입니다. 하지만 이 글이 리뉴얼 되면 이 글에 대한 질문을 하거나 토론을 할 수도 있습니다.

스마트 클라이언트 시리즈 5번째 글입니다. 설 연휴와 여러 회식자리로 인해 좀 늦게 글을 쓰게 되었습니다. 혹시나(설마~) 기다리신 분이 계셨다면 죄송합니다만... 너무 목메고 기다리시지 않으시길 바랍니다... -_-;

스마트 클라이언트에 대한 자료를 찾기가 쉽지 않은 상황에서, 좀 테스트를 해보려고 하면 잘 안 되는 경우가 허다 합니다. 무슨 예외 메시지라도 나타나면 어케 대처를 해보겠는데, 화면에 아무 것도 나타나지 않고 잠잠하다던가, 브라우저 임베디드 스마트 클라이언트 구현 시, 브라우저 상에 댑쑝 큰 컨트롤 박스(화면2 참조)가 나타난다든가 하는 현상은 원인을 파악하기 쉽지 않습니다. 몇 번이고 제길슨을 외치면서 다시 해 보아도 결과는 마찬가지이고 인터넷 검색을 해 보든, 내노라 하는 개발자 커뮤니티를 검색해 보든 원하는 내용도 보이지 않으며, 질문을 올려봐도 대답해 주는 사람도 없곤 합니다. 스마트 클라이언트의 진입 장벽이라고 할까요?

이번 포스트에서는 스마트 클라이언트 시나리오상에서 발생할 수 있는 전형적인 문제들과 이들 문제의 원인을 파악하는데 도움이 되는 도구와 팁을 소개할까 합니다. 여기서 다루는 내용이 모든 상황을 커버할 수 없음을 이해해 주시기 바랍니다. 다만 앞서 다룬 스마트 클라이언트, 그것을 알려주마 (III) : 작동 원리 글과 스마트 클라이언트, 그것을 알려주마 (IV) : App Base Directory & Configuration 글 그리고 앞으로 다루게 될 Code Access Security 및 DLL 이 다운로드 되는 상황 등을 정리해서 천천히 생각해 보면 원인을 찾는데 도움이 되리라 생각됩니다.


시리즈 목차

Smart Client (IV) : Trouble Shooting

스마트 클라이언트를 구현할 때 항상 까다로운 것이, 당췌 문제의 원인 파악이 쉽지 않다는 것이다. 필자도 처음 이 놈을 접했을 때 마찬가지였다. "아이 C8 왜 나만 안 되는겨?" 를 수없이 부르짖고 Reflector로 닷넷 프레임워크의 내부를 까보고, 다양한 테스트를 해 본 후라야 그 원인을 겨우 찾을 수 있었다. 물론 관련 자료를 찾는 것 역시 존나게 힘들다. 닷넷 스마트 클라이언트는 상당히 매력적인 기술이지만 정말 똥줄 타게 만드는 기술인 것이다.

이번 포스트에서는 스마트 클라이언트를 처음 테스트하고 접했을 때 자주 접하게 되는 몇몇 문제점과 이들 문제의 원인을 파악하는데 도움을 주는 팁과 유틸리티를 소개하고자 한다. 여기서 다루는 내용은 스마트 클라이언트를 처음 접하는 사람들이 겪는 기본적인 문제를 다루고 있다. 예를 들자면, 아조 간단하다고 생각되는(필자만의 생각일지도 모르지만) 지난 스마트 클라이언트, 그것을 알려주마 (II) : 맛보기 예제 를 따라 하려고 해도 제대로 작동하지 않는 몇몇 경우에 대한 답을 여기서 얻을 수 있을 것이다. 하지만 좀 더 진보된 질문들, 예를 들어 클라이언트에 Code Access Security 설정은 어떻게 하면 좋은가 라든가, DLL 이 업데이트 되었지만 어떤 경우에는 다운로드 되고 어떤 경우에는 안 된다든가 하는 중/고급(?) 문제 해결은 이어지는 시리즈에서 다루게 될 것이다 (필자가 거의 미친 것 같다. 당췌 얼마나 길게 시리즈를 연재하려고 하는 것인지... -_-).

Checking download

가장 기본적인 실수는 URL을 잘못 기술하는 것이다. URL 내에 포함된 단어의 스펠링을 틀린다던가 파일 이름을 잘못 쓴다던가 등등... 이런 경우가 없을 것 같지? 그렇지 않다. 누구나 실수는 할 수 있기 때문에 OBJECT 태그의 classid 속성에 잘못된 URL을 써 넣는다든가, A 태그 혹은 브라우저 주소 창에도 EXE에 대한 잘못된 URL을 명시할 수 있다. 이러한 실수는 매우 기초적인 오류이지만 찾기 쉽지 않다. 무슨 초딩도 아니고 글씨를 잘못 써서 오류가 나리라고 생각하지 않기 때문이다.

스마트 클라이언트를 테스트 할 때는 무엇보다도 스마트 클라이언트 모듈(DLL 혹은 EXE)이 다운로드 되는지 확인 사살해야만 한다. 일단 DLL 이나 EXE 가 다운로드 되어야만 스마트 클라이언트든 더미 클라이언트든 해먹을 것이 아닌가? 정확하게 스마트 클라이언트 모듈이 다운로드 되는지 확인하기 위한 방법은 네트워크 모니터링 도구나 HTTP 모니터링 도구를 사용하는 것이 최고다.

기본적으로 Windows 에 설치할 수 있는 네트워크 모니터는 네트워크 패킷을 죄다 캡처 하는 능력을 가지고 있다. 하지만 스마트 클라이언트는 HTTP를 사용하므로, TCP/IP 패킷 등은 머리만 아플 뿐 도움이 되지 않는 경우도 많다. 따라서 필자는 Fiddler 라는 도구를 즐겨 사용한다. Fiddler는 스마트 클라이언트 뿐만 아니라 HTTP 관련 프로그램(웹 어플리케이션, 웹 서비스 호출 등등)을 디버깅하는데 없어서는 안 될 도구이다. Fiddler는 무료로 사용할 수 있는 도구이다. 마이크로소프트의 개발자가 개발한 것으로 보이는 이 개발 툴은 닷넷 프레임워크 1.1을 이용하여 개발한 도구이므로 닷넷 프레임워크 1.1 이상이 설치되어 있어야 한다.

화면1은 필자가 작성한 스마트 클라이언트 예제에서 브라우저 임베디드 스마트 클라이언트의 라이브 예제를 수행할 때를 Fiddler로 캡처한 모습이다. 정확하게 스마트 클라이언트 모듈인 ClientModule.DLL 이 다운로드 되고 있음을 확인하자. 즉 HTTP 결과 코드가 200 인가를 확인해야만 한다. 만약 URL이 잘못되었다든가 DLL 파일 이름을 잘못 적었다든가, DLL 이 서버에 존재하지 않는다든가 등의 문제가 발생하면 HTTP 결과 코드는 200 이 아닌 404(NOT FOUND)가 나타날 것이다. 추가적으로 오른쪽 하단 패널에서 다운로드 된 콘텐트의 MIME 타입이 application/x-msdownload 임도 확인하자. 이 MIME 타입 덕에 스마트 클라이언트가 구동됨은 스마트 클라이언트, 그것을 알려주마 (III) : 작동 원리에서 밝힌바 있다.


화면1. 브라우저 임베디드 스마트 클라이언트가 구동될 때의 상황을 Fiddler로 캡처 한 모습

화면1에서는 또 흥미로운 것을 보여주는데, 먼저 iexplore.exe.config를 다운로드 하려고 한다는 점이다. 왜 이 .config 파일을 다운로드 하려고 하는가는 스마트 클라이언트, 그것을 알려주마 (IV) : App Base Directory & Configuration 포스트에서 어플리케이션 도메인과 configuration 파일 관련 부분을 설명할 때 이미 설명했다.

또 한가지 이상한 것은 다운로드 하고자 하는 DLL (/Apps/SmartClientBasic/ClientModule.DLL)을 제외하고 이상한 DLL/EXE를 다운로드 하려고 시도한다는 점이다. 이는 닷넷 프레임워크가 스마트 클라이언트 시나리오를 통해 구동될 때, 새로운 어플리케이션 도메인으로 해당 모듈을 로드 할 때 발생하는 현상으로 configuration을 명시하지 않았기 때문에 발생한다. 스마트 클라이언트, 그것을 알려주마 (IV) : App Base Directory & Configuration에서 이미 명시하였듯이 configuration 파일이 명시되지 않으면 생성되는 어플리케이션 도메인의 베이스 디렉터리는 루트로 설정되어 버린다. 따라서 루트에서 DLL을 로드하려고 시도하기 때문에 일련의 404 NOT FOUND 가 발생한다. 이를 제거하기 위해서는 명시적으로 configuration 파일(비록 그것이 비어 있더라도)을 지정해 주면 된다. 굳이 이렇게 configuration 파일을 지정하지 않더라도 스마트 클라이언트가 구동되는 데는 지장이 없지만 클라이언트와 서버 사이에 8회 이상의 라운드 트립(round-trip)이 발생한다면 스마트 클라이언트 구동 시간이 늦어지게 되므로 좋지는 않다. 그리고 수백 수천 사용자가 스마트 클라이언트를 사용한다면 수만, 수십만개의 404 NOT FOUND 가 웹 서버 상에 발생하게 되므로 웹 서버의 부하도 증가하므로 더욱 좋지 않음을 기억해 두자.

(화면1에서 그외의 .css, .js 파일은 필자의 사이트에서 로깅을 위해 사용하는 java script 파일이므로 걍 무시하자.)

IEHost.dll Debugging Message

독립 스마트 클라이언트는 별도의 IEExec.exe 프로세스에 의해 URL로 주어진 .exe 파일이 로드 되고 수행된다. 이 과정에서 어떠한 예외(exception)이 발생하면 그것은 곧바로 화면에 표시되게 된다. 클라이언트 컴퓨터 설정에 따라 구체적인 예외 메시지가 나타날 수 도 있고 오류 보고 다이얼로그가 나타날 수도 있다.

그러나... 임베디드 스마트 클라이언트는 스마트 클라이언트 초기화 시에 발생하는 예외는 조용히 IEHost.dll 이 먹어 버린다. 즉, IEHost.dll 이 어플리케이션 도메인을 생성하고 초기화 한 후, OBJECT 태그의 classid 에 의해 지정된 클래스의 인스턴스를 만드는 초기화 과정에서 발생되는 모든 예외는 사용자에게 아무런 피드백이 발생하지 않는다는 것이다. 이 때문에 브라우저 임베디드 스마트 클라이언트가 좀 더 어렵게 느껴지는 것이다. 당췌 예외 메시지를 봐야 원인이 무엇인지 겐또 라도 때려볼 것 아닌가?

왜 IEHost.dll 이 예외를 쳐 먹어 버리는가는 필자도 확실하지 않다. 다만 ActiveX 활성화 과정에서 예외 메시지를 UI (메시지 박스 혹은 다이얼로그)로 표시하기 어려웠으리라 추측만을 할 뿐이다. 스마트 클라이언트 뿐만 아니라 일반 C++, VB, Delphi 로 작성한 ActiveX 컨트롤도 classid 가 잘못되거나 초기화가 잘 못되면 화면2와 같은 쥐랄 맞은 컨트롤 박스가 나타나는 것은 독자들도 잘 알고 있을 것이다.


화면2. 원인을 알 수 없는 쥐랄 맞은 컨트롤 박스

마이크로소프트의 닷넷 프레임워크 팀이 짱구들이 아닌 이상 이러한 문제를 모를 리가 없다. KB를 잘 뒤져보면 IEHost.dll 이 초기화 시에 발생하는 행동을 로그로 남기도록 레지스트리를 설정하는 방법이 나와 있다. 이 레지스트리 설정은 다음과 같다.

  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\DebugIEHost (DWORD)
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\IEHostLogFile (REG_SZ)

먼저 DebugIEHost 값은 IEHost.dll 이 어플리케이션 도메인을 생성하고 configuration 파일을 결정하는 등의 작업을 수행할 때 관련 행동을 로그 파일로 기록할 것인가를 결정한다. 이 값은 기본적으로 설정되어 있지 않으며, 이 값이 설정되더라도 0의 값을 가지면 로그는 기록되지 않는다. 이 값이 1이면 IEHost.dll 은 로그를 기록한다. IEHostLogFile 값은 로그를 남길 파일이름을 지정하는데 사용된다. 이 값에 유효한 절대 파일 경로가 반드시 명시 되어야만 로그를 구경할 수 있다. 예를 들어 IEHostLogFile 을 C:\DebugIEHost.log 로 설정했다면, 로그 파일은 C:\DebugIEHost.log1 이란 파일이 생성되게 된다(마지막에 숫자 1이 붙는다. 이유는 저도 잘 모르겠심더... -_-;).

백문(百聞)이 불여일견(不如一見)이요, 백견(白見)이 불여일 Run 이라 했다. 테스트를 해보자. 지난 맛보기 예제에서 사용한 임베디드 스마트 클라이언트의 UIControl 클래스의 생성자에 강제로 예외를 발생시는 코드를 추가한다.

// 생성자

public UIControl()

{

??? throw new Exception("테스트 예외... 요게 보이니?");

??? InitializeComponent();

}

리스트1. 강제 예외 발생 코드

로그 파일을 구경하기 위해 생성자에서 예외 코드를 집어넣어야 하는 이유는, 앞서도 언급했듯이 IEHost.dll 이 스마트 클라이언트를 초기화하는데 관여되고, 초기화 과정 중의 하나가 OBJECT 태그의 classid 속성에 명시된 클래스의 인스턴스를 생성하는 것이기 때문이다. 물론 초기화가 성공적으로 완료되고 발생되는 예외(예를 들어 Load 이벤트에서 발생하는 예외)는 화면상에 예외 대화 상자가 이뿌게 나타난다.

어쮜 되었건, 리스트1과 같이 예외를 강제로 발생시키도록 코드를 수정하고 스마트 클라이언트를 구동해 보자. 그러면 레지스트리에 설정한 로그 파일에 로그가 기록되어 있을 것이다. 로그 파일의 내용은 리스트2와 같다.

Creating security manager

Microsoft.IE.Manager: Microsoft.IE.Manager: unique id lgth = 44
Microsoft.IE.SecureFactory: Create SecureFactory() with security information
Microsoft.IE.Manager: Created secure factory
Microsoft.IE.SecureFactory: Creating instance of the object in the correct domain
Microsoft.IE.SecureFactory: pUrl = http://localhost.com/SmartClientBasic/SmartClient.htm
Microsoft.IE.SecureFactory: id = 86474707A3C6F63616C686F63747E236F6D630000000
Microsoft.IE.SecureFactory: link =
Microsoft.IE.SecureFactory: licenses =
Microsoft.IE.Manager: Url = http://localhost.com/SmartClientBasic/SmartClient.htm
Microsoft.IE.Manager: UrlGetPartW returned 80070057
Microsoft.IE.Manager: CodeBase = http://localhost.com
Microsoft.IE.Manager: Application = SmartClientBasic
Microsoft.IE.Manager: Found a codebase
Microsoft.IE.Manager: UrlCanonicalize returned 0
Microsoft.IE.SecureFactory: URL codeBase: http://localhost.com/
Microsoft.IE.SecureFactory: URL application: SmartClientBasic
Microsoft.IE.SecureFactory: Locating domain for http://localhost.com/
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.
Microsoft.IE.SecureFactory: Need to create domain
Microsoft.IE.SecureFactory: Application base: http://localhost.com/
Microsoft.IE.SecureFactory: Private Bin Path: bin
Microsoft.IE.IDKey: Created key
Microsoft.IE.SecureFactory: Trying to create instance of type http://localhost.com/SmartClientBasic/ClientModule.DLL#ClientModule.UIControl
Microsoft.IE.SecureFactory: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Exception: 테스트 예외... 요게 보이니?
at ClientModule.UIControl..ctor()
--- 내부 예외 스택 추적의 끝 ---

Server stack trace:
at System.RuntimeType.CreateInstanceImpl(Boolean publicOnly)
... 이하 생략 ...
 

리스트2. IEHost.dll 이 생성한 로그 파일 내용 예제

노란색으로 졸라 강조해 놓은 부분을 살펴보자. 먼저 생성되는 어플리케이션 도메인의 베이스 디렉터리가 어떻게 설정되나를 보여주고 있다. 기본 예제에서 Configuration 파일을 지정하지 않았으므로 루트 URL이 베이스 디렉터리로 설정되었음을 확인하자(지난 포스트에서 이미 설명한 바 있다). 그 다음은 OBJECT 태그의 classid 속성에 지정한 클래스의 인스턴스를 생성하려고 하고 있음을 알 수 있다. 우리가 코드에 강제로 예외를 발생시켰으므로 해당 예외의 정보를 호출스택을 포함하여 상세히 기록하고 있다.

리스트2와 같은 로그 파일은 왜 브라우저 임베디드 스마트 클라이언트가 구동되지 않는가에 대한 답을 제시해 주곤 한다. 브라우저 임베디드 스마트 클라이언트 개발자라면 반드시 앞서의 레지스트리 설정을 수행하고 필요할 때마다 로그 파일을 참조해야 한다.

때로는 화면2와 같은 컨트롤 박스가 나타나는데, DebugIEHost 로그 파일이 생성되지 않는 경우도 있다. 즉, 로그 파일을 삭제하고 테스트를 수행했을 때 화면2와 같이 컨트롤 박스가 나타나지만 로그 파일은 존재하지 않는 경우이다. 이는 IEHost.dll 이 수행되기 전에 무언가 문제가 있는 것이다. 일단 IEHost.dll 이 초기화 작업을 수행하면 로그 파일은 무조건 생성되기 때문이다. 이러한 상황이라면 Fiddler를 통해 DLL이 제대로 다운로드 되는지, 또 서버에서 DLL이 다운로드 될 때 MIME 타입을 제대로 설정해 주는지 확인해야 한다. 또한 닷넷 프레임워크가 정상적으로 설치되지 않는 경우도 있을 수 있다.

Code Access Security

대개의 경우, 스마트 클라이언트에 태클을 거는 놈은 Code Access Security (CAS) 이다. CAS에 대해서는 다음 포스트에서 등장 배경, 적용 과정, 설정 방법 등을 살펴볼 것이다. 여기에서는 CAS의 디폴트 설정이 스마트 클라이언트에 어떤 영향을 주는지 대표적인 몇 가지 사항만을 살펴보도록 하겠다. 이 글은 레퍼런스가 아니다. CAS 권한에 대한 상세한 내용은 MSDN을 참고하기 바란다... 이렇게 말하면 항상 불만을 가지는 사람들이 있다. 이런 사람들은 호강에 초쳐서 요강에 헤딩하는 인간이라고 밖에 보이지 않는다. 이정도 가이드를 해 주었으면 실제 자신에게 부닥친 문제는 자기가 찾아 봐야 할 것인데, 두세 살 짜리 오줌싸개도 아니면서 떠먹여 주길 바라는 것은 도둑심보라 아니할 수 없다.

기본적으로 스마트 클라이언트 모듈이 다운로드 되면, 다운로드 된 곳(URL)이 인터넷상의 영역(zone)에서 어디인가에 따라 CAS 권한이 달라진다. 예를 들어 다운로드 한 호스트가 www.simpleisbest.net 라면, 일반적으로 이 호스트는 "인터넷 영역"이 된다. 만약 이 호스트를 신뢰된 사이트에 등록해 놓았다면 영역은 "신뢰된 사이트 영역"이 될 것이고, 인트라넷 사이트에 등록해 놓았다면 "인트라넷 영역"이 될 것이다. 인터넷 영역을 설정하는 방법은 브라우저의 옵션메뉴를 선택하면 나타나는 "인터넷 옵션 대화상자"의 보안 탭에서 설정할 수 있다. 기본 설정상 로컬 시스템 영역을 제외한 어떤 영역이건, 그 권한은 상당히 제약적이다.

CAS는 이렇게 영역별로 서로 다른 권한을 준다. 그 중 인터넷 영역에 대해서는 매우 제한적인 권한만을 허용하고 있다. 예를 들어 인터넷 영역에서 다운로드 된 어셈블리(DLL, EXE)는 로컬 파일 시스템에 대해 IO가 불가능하다. 다만, "파일 열기" 대화 상자를 통해서는 파일을 열 수 있다. 이는 사용자가 파일을 선택하는 동의 절차 없이 임의의 파일을 열 수 없도록 하는 보안 설정이라 보면 된다. 그 외에도 인터넷 영역의 CAS 설정은 레지스트리 액세스는 물론이요 P/Invoke 선언이 불가능하며 리플렉션(reflection)도 사용할 수 없고, 쓰레드를 제어할 수 없을 뿐더러, 데이터베이스 접속은 물론이요 소켓까지 액세스 할 수 없다. 다만 어셈블리를 다운로드 한 사이트에 대해 HTTP 액세스는 가능하다. 정확한 CAS 설정은 MSDN과 .NET Configuration MMC를 통해 설정을 참고하기 바란다.

HTTP 액세스에 대해서는 약간의 부연 설명을 하자면, 기본 CAS 설정은 어셈블리가 다운로드 된 사이트에 대해서만 HTTP 액세스를 허용한다. 예를 들어 DLL 이 www.simpleisbest.net 에서 다운로드 되었다면 HttpWebRequest 클래스는 http://www.simpleisbeste.net 으로 시작하는 URL에 대해서만 액세스를 허용한다는 것이다. 이외의 IP, 호스트 이름은 모두 SecurityException을 유발하게 됨을 잘 이해하자.

예를 들어 보자. 우리의 지난 예제인, ClientModule.dll 을 수정하여 썰렁한(?) 기본 데이터 그리드가 아닌 상용 그리드(Flex Grid 같은) 를 사용하기로 했다고 해보자. 상용 그리드로 디자인을 하고, 코드를 수정하고 로컬 컴퓨터에서 테스트 해보면 잘 작동할 것이다. 그리고 DLL을 스마트 클라이언트 시나리오에서 테스트 해보면 아마도 짜증나는 컨트롤 박스가 나타나던가(브라우저 임베디드 스마트 클라이언트. 앞서 언급한 IEHost 로그 파일을 살펴보아야 한다), SecurityException (독립 스마트 클라이언트)가 발생할 것이다. 이유는 이렇다. 대개의 상용 컨트롤은 Win32 API를 직접 호출하여 자신의 기능을 구현하곤 한다. Win32 API를 호출하기 위해서 런타임은 P/Invoke 호출을 수행할 것이다. 하지만 기본 설정상 스마트 클라이언트는 P/Invoke 에 대한 CAS 권한을 가지고 있지 않다. 이런 이유로 SecurityException 이 발생하는 것이다.

그렇다면 이를 어떻게 극복해야 할까? 그것은 작성하고자 하는 스마트 클라이언트가 어떤 것이냐에 따라서 달라진다. 불특정 다수(사실 클라이언트 PC에 닷넷 프레임워크가 설치되어야 하므로 불특정이란 말은 좀 어폐가 있겠다)를 대상으로 하는 스마트 클라이언트라면 (예를 들어 업로드 컨트롤), 기본 권한이 허용하는 한도 내에서 UI 수준을 낮추던가 기능을 줄이는 방법을 통해 CAS의 심기를 건드리지 않는 것이 좋다. 하지만 사내 인트라넷과 같이 제한된 사용자를 대상으로 하는 스마트 클라이언트, 예를 들어 MIS 관리 시스템이나 영업 지원 시스템 등등, 이라면 각 클라이언트 PC마다 해당 스마트 클라이언트에 대한 CAS 설정을 하도록 강제함으로써 스마트 클라이언트가 보다 많은 권한을 갖도록 설정해 주는 것이 좋다. 각 클라이언트 PC에 CAS 설정을 수행하는 방법은 CAS 설정을 수행하는 코드를 작성하고 이것을 각 클라이언트에 .MSI 를 설치하고 수행하도록 하는 방법이나 ActiveX를 이용하여 자동으로 셋업이 진행되도록 하는 방법 등을 생각해 볼 수 있겠다. 구체적인 예제는 다른 포스트(스마트 클라이언트 고급 기법에 대한 포스트를 계획 하고 있다)에서 보여주기로 하고 여기서는 더 이상 논하지 않겠다.

Debugging Smart Client

스마트 클라이언트의 어려운 점 또 한가지는 디버깅이 용이하지 않다는 것이다. 뭐 일반적인 윈폼 어플리케이션이라면 그냥 비주얼 스튜디오의 디버깅 기능을 사용하면 간단할 터인데... 스마트 클라이언트는 그렇지 않다. 비주얼 스튜디오에서 디버깅을 걸기 애매하기 때문에 대개 "Process Debug" 기능(디버그 메뉴)을 통해 브라우저 혹은 IEExec.exe 프로세스를 attach 하는 방식을 사용해야 한다. 이렇게 하면 일반적인 이벤트 발생에 대해 break point를 설정하여 어느 정도 디버깅이 가능하다. 하지만 OBJECT 태그에 의해 생성되는 클래스의 생성자나 Load 이벤트에 대해서 break point를 설정할 수 없다. 왜냐면 디버거가 attach 된 후에라야 break point가 활성화 되는데, 일단 브라우저나 독립 스마트 클라이언트 프로세스가 기동되어야 프로세스를 attach 하던 말던 할 것 아닌가? 그리고 프로세스의 구동과 함께 생성자 혹은 Load 이벤트가 발생되어 버리기 때문에 attach 된 후에는 이 부분의 코드를 디버깅하기 어려워 지는 것이다.

스마트 클라이언트를 디버깅 하는 가장 일반적인 요령은, 로컬 컴퓨터에서 모든 테스트와 디버깅을 완료하는 것이다. 즉, 스마트 클라이언트 모듈(ClientModule.DLL)을 비주얼 스튜디오에서 개발할 때 이것을 테스트 하기 위한 더미 EXE 프로젝트를 만들고 이 EXE에서 스마트 클라이언트 모듈을 로드 하여(마치 지난 맛보기 예제의 Launcher.EXE 처럼) 수행하도록 하는 것이다. 이렇게 함으로써, 기본적인 스마트 클라이언트 모듈의 작동 유무를 완전히 파악하고 디버깅 한 후에, 웹 서버에 클라이언트 모듈을 올려 놓고 스마트 클라이언트 시나리오에서 다시 한번 테스트를 완료하면 될 것이다. 이렇게 함으로써 귀찮게 브라우저 프로세스나 IEExec.exe 프로세스를 attach 하는 불편함을 조금이나마 줄 일 수 있다.

또 한가지 디버깅의 문제는 앞서 언급한 대로 로컬 테스트는 잘 작동하지만, 스마트 클라이언트 시나리오에서는 제대로 작동하지 않는 경우를 생각해 볼 수 있겠다. 이러한 경우의 99%는 스마트 클라이언트 세팅이 잘못 되었다든가(URL을 잘 못 기록했다든지 등등), CAS 보안에 위배되는 경우이다. 이런 문제가 아님에도 불구하고 스마트 클라이언트 시나리오에서 반드시 디버깅을 해야 한다면 System.Diagnostics 네임스페이스의 Debugger 클래스를 사용하면 편리하다. Debugger 클래스의 Break() 메쏘드는 디버거의 break point 와 완전히 동일한 역할을 수행한다. 예를 들어 지난 맛보기 예제에서 사용한 임베디드 스마트 클라이언트의 UIControl 클래스의 생성자에 Debugger.Break() 메쏘드 호출을 추가하면 화면3과 같은 디버깅 대화상자가 나타날 것이다. 이 때 "다시 시도" 버튼을 선택하면 눈에 익숙한? JIT 디버거 선택 대화 상자가 나타나고 디버거를 선택하면 디버깅이 가능해 진다. 즉, 스마트 클라이언트의 생성자나 Load 이벤트와 같이 디버거를 attach 하여 디버깅 하기 힘든 상황에서도 디버깅이 가능하다는 것이다. 비록 코드를 수정하여 디버깅을 해야 하는 아픔이 있지만 당췌 디버깅을 못해 갑갑해 하는 것 보다는 100 배는 낫다.


화면3. Debugger.Break() 메쏘드 호출 시 나타나는 디버깅 대화상자

What's Next

이번 포스트는 정말 가볍게 팁 몇 가지를 적으려고 했지만 여전히 길어져 버렸다. 장문을 읽어 준 독자에게 심심한 감사를 드린다. 다음 포스트는 스마트 클라이언트의 최대의 난적 Code Access Security에 대해 언급할까 한다. 많은 닷넷 개발자들이 Code Access Security에 대해 한 두 번쯤 들어 보았겠지만, 사실 그것이 왜 등장했으며 어떤 방식으로 작동하는지 잘 모르는 경우가 많기 때문에, Code Access Security가 등장한 배경부터, 적용되는 방법 등을 살펴보도록 하겠다. 또한 스마트 클라이언트에서 Code Access Security를 설정하는 방법을 살펴보도록 하겠다. 다음 포스트는 상당히 방대한 내용을 요약해야 하기 때문에 시간이 좀 소요될 지도 모르겠다... 게다가 요즘 필자가 딴 데 정신이 팔려 있기 때문에... 다음 글이 빨리 올라오리라고 기대하는 것은 정신 건강에 해로울 것이다... 흐흐흐...



Comments (read-only)
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 앤시스 / 2006-02-07 오후 7:52:00
정말 머리에 쏙쏙 들어오는군요. ^^
좋은 포스트 감사하며 정신 건강을 좀 해치더라도 다음 포스트를 학수고대하겠습니다.~
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 매그넘 / 2006-02-09 오후 12:39:00
이렇게 많이 써주셨으나..... 아직도 목마릅니다. ㅎㅎㅎ 다음 포스팅을 기대하겠습니다.

#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / Chandler / 2006-02-09 오후 7:34:00
기다리고 있었습니다. ^^ 좋은 글 감사드립니다. ^^ 저두 다음을 기대하겠습니다.
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / Freecoder / 2006-02-10 오전 9:10:00
좋은데요 .. 뭔가 대략 중독되가는 느낌 .. ^^;; 다음글 기다하겠습니다.
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 제뤼 / 2006-02-13 오후 3:06:00
^^
다음편도 완전 기대하고 있습니다~
감사합니다~
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / bandb2002 / 2006-02-13 오후 4:15:00
글 잘보고 있습니다. 정말 도움이 많이 되네요.
모든 예제를 테스트해보니 잘됩니다.
그런데, 스마트클라이언트 구현을 마쳤고 테스트 pc들에서는 모두 배포가 잘~ 됩니다. 하지만,
정작 사용할 저희 갑(싸이트)는 active directory 정책에 막혀서 해당 정책이 적용된 싸이트엔 배포가 안됩니다. 헐~
Fiddler 로 찾아보면 해당 dll이 304에러가 나는군요 ㅡㅡ;
해결책이 없을까요?
정작 ad 정책때문에 안되는것이라면... 미리배포해서 사용하는 방법도 있다고 하던데.. 그 방법이라도 좀 알고싶거등요.
다 맹글어놓고 이기 문 날벼락인지...^^;

답변좀 꼭 부탁드립니다.
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 블로그쥔장 / 2006-02-15 오전 9:55:00
먼저 304는 오류가 아닙니다. 304 NOT MODIFIED 는 서버의 DLL이 변경사항이 없기 때문에
클라이언트에 (브라우저에 의해) 캐시된 DLL을 사용하라는 뜻입니다. 고로 오류가 아닌 좋은 반응이라 할 수 있겠습니다.
304가 많이 나면 날 수록 캐시가 잘 된다는 의미이므로...

따라서 304가 문제의 원인은 아닌듯 보이는 군요. AD 정책이 어떻게 설정되어 있는지 알 수 없지만
AD 정책에 의해 스마트 클라이언트가 배포가 안된다는 것은 좀 납득이 가지 않군요.
제 경험상 AD 정책이 스마트 클라이언트 배포를 막는 경우는 없었습니다만....

미리 배포를 하는 방법이 있을 수 있습니다만, 그것은 웹을 통해 변경된 DLL을 자동으로 배포하는
스마트 클라이언트의 장점을 포기하는 것입니다. 변경될 때마다 배포 패키지를 만들어 뿌려야 하기 때문에...
미리 배포하는 방법은 클라이언트 모듈을 MSI 로 묶어서 배포하는 거죠.
그리고 DLL을 regasm으로 등록하고(배포 패키지에 의해), 해당 UserControl을 표시할 때는
OBJECT 태그의 classid에 DLL의 URL 대신 clsid 값을 사용해야 합니다.
(완전히 ActiveX 사용법과 동일합니다.)
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / sadmong / 2006-02-17 오전 5:50:00
정말 잘 보았습니다 ^^;; 디버깅등등을 고려하지 않으면, ActiveX제작보다는 훨쉬운데.. 이것 저것 고려하니..
역시 그리 만만하지는 않군요 ^^
이제 여기 디버깅 방법으로 이전 예제를 좀 테스트 해봐야 겠네요 ^^
글쓰신 지가 얼마 되지 않으셧네요^^ 전 죽어도 이런거 못할거 같은데..
바쁘신중에도 이렇게 상세하게 글 올려주시는점에 깊이 감사드립니다.
영원한 애독자가 될것 같습니다 ^^
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / bandb2002 / 2006-03-10 오전 11:06:00
답변감사합니다. 304에러 운운했던 사람입니다.^^;
확인결과 저희 갑 싸이트의 AD정책중 인터넷영역 부분에 ".NET Framework 기반구성요소" 의 두항목이 사용안함으로 되있더군요. ㅡㅡ;
그래서, 해당 항목을 레지스트리로 강제로 사용함으로 수정을 했더니 잘되었습니다.

한가지 더 궁금한게 있는데요.
현재 설치된 Framework의 버전 샘플창에 나타나던데.. 어떤 함수나 코드를 사용하시는지요?
아무리 뒤져봐도 안보이네요 ㅡㅡ?

수고하세요.
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 블로그쥔장 / 2006-03-12 오후 9:36:00
관련 답변을 포스트로 올렸습니다. 약간 길어서리...

http://www.simpleisbest.net/archive/2006/03/12/564.aspx

도움이 되셨기를....
#이제 이글을 읽기 시작합니다. / 백의민족 / 2006-07-26 오후 8:05:00
너무 감사합니다.
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 워너비 / 2006-10-16 오후 4:36:00
질문이 있습니다.
브라우저에서 <object>태그로 dll을 사용하는 경우에,
Content-Type이 application/x-msdownload라고 나와야 하는데,
제경우에는, Fiddler로 보니깐
dll의 헤더값이 Content-Length=0이라고 나오고
Content_Type은 아예 나오지 않는 군요.

이런경우 세팅같은게 잘못되어 있는 건가요~?
답변 부탁드립니다~
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 블로그쥔장 / 2006-10-16 오후 4:54:00
세팅이 잘 못되어 있는지 정확하지는 않습니다.
정확히 해당 DLL을 다운로드 하려는 HTTP GET 에 대해 Content-Type 이 application/x-msdownload 가 아닌 경우라면
웹 서버 상의 설정을 의심해 볼 수 있겠습니다.
DLL이 존재하는 해당 디렉터리가 "수행" 권한을 갖고 있다면 DLL이 다운로드 되지 않고
ISAPI Extension으로 인식되어 버리기도 합니다.
웹 서버 설정을 다시 확인해 보시기 바랍니다.
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 이건 어떻게..... / 2006-10-16 오후 5:03:00
웹페이지에서 두개의 색상을 입력해서 폼을 전송하면
두 색 사이를 그라데이션 효과주면서 이어주는(?) 간단한 컴포넌트를 C#으로 만드는데요
스마트 클라이언트로 제작하려고 합니다.
일단 윈도 응용프로그램으로 만들어서 테스트 성공해서
DLL파일로 만들어 웹페이지에서 끼워넣고 테스트를 해봤는데
웹페이지에서 파라미터는 제대로 받아오는데 막상 테스트할때는 되던
색상표현이 안나타나내요........
에러가 나는건 아닙니다.
파라미터도 제대로 받고 색상을 그려주는 함수 내에서도
메세지박스 띄어서 확인해도 정상적으로 되는데 왜 화면에 색상이 안나타나는지
모르겠습니다.
스마트 클라이언트 활성화도 시켰고요.........
이런건 어떻게 해결하죠?...ㅜㅜ
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 블로그쥔장 / 2006-10-16 오후 7:48:00
글쎄요... 정확히 어떻게 그라데이션 효과를 주셨는지 알 수 없어서
정확한 답변을 드리기 어렵습니다만...
Draw 이후 발생하는 Paint 이벤트의 문제로 보입니다.
그라데이션 효과 이후 Invalidate류의 메쏘드를 호출하셨다면 Application.DoEvent()를 호출해 보시지요.
소스를 보내 주시는 것이 가능하시다면 소스를 메일로 보내주시면 검토해 보겠습니다.
#좀 다른 류의 문제.......내요....ㅡㅡ;; / ㅜㅜ / 2006-10-17 오후 3:06:00
스마트 클라이언트로 컴포넌트 만들고 브라우저에 끼워 넣었습니다.
작동은 정상적으로 잘되는데 폼을 프린트를 하니까 프린트가 안되더군여.....
스마트 클라이언트 위 모든 컨트롤들이 프린트를 하면 보이지가 않습니다.
모니터에서는 작동 잘하고 잘보이는데요......
프린트를 꼭 해야되는데 왜그런지....해결방법은 없는지 알고싶습니다.
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 이상하게 안되네요 / 2007-02-02 오후 3:43:00
이상하게 안되네요
HTTP GET 에 대해 Content-Type 이 application/x-msdownload 인데 dll이 다운로드 되지 않네요 웹서버 설정을 몇번을 확인했는데
왜 그런지... 알수가 없네요
조금 의심이 되는건 Fiddler 로 체크를 해봤더니... Caching 가 no-Cache Expires라는거....
어떻게 해야 하는지 알고 계신분 도움 요청합니다.
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 블로그쥔장 / 2007-02-04 오후 7:53:00
HTTP 결과가 200 OK가 나오거나 304 NOT Modified 라고 나오면
이미 다운로드가 된 것입니다.
이 경우 다운로드된 DLL이 구동되는 과정에서 오류가 발생한 것으로 보아야 합니다.
IEHostDebug 설정을 수행하여 로그 파일의 내용을 확인해 보십시요.
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 웹이아닌 파일로는 안되나요 / 2007-02-04 오후 10:15:00
저기 질문있는데요
스마트 클라이언트는 웹이 아닌 로칼에서 그냥 실행은 안되나요
http::// 이 방식이 아니라... d:\appweb\test.html 이렇게 는 스마트 클라이언트는 구동이 안되나요?
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 블로그쥔장 / 2007-02-05 오전 1:13:00
로컬에서 사용하는 방법은 전혀 접근방법이 다릅니다.
ActiveX 처럼 사용해야 하며, 이를 위해서는 어셈블리는 regasm.exe로 등록해야 합니다.
또한 OBJECT태그의 clsid 값을 줄때 DLL의 경로가 아닌 GUID를 명시해야 하죠.
(ActiveX와 같죠?)
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / 트러뷸 슈팅까지!! / 2007-02-14 오후 5:29:00
잘보고 있습니다.
컨트롤들이 하얀색으로 이상하게 나오는 것이 오류인줄 알고 한참 알아봤는데 304로 떨어지고, 따로 색상을 부여하니 정상으로 나오는듯 ㅎㅎ

처음 사용하는 tomcat으로 해서 삽질이 비약적으로 증가 한거 같네요

그리고 오류 보고 하나 !! 각 챕터 번호가 매치가 안되는거 같아요 목차에는 (V) 트러블 슈팅인데 내용에는 (IV) 트러블 슈팅이네요.. 사소한 오류..

강좌(?) 감사합니다~~

#re: 어렵....OTL / 희정 / 2007-04-17 오후 4:47:00
음...에헷..; 어렵네요.
그래도 열심히 해보겠습니다! 그리고 강좌 자세하게 잘 써주셔서 너무 감사해요!
#re: 스마트 클라이언트, 그것을 알려주마 (V) : Trouble Shooting / Zzanggu / 2007-07-11 오전 10:04:00
좋은 정보 감사합니다. 최근에 스마트 클라이언트를 알고 공부 중인데..

참 많은 도움이 되네요.

내공이 부족해서. 이해하기 좀 힘들지만.. 설명이 참 잘 되있네요.

굿 입니다. 굿~~