Posted
Filed under C#

Internet Explorer 에서의 닷넷 Smart Client 개발

   강좌 최초 작성일 : 2004년 02월 15일
   강좌 최종 수정일 : 2005년 03월 10일

   작성자 : kevin(정 성태)
   편집자 : Taeyo(김 태영)

   강좌 제목 : Smart Client 의 개요

강좌 전 필자의 잡담>

그 전에 태오의 잡담 : 이 강좌는 2004년 2월부터 4월까지 월간마소에 연재되었던 스마트 클라이언트에 대한 컬럼이구요. 닷넥엑스퍼트의 기술 컨설턴트이신 정성태님이 제공해주셨습니다. 스마트 클라이언트에 대한 자료를 구하기 힘든 상황에서 이렇게 선뜻 좋은 자료를 공개해주신 성태님께 다시 한번 감사드립니다.

참고로, 성태님의 개인 사이트는 바로 www.sysnet.pe.kr입니다.
강좌보고 감동을 먹어서 한마디 격려를 해 주고 싶거나, 강좌에 대해 질문은 요기로!!!


요즘 들어서, Smart Client 라는 용어를 심심치 않게 들어 보았을 것이다. 모바일 분야에 계신 분들은 하나의 "기기" 라고 알고 계실 텐데, 필자의 이번 강좌에서는 "기기" 를 다루는 것이 아니고, Microsoft 가 선보인 ".NET Framework" 의 부분으로 나온 "Smart Client" 소프트웨어 개발을 다루려고 한다. 사실, 닷넷에서도 Smart Client 라는 용어는 다소 광범위하게 쓰이는데, 이 강좌에서는 주로 "인터넷 익스플로러에 임베드 된 형태의 컨트롤" 을 다룰 예정이다. 너무 말이 어려웠을 지 모르겠지만, 쉽게 한번 더 풀이해 보자면, 기존 ActiveX 컨트롤을 대체하는 Smart Client 를 구현해 본다는 것이다.

정성태 kevin@dotnetxpert.com

현재 (주) 닷넷 엑스퍼트 에서 기술컨설턴트로 일하고 있으며, 주로 COM-ActiveX, COM+, .NET Framework 관련한 작업을 하고 있다.


연재 순서
1회 : Smart Client 의 개요
2회 : Internet Explorer 와의 연동
3회 : 배포 연재 가이드
운영체제 : IIS 가 설치된 Windows 운영체제 - 필자의 경우 Windows 2003
개발도구 : Visual Studio .NET 2003, .NET Framework v1.1.4322
기초지식 : COM, C#, ASP.NET 기초
응용분야 : 현재로서는 기업 내부의 인트라넷 환경에서의 ActiveX 컨트롤 대체.
이후, 닷넷 프레임워크가 일반화되면 외부 웹사이트 에서의 ActiveX 컨트롤 대체

[강좌의 소스를 다운로드하고 싶다면 클릭하세요!!]


.NET Framework 이 나왔다. 어렵다던 NT Service 조차도 .NET Framework 이 나오면서 구현이 간단해졌다. 웹 프로그램도 마찬가지다. 예전 ASP 에서 "Microsoft Scripting Runtime 개체 라이브러리" 에서 제공되는 이외의 기능을 사용하려면 VC++/ VB 를 이용하여 COM 개체를 만들어야 했지만, 이제는 ASP.NET 에서 .NET Framework 의 Base Class Library 를 이용할 수 있어서 COM 개체를 제작할 필요성이 없어졌다. 이번 연재에서 다룰 "Smart Client" 는 기존의 "ActiveX 컨트롤" 을 교체할 수 있는 기술이다. 물론, ActiveX 컨트롤 제작보다 훨씬 쉬워졌음은 말할 것도 없다. 그 동안 수많은 ActiveX 를 제작해 오던 필자 개인적으로도 이번 "Smart Client" 는 환영할 만한 기술이 아닌가 생각된다.

먼저 접하게 되어 겪었던 시행착오를 비롯해서 예제 중심으로 설명을 해나갈 테니, 관심있는 독자들은 단계별로 하나씩 따라서 해보길 권한다. 참고로, IIS 는 5.0 과 6.0 에서 많은 차이고 있고, .NET Framework 역시 1.0 과 1.1 에는 많은 차이가 있다. 앞으로의 기사는 IIS 6.0 과 .NET Framework 1.1 을 기준으로 하므로 이것과 다른 환경을 가진 독자의 경우, 아래의 설명에서 상이한 부분이 있을지도 모르니 감안해 주기 바란다.

1. ActiveX 보다 쉬운 컨트롤
2. 간단한 컨트롤 제작
3. 이벤트 구현
4. 이벤트 동작을 위한 닷넷 보안 변경


1. ActiveX 보다 쉬운 컨트롤

현업에 계신 분들 중에서, 순수하게 웹 사이트의 출력을 DHTML 로만 하는 것이 너무도 힘겹다는 것을 토로한다. 대부분의 경우에 있어 고객의 요구는 DHTML 의 제약을 생각하지 않는다. 무조건 이러이러한 기능이 필요할 뿐이고, 그러한 기능을 Script 로 구현하려니 속도저하 및 코드의 유지보수에 어려움이 오는 것은 당연하다. 특히 루프가 많은 경우, 스크립트의 속도저하는 심각해지며, 운영체제와 독립된 Script 의 한계로 인해 구현이 불가능한 부분까지도 나올 수 밖에 없다. 그런 상황에서 해결책으로 제시된 것은 ActiveX 컨트롤이었다. Internet Explorer 를 기반으로 하는 그룹웨어를 보면, ActiveX 로 "도배" 를 한 사이트가 많다. "도배" 라는 용어를 썼는데, 절대 탓하려는 의미가 아니다. 요구사항대로 하려니, 답은 ActiveX 뿐이었고, 그로 인해 개발생산성이 현저하게 떨어졌을 것이다.

이젠 ActiveX 를 떠나야 할 시기가 된 것 같다. VC++ 에서 벗어나서 VB 수준의 편리함을 제공해주는 Smart Client 가 여러분 곁에서 기다리고 있다. Smart Client 의 실현 가능성에 있어 장애물이라면 아직 "닷넷 프레임워크" 가 널리 퍼지지 않았다는 사실이다. 일단, 그 부분은 시간이 해결해 줄 것이고, 가능한 범위를 찾아보면 인트라넷을 예로 들 수 있겠다. 정책적으로 닷넷 프레임워크를 설치할 수 있는 상황이라면, ActiveX 보다 개발생산성을 현저하게 높여줄 "Smart Client" 를 적용하는 것이 현명한 선택이 된다. 다음은 필자가 생각해 본 비교 도표이다.

Visual Basic Visual C++ Smart Client
구현의 용이성
클라이언트 보안
쉬운 배포
코드 인증 필요 필요 *필요/불필요

( *사실 Smart Client 역시 결국 코드 인증이 필요하게 된다는 것만 알아두자. 다른 점이라면 해당 DLL 에 할 필요는 없고, 별도의 보안설정을 해주는 모듈에 대해서만 코드 인증을 하면 된다. 이 부분에 대해서는 연재 3회에서 자세히 다루겠다. )

그것을 감안하더라도 모든 면에서 우수한 것을 한눈에 알 수 있다. Smart Client 는 제작 언어를 자유롭게 선택할 수 있으며, Code Access Security 에 기반한 보안으로 인해 사용자 입장에서도 안전하게 사용할 수가 있다. ActiveX 의 경우 CAB 파일등을 만들어야 했지만, "Smart Client" 는 단순히 DLL 또는 EXE 파일을 웹 상에 올려놓기만 하면 된다. ActiveX 와 마찬가지로 웹 서버가 어떤 것이냐는 중요하지 않다. 결국 Smart Client 코드의 실행은 클라이언트에서 이루어지기 때문이다. 심지어, 사용자 컴퓨터의 보안설정을 바꿀 필요가 없는 범위내에서의 기능구현이라면, 코드 인증조차도 필요없이 바로 배포가 가능하다. 그렇다고 해서, 앞으로의 설명들이 줄곧 쉬울 거라고 생각해서는 안된다. 기존 구현된 ActiveX 중에서 복잡한 것까지도 모두 대체할 만한 "Smart Client" 를 원한다면 다소 어려운 이야기까지 흘러갈테니 말이다.


2. 간단한 컨트롤 제작

처음부터, 너무 쉽다고 설명해서 내심 걱정된다. 사실, "간단한" 컨트롤인데도 정작 고려해야 할 것이 많기 때문이다. 아직은 COM 에 대한 요소도 적용되어 있고, WinForm 독립 프로그램과는 달리 클라이언트 접근에 대한 보안사항까지 민감하게 적용되다 보니 실제로는 "닷넷 프레임워크" 에 대한 전반적인 지식을 요구할 정도이다. 미리 Smart Client 를 공부해 보신 분도 계실 것이고, 비록 "간단한" 컨트롤 제작이지만, 이번 회를 모두 할애할 정도이니 차근차근 숙지해 보도록 하자.

실습

이제, 단계별로 구현을 해나가면서 설명을 할 텐데, 이번회에서는 기본적인 메서드, 프로퍼티, 이벤트를 구현한 Smart Client 로써 HTML 에서는 구현이 다소 복잡한 트리 컨트롤을 예제로 제작해 보겠다. 이번에 만드는 컨트롤은 나머지 연재에서 계속 확장될 것이므로, 직접 실습해 볼 것을 권한다.

ㄱ. [화면 1] 같이 Visual Studio.NET 통합환경을 실행시켜서, "WebApp" 라는 웹 Application 프로젝트를 생성한다.

[화면 1 : 웹 프로젝트 생성]

팁이라고 할 수 있는 설명을 덧붙여 보면, 실제로 [화면 1]과 같이 프로젝트를 생성하게 되면, Visual Studio.NET 이 IIS 루트 디렉토리로 지정된 곳에 만들게 된다. 보통 C:\InetPub\wwwroot\WebApp 폴더가 될 텐데, 사실 이렇게 프로젝트가 생성되길 바라는 분들은 없을 것이다. 그러니, 자신의 작업폴더 ( 필자의 경우에는, D:\workshop ) 아래에 "WebApp" 폴더를 만들고, [화면 2] 와 같이 등록정보 창에서 "웹공유" 설정을 한다. 그런 후, "WebApp" 웹 프로젝트를 만들면 사용자가 의도했던 "D:\workshop\WebApp" 폴더에 Visual Studio.NET 이 프로젝트 파일들을 생성하게 된다.

[화면 2 : WebApp 폴더를 웹공유 시킴]

ㄴ. [화면 3] 과 같이 Smart Client 를 구현할 "클래스 라이브러리" 프로젝트를 생성한다. ( 여러 언어 중에서 필자는 Visual C# 을 선택했다. )

[화면 3 : Visual C# 클래스 라이브러리 생성]

ㄷ. 이제, 프로젝트 준비는 끝났고, 예정했던 데로 Smart Client 컨트롤을 생성해 보자. [화면 4] 에서 보는 것처럼 "사용자 정의 컨트롤" 을 선택하고 "TreeControl.cs" 란 이름으로 추가하자.

[화면 4 : 새 항목 추가 - 사용자 정의 컨트롤]

ㄹ. 컨트롤 디자인 폼에 "도구상자" 로부터 "TreeView" 를 끌어다 놓고 이름을 "_treeView" 로 수정한다.

ㅁ. TreeControl.cs 에서 메서드와 프로퍼티를 구현하자. 자세한 코드는 [소스 다운로드] 를 참조하되, 독자 나름대로 자유롭게 추가해 보기 바란다.

메서드
public void LoadXML( string text ); public 이므로 스크립트에서 액세스 가능.XML 문서를 문자열로 받아서 트리에 보여줌.
private bool SetTreeData( XmlNodeList nodeList, TreeNode parentNode ); private 이므로 스크립트에서 액세스 불가능. 재귀호출을 통해 데이터를 실제로 트리에 렌더링.
프로퍼티
public string SelectedNodeText; [get] 선택된 노드의 XML 텍스트를 반환

ㅂ. 제대로 된 기능을 구현하기 위해서는 트리 컨트롤의 노드를 클릭시에 이벤트를 발생시켜야 할 것이다. 하지만, 이벤트에 대해서는 복잡하므로 잠시 미루겠다. 컴파일 후, SmartClient.dll 을 "WebApp" 웹 응용 프로그램의 WebForm1.aspx 가 있는 폴더에 복사하자. 실제 개발시에는 매번 DLL 이 변경될때마다 복사하기가 번거로우므로, [화면 5] 와 같이 출력 경로를 지정해 놓으면 편리할 것이다.

[화면 5 : 출력 경로 설정]

ㅅ. 이제, "WebApp" 프로젝트로 돌아가서 "WebForm1.aspx" 를 수정해 보자. cs 코드는 수정할 필요없고, HTML 을 다음과 같이 수정한다.

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebApp.WebForm1" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

<html>
    <head>
        <title>WebForm2</title>

        <script language=jscript> -------------------------- ①
            function window.onload()
            {
                Form1._Control1.LoadXML( _xmlData.xml );
            }
        </script>

    <xml id=_xmlData> -------------------------------- ②
    <tree>
        <L expand="T">
            <D>마소</D><D>http://www.imaso.co.kr/</D><D>추가 DATA</D>
            <L expand="T">
                <D>닷넷엑스퍼트</D><D>http://www.dotnetxpert.com/</D><D>추가 Data1</D>
            </L>
        </L>
        <L expand="F">
            <D>Microsoft</D><D>http://www.microsoft.com</D><D>추가 Data2</D>
        </L>
    </tree>
    </xml>

    </head>
    <body MS_POSITIONING="GridLayout">

        <form id="Form1" method="post" runat="server">
            <OBJECT id="_Control1" style="WIDTH: 272px; HEIGHT: 193px"
                classid="SmartClient.dll#SmartClient.TreeControl" VIEWASTEXT>
            </OBJECT> -------------------------------- ③
        </form>
    </body>
</html>

단계별로 살펴보기로 하자.

① 예전의 ActiveX 컨트롤을 사용하는 것과 방식은 같다. 해당 Smart Client 의 public 메서드를 스크립트 상에서도 호출해 주면 된다.

② XML 데이터 아일랜드 로 해서 XML 데이터를 컨트롤에서 쉽게 사용할 수 있도록 HTML 내에 넣어 두었다. 그리 중요한 사항은 아니다.

③ Smart Client 가 HTML 내부에서 어떻게 사용될 수 있는지를 보여준다. <OBJECT/> 태그를 사용한다는 면에서는 ActiveX 와 동일하다. 다른 부분이라면, classid 뿐인데, 웹서버에서 SmartClient.dll 을 발견할 수 있는 상대경로 위치와 어떤 클래스를 활성화 시킬 것인지에 대한 타입 정보를 기술하고 있다. 나중에 알게 되겠지만, SmartClient.dll 파일을 regasm.exe 로 로컬에 COM 개체로 등록한다면, 이 부분 조차도 실제 CLASS ID 로 교체 가능하다.

ㅇ. 구현완료 및 테스트 준비가 모두 끝났다. WebApp 프로젝트를 컴파일 하고, 웹 브라우저에서 http://localhost/WebApp/WebForm1.aspx 로 가보자. [화면 6] 과 같은 결과가 보일 것이다. ActiveX 와 비교해 보면 얼마나 편리해 졌는 지 느껴지는 순간이다. 진작에, 개발이 이런 식으로 되었어야 하지 않았나 하는 생각마저 드는 것은 왜일까. 이번엔, http://127.0.0.1/WebApp/WebForm1.aspx 로 해보자. IIS 6.0 의 경우에 비밀번호를 물어볼 것이다. 127.0.0.1 을 "로컬 인트라넷" 이 아닌 "인터넷" 으로부터의 접근으로 인식하는 데다가, IIS 6.0 은 기본적으로 가상 디렉토리에 대해서 "익명접근" 을 허용하지 않도록 되어 있기 때문이다. 이 경우, 매번 불편하게 계정을 입력하던지, 아니면 IIS 6.0 에서 "WebApp" 가상디렉토리에 대해서 "익명접근" 허용을 체크해 두면 된다.

[화면 6 : 예제 실행화면]

한가지 더 언급하자면, "SmartClient.dll" 어셈블리에 "강력한 이름서명" 을 하게 되면, "127.0.0.1" 에서든 "localhost" 에서든 전혀 활성화가 되지 않는다. 어떠한 기준이 적용되는 지는 아직 모르겠지만, 상식적으로는 이해가 되지 않는 기준이다.


3. 이벤트 구현

어떻게 닷넷 프레임워크의 Class 가 COM 개체로 매핑이 되는지에 대해서는 내부 구현은 정확히 알 수 없다. 하지만, 어쨌든 IUnknown 관련한 인터페이스에 vtable 을 맞추어 주면 호출할 수는 있을 것이다. 마찬가지로 이벤트 역시 COM 의 규약을 따르기만 해준다면 상호연동을 하게 될 것이다. 그걸 개발자가 해주어야 할까? ActiveX 시절에는 그렇게 하는 것이 당연했지만, 닷넷 프레임워크의 Smart Client 로 와서는 코드라기 보다는 "특성" 으로 바뀌었다. 닷넷의 "특성" 을 이용하여 개발자가 "표시" 만 해두면 모든 코드는 컴파일러가 알아서 삽입해 준다. 이벤트 소스를 알리는 특성과, 이벤트를 발생하는 내부 코드만 준비하면 끝인 셈이다. 물론, 이벤트를 거는 것은 외부코드에서 해야 할 일이다.

이제부터 위에서 만든 Tree Control 에서, 노드가 선택이 되면 이벤트를 발생한 것을 스크립트에서 받고 URL 을 얻어내어 해당 주소로 네비게이션 하는 것을 구현해 보겠다.

ㄱ. 이벤트 소스 인터페이스 마련.

문법은 VC++ ATL 에서 IDL 다룰 때와 상당히 유사하다. SmartClient 프로젝트에서 "TreeEvent.cs" 파일을 새로 추가하고 다음과 같이 이벤트 인터페이스를 구현하자.

public interface ITreeControlCOMIncoming ----------------- ①
{
    void LoadXML( string text );
    string SelectedNodeText { get; }
}

[Guid("A59B958D-B363-454b-88AA-BE8626A131FA")] ------- ②
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] ------- ③
public interface ITreeEvent
{
    [DispId(0x60020000)] --------------------------- ④
    void NodeClicked();
}

① 기본적인 Smart Client 의 메서드를 스크립트에서 호출하고 싶을 때는 public 제한자를 주는 것으로 끝났지만, 이벤트를 구현하면서는 외부에서의 호출을 위한 목록을 인터페이스에서 기술해 주고 그것을 상속받아야 한다. 뒤에 TreeControl 클래스에 주게 될 ClassInterfaceType.None 으로 인해서 외부로 기능을 노출시킬 메서드나 프로퍼티를 이와 같이 인터페이스를 정의하여 관리하게 된다..

② 해당 Event Source 인터페이스에 대해서 임의적으로 유일한 GUID 값을 설정한다.

③ Script 에서 이벤트를 걸 것이기 때문에 IDispatch 가 적용되어야 한다.

④ 각각의 이벤트에 대해 임의적으로 DispID 상수값을 설정한다.


ㄴ. 이벤트 소스 인터페이스와 TreeControl 클래스와 연결

VC++ 로 ATL 을 해보지 않으신 분들은 위의 사항만 해도 낯설어 하실 것 같다. 하지만 거의 정형화된 틀이니 사용되는 특성들이 다소 낯설지라도 지금 보여드리는 "틀" 대로만 해주면 문제가 발생하진 않을 것이다.

[ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(ITreeEvent))] ------- ①
public class TreeControl : System.Windows.Forms.UserControl, ITreeControlCOMIncoming --- ②
{
    private System.Windows.Forms.TreeView _treeView;

    public delegate void NodeClickedHandler(); ------------------- ③
    public event NodeClickedHandler NodeClicked;

    protected void OnNodeClicked()
    {
        if ( NodeClicked != null )
        {
            Invoke( NodeClicked, null );
        }
    }

    public string SelectedNodeText
    {
        get
        {
            if ( _treeView.SelectedNode == null )
            {
                return string.Empty;
            }

            XmlNode aNode = _treeView.SelectedNode.Tag as XmlNode;
            return aNode.OuterXml;
        }
    }
}

① ClassInterfaceType.None 으로 인해서 상속받은 interface 에 명시된 프로퍼티와 메서드만을 외부에 노출시키겠다는 것을 알리고 ComSourceInterface 특성으로 TreeControl 의 이벤트 소스 인터페이스가 ITreeEvent 라고 알리게 된다. 이 특성을 컴파일러가 인지할 것이고 그에 따른 코드를 자동으로 생산해 낼 것이다.

② ClassInterfaceType.None 특성지정으로 인해서 ITreeControlCOMIncoming 인터페이스에 명시적으로 지정된 메서드와 프로퍼티만을 외부에 공개합니다.

③ 이벤트 구현은 C# 이벤트 구현을 따른다. ComSourceInterface 에서 선언된 메서드 하나당 delegate 하나씩 선언하고 대응되는 event 를 정의하면 된다.


ㄷ. 이벤트 발생

TreeControl 의 경우, 노드가 선택될 때마다 외부에 이벤트를 발생시킬 것이므로 TreeView 컨트롤의 AfterSelect 이벤트가 발생할 때마다 아래와 같이 호출해 주면 된다.

private void _treeView_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
{
    OnNodeClicked();
}


ㄹ. 스크립트에서 이벤트 받기

역시 기존 ActiveX 이벤트 처리하는 것과 다를 것이 없다. 다음은 선택된 트리 노드로부터 XML 텍스트를 받아오고 그 데이터 중에서 URL 노드의 값을 읽어들여 해당 사이트로 이동을 한다.

<script event="NodeClicked()" for="_Control1">
    var xmlText = _Control1.SelectedNodeText;
    var xmlDoc = new ActiveXObject( "Microsoft.XMLDOM" );
    if ( xmlDoc.loadXML( xmlText ) == true )
    {
        document.location.href = xmlDoc.selectSingleNode( "L" ).childNodes.item( 1 ).text;
    }
</script>

모두, 구현을 했으면 컴파일 하고 http://127.0.0.1/WebApp/WebForm1.aspx 로 테스트 해보자. 이제까지의 코딩을 따라해 주신 여러분들께 죄송하지만, 위의 구현은 "예외" 발생으로 끝나고 만다. 왜 예외상황이 되어버린 것일까? 이런 현상은 Smart Client 에서 이벤트를 실행하는 것이 닷넷의 "보안" 에 위배되기 때문이다. 즉, "인터넷" 으로부터 다운로드 받은 모듈의 코드가 "Unmanaged 코드" 를 호출할 수 없도록 해놓은 것이다. 이벤트는 명백히 COM 개체로 구현이 되고 COM 은 Unmanaged 코드라서 "닷넷" 은 그것을 허용치 않는 것이다.

여기서, 한가지 잠시 의문이 생기는 독자가 있을 것이다. 결국 Smart Client 를 Script 에서 접근할 때는 마찬가지로 COM 호출을 하는 것인데, 그것은 왜 예외가 아니라는 것인지? 그 이유에 대해 해답을 이끌어 내자면 이런 식이다. 자바 스크립트에서 Smart Client 를 호출하는 것은 외부에서 닷넷 코드를 호출하는 것 뿐이다. 즉, 우리가 만든 컨트롤 내부의 닷넷 코드가 "Unmanaged Code" 를 실행하는 것이 아니고, 외부에서 "Unmanaged Code" 를 통하여 우리의 닷넷 코드를 실행시키는 것이다. 그와 반면에 이벤트의 처리는 다르다. COM 에서의 이벤트 처리는 "쌍방향 통신" 이다. 이벤트를 걸게(sinking) 되는 것은 예외 조건에 걸리지 않는다. 그래서 스크립트 엔진이 <script event="..." for="..." /> 을 해석하는 시점에 예외가 발생하지 않는 것이다. 마치, 컨트롤의 public 메서드 호출과 같이 외부에서 Unmanaged Code 를 통해서 실행하는 것 뿐이기 때문이다. 하지만, 이벤트 발생은 다르다. 이벤트 발생의 근원은 닷넷 코드이고, 그것은 곧 이벤트와 연결된 외부 IDispatch 인터페이스를 호출하는 것을 의미하며, IDispatch 인터페이스 호출자체는 "Unmanaged 코드" 이기 때문에 닷넷 보안 설정에 위배가 되는 것이다.

"인터넷으로부터 다운로드 받은 어셈블리 코드" 는 "Unmanaged 코드" 를 호출해서는 안된다.


4. 이벤트 동작을 위한 닷넷 보안 변경

Win32 시절에도 그랬지만, 보안은 다가서기가 힘들다. 그래도 닷넷은 그나마 쉬운편이니 너무 큰 부담은 갖지 말기 바란다. 위에서 이미 "이벤트" 를 발생시키는 것이 "Unmanaged Code 를 호출할 수 없다" 는 것으로 인해 예외가 발생한다고 했다. 그렇다면, 당연히 그 보안 사항을 허락한다면 "이벤트" 는 정상적으로 동작하게 될 것이다. 우선, 이번 호에서는 보안 설정을 "Microsoft .NET Framework 1.1 구성" 를 통해서 해보겠다. 시작메뉴에서 "프로그램/관리도구/Microsoft.NET Framework 1.1 구성"을 선택하자.

[화면 7 : .NET Configuration 1.1 실행화면]

http://localhost 의 경우에는 "LocalIntranet_Zone" 에 설정된 권한이 적용되고, http://127.0.0.1 로는 "Internet_Zone" 이 적용된다. 바꿔 말하면, IP 와 DNS 로 접근할 때는 "Internet_Zone" 이고, NETBIOS 이름이나 "localhost" 로 접근하는 것은 "LocalIntranet_Zone" 이다. 각각의 권한을 살펴보면 알겠지만, 인터넷 존이 보다 더 강화된 보안규칙으로 제한을 하고 있는 것을 볼 수 있다.

자, 그럼 무엇을 해야 겠는가? 당연히 "런타임보안정책 / 컴퓨터 / 코드 그룹 / All_Code / Internet_Zone" 의 보안설정을 바꿔주어야 할 것이다. ( 설정을 마친 후, http://127.0.0.1/ 로 접근한다면 이벤트 관련해서 예외가 발생하지 않는다. 하지만, http://localhost 로는 여전히 예외가 발생한다. 필자가 다음의 설명을 통해 "Internet_Zone" 을 바꾸겠으니, 이글을 읽는 독자는 "LocalIntranet_Zone" 을 바꿔보길 바란다. )

[화면 7] 에서 "Internet_Zone" 의 "등록정보" 창을 띄우고 "권한 집합" 탭으로 가보자.

[화면 8 : Internet_Zone 의 등록정보 창]

[화면 8] 에서 보는 것처럼, "권한 집합" 이 "Internet" 으로 설정되어져 있다. 그리고, "Internet" 권한집합은 "파일대화상자", "격리된 저장소 파일", "보안", "사용자인터페이스", "인쇄" 권한을 가지고 있다. 각각의 권한을 마우스로 클릭하고, "권한보기" 버튼을 눌러보자. "Internet" 권한집합은 다음 표와 같이 설정되어져 있다.

파일 대화상자 열기
격리된 저장소 파일 허용된 용도 사용자로 도메인 격리
디스크 할당 10240
보안 코드 실행사용
사용자 인터페이스 창 작업 안전한 최상위 창
클립보드 자체 클립보드
인쇄 안전한 인쇄

우리가 원하는 것은 "관리되지 않는 코드 호출 허용" 이다. [화면 7] 을 보면, ".NET Configuration 1.1 / 내컴퓨터 / 권한집합" 노드가 있는데, 우리가 원하는 "Internet" 권한집합을 선택하자. MMC 의 오른쪽 패널에 "권한 보기" 만이 존재한다. 반면에 "Everything" 권한 집합을 선택해 보자. 오른쪽 패널에 "권한 보기 / 권한 변경 / 권한 집합 이름 바꾸기" 가 있는 것이 확인된다. 즉, "Internet" 권한집합은 더 이상 변경 불가능하다는 것을 의미한다. Smart Client 만을 위한 권한 집합을 새로 하나 만들어야 하는데, 어차피 보안 설정이 "Internet" 권한 집합에서 하나만 추가할 것이기 때문에 기존 집합으로부터 복제해서 만드는 것으로 해보겠다.

ㄱ. "권한 집합 / Internet" 컨텍스트 메뉴에서 "복제" 를 선택한다. 그럼, 새롭게 "Internet 의 복사본" 권한 집합이 생긴다.

ㄴ. "속성" 창을 띄우고, "권한 집합 이름" 을 "SmartClientSet" 으로 변경한다.

ㄷ. 오른쪽 패널에서 "권한 변경" 을 선택한다.

ㄹ. "권한 집합 만들기" 창이 열리는 데, 더 추가하거나 삭제할 것은 없다. 오른쪽의 "할당된 권한" 목록에서 "보안" 을 선택하고, "속성" 버튼을 클릭하자. [화면 9] 에서처럼 추가로 "관리되지 않는 어셈블리 호출 허용" 을 체크하자.

[화면 9 : 권한 설정 - 관리되지 않는 어셈블리 호출 허용 추가]

ㅁ. "확인" 버튼과 "마침" 버튼을 차례로 누르자. 그럼, 새롭게 "SmartClientSet" 이란 새로운 "권한 집합" 을 만든 것이다.

이제 이것을 코드 그룹의 "Internet_Zone" 에 적용시키면 된다. 하지만, 잠깐 생각해 볼 것이 있다. "Internet_Zone" 전체에 "SmartClientSet" 권한집합을 적용시키는 것이 타당한가? 너무나 당연하게, 그것은 로컬 시스템에 치명적인 보안 결함을 안겨 주는 것이다. 자신의 컴퓨터에서 방문하는 모든 인터넷 사이트들의 "Smart Client" 에게 그러한 권한집합을 갖게 하는 것은 위험하다. 우린 단지, 특정 웹사이트를 지정해서 해당 권한을 추가해 주는 식이어야 한다.

ㄱ. 코드 그룹의 "Internet_Zone" 을 선택하고, 오른쪽 패널에 나오는 "자식 코드 그룹 추가" 메뉴를 선택하자. 물론, 컨텍스트 메뉴로도 접근이 가능하다.

ㄴ. "코드 그룹 만들기" 대화창에서 "이름" 을 InternetSmartClient_Zone 으로 설정하자. 독자 임의로 이름을 지어도 된다.

ㄷ. "조건 형식 선택" 을 해야 하는데, 우리가 관심있는 Smart Client 는 인터넷으로부터 다운로드하여 실행되기 때문에 선택해야 할 조건은 "URL" 이 된다. 선택하고 나면, 하단에 URL 입력 상자가 나오는데 그곳에 http://127.0.0.1/* 라고 입력한다.

ㄹ. "코드 그룹에 권한 집합 할당" 에서 우리가 이전에 만들어 두었던 "SmartClientSet" 을 선택한다.

이것으로, 설정은 모두 끝났다. 이전에 만들어 두었던 TreeControl 을 테스트 해보자. http://127.0.0.1/WebApp/WebForm1.aspx 로 탐색하고, 트리에 나오는 노드를 선택해 보자. "예외" 발생 없이 이벤트를 정상적으로 받는 것을 확인할 수 있다. 모든 설명이 끝이 났다. 이제 여러분 나름대로 주제를 가지고 또 다른 "Smart Client" 를 제작하여 테스트 해보기 바란다.

물론, 모든 문제가 깔끔하게 해결된 것은 아니다. 이로 인해 "보안을 수정해야 하는" 배포에 대한 문제가 발생한다. 이벤트를 사용하는 Smart Client 의 경우에는 모든 클라이언트 컴퓨터마다 그와 같은 보안 설정을 해주어야 한다는 것인가? 아쉽게도 그래야 한다. 하지만, 사용자로 하여금 직접 설정하게 할 수 있을 정도로 간단한 것이 아니다. 따라서, 배포하는 입장에서는 위의 설정을 자동으로 해주는 프로그램을 하나 만들어서 미리 사용자의 컴퓨터에서 실행을 하도록 해주는 식으로 배려를 해주어야 한다. 이와 같은 배포 문제에 대해서는 연재 3회에서 자세히 다루도록 하겠다.


연재 1회를 마치며

Smart Client 제작을 해보니 어떻다고 생각되는가? 닷넷만 알아서는 안되는 문제였다고 생각하지는 않는가? 그렇다. 아직까지는 "닷넷 프레임워크" 자체가 Windows 상에서 운영되고 있으며, Windows 에는 수많은 COM 기술이 녹아있다. 결국, "닷넷(으로 만든) 컨트롤" 이란 기존 COM 을 사용하는 무수한 Application 과의 연동을 위해서라도 "COM" 에 대한 배려를 안할 수 없고, 앞으로도 얼마 동안은 "COM" 에 대한 지식이 있는 사람이 "닷넷 컨트롤" 에 대해서도 많은 유연성을 발휘할 수가 있을 것이다. "인터넷 익스플로러" 6.0 버전이 나온지도 꽤 오랜 시간이 흘렀다. 마치 Visual Studio 97 을 내놓은 이후로 많은 공백이 있던 것과 비슷한 것이 아닐런지. 필자의 개인적인 생각으로는 인터넷 익스플로러 의 다음 버전에는 "닷넷 프레임워크" 와의 연동을 많은 부분 개선시켜서 내놓을 거라 생각하기에 내심 기대를 하고 있는 중이다.

어떻게, 어느 부분이 개선될지는 모르겠지만 그것은 불확실한 미래의 일이고, 연재 2회 기사에서는 현재의 프레임워크와 인터넷 익스플로러 안에서 기존의 ActiveX 가 썼던 기교를 Smart Client 로 어떻게 대체가 되는 지에 대해서 자세히 설명할테니 기대해 주기 바란다.


참고 URL

MSDN Magazine February 2003 : Give Your .NET-based Applications a Fast and Responsive UI with Multiple Threads
http://msdn.microsoft.com/msdnmag/issues/03/02/Multithreading/default.aspx

MSDN Magazine June 2002 : Code Access Security and Distribution Features in .NET Enhance Client-Side Apps
http://msdn.microsoft.com/msdnmag/issues/02/06/rich/

MSDN Magazine January 2002 : Host Secure, Lightweight Client-Side Controls in Microsoft Internet Explorer
http://msdn.microsoft.com/msdnmag/issues/02/01/UserCtrl/default.aspx 

2009/07/17 20:40 2009/07/17 20:40