COM+ 응용 프로그램과 IIS 버전 5.0의 웹 응용 프로그램

등록일시: 2004-08-04 15:54,  수정일시: 2018-04-07 12:04
조회수: 22,803
본문은 최초 작성 이후, 약 20년 이상 지난 문서입니다. 일부 내용은 최근의 현실과 맞지 않거나 동떨어져 있을 수 있으며 문서 내용에 오류가 존재할 수도 있습니다. 또한 본문을 작성하던 당시 필자의 의견과 현재의 의견에 많은 차이가 존재할 수도 있습니다. 이 점, 참고하시기 바랍니다.

특정 시스템을 운영하거나 그에 기반한 프로그래밍 작업을 진행하는 경우, 늦건 빠르건 간에 대부분 해당 시스템에서 키 포인트가 되는 무언가를 발견하게 될 확률이 높다. 때로는 시스템의 아키텍처가 키 포인트인 경우도 있고, 아니면 데이터에 접근하는 방식이 키 포인트인 경우도 있는 등 환경에 따라 매우 다양한 경우들이 존재할 수 있을 것이다. 그리고 대개의 경우, 그 키 포인트를 얼마나 빠르게 찾아내고 또 얼마나 정확하게 이해하느냐에 따라 해당 시스템의 운영자나 개발자의 숙련도가 좌우되는 것이 일반적이다.

만약, 누군가가 필자에게 IIS의 키 포인트가 무엇이라고 생각하냐고 물어본다면 필자는 조금도 망설이지 않고 COM+ 응용 프로그램과 IIS 웹 응용 프로그램간의 상호 관계를 파악하는 것이 IIS를 이해하기 위해서 가장 중요한 키 포인트라고 대답할 것이다. 단, 여기에는 IIS의 버전을 5.0으로 제한한다는 조건과 IIS가 호스팅하는 프로그래밍 환경이 ASP라는 두 가지 전제 조건을 붙이도록 하겠다. 이런 전제 조건들이 요구되는 이유에 관해서는 본문을 진행해나가면서 한 가지씩 차례차례 설명하도록 하겠다. 그리고, 미리 한 가지 확실하게 말해두고 싶은 점은 본문에서 설명하고자 하는 내용들을 이해하지 못하고서는 이런 제약 조건들과 관련된 논제들에 관해서도 명확하게 이해할 수 없을 것이라는 사실이다.

가령, IIS 6.0에서 새롭게 소개된 작업자 프로세스 격리 모드가 기존의 응용 프로그램 격리 모드와 어떤 부분에서 다른지 정확하게 이해하기 위해서는 먼저 본문에서 다루고자 하는 논제들을 확실하게 이해하고 넘어가야만 한다. 그리고, ASP.NET이 내부적으로 ASP와 어떻게 다른 환경에서 실행되고 관리되는지를 이해하고자 하는 경우에도, 역시 본문에서 살펴볼 논제들에 관한 지식이 필수적으로 요구된다. 바로 그런 면에서 COM+ 응용 프로그램과 IIS 웹 응용 프로그램간의 상호 관계에 관한 논의는 IIS를 보다 깊이 이해하고자 하는 분들에게 지금까지와는 다른 새로운 관점에서 IIS를 바라볼 수 있도록 도와줄 수 있는 신선한 시각들을 제공해 줄 것이다. 사실 본문은 IIS 6.0 버전을 통해서 새롭게 소개된 아키텍처들을 논의하기 위한 선수 지식들을 다루기 위한 목적으로 작성된 것이다. 본문을 통해서 IIS에 관한 새로운 지식들, 예를 들어 격리 모드나 프로세스 ID, 가장, 또는 보안 관련 이슈와 같은 내용들을 접하게 되는 계기가 되기를 바란다.

IIS 6.0 사용자들을 위한 설정

아마도 본문을 읽고 계신 분들 중에는 벌써 자신의 컴퓨터에 윈도우즈 2003 제품군을 설치해서 운영체제로 사용하고 계신 분들도 있을 것이다. 그런 분들은 먼저 자신의 IIS 6.0이 작업자 프로세스 격리 모드로 실행되고 있는지, 아니면 IIS 5.0 격리 모드로 실행되고 있는지를 확인해보기 바란다. 특별히 설정을 바꾸거나 하지 않았다면 대부분 작업자 프로세스 격리 모드로 실행되고 있을 텐데, 만약 그렇다면 지금 그 상태로는 본문에서 논의하고자 하는 내용들을 직접 확인하는 것이 불가능하므로 먼저 응용 프로그램 격리 모드를 IIS 5.0 격리 모드로 전환해야만 한다. 현재 설정된 응용 프로그램 격리 모드를 확인할 수 있는 가장 간단한 방법은 인터넷 정보 서비스(IIS) 관리 스냅인에서 좌측의 콘솔 트리를 점검해 보는 것이다. 만약 다음과 같이 콘솔 트리에 응용 프로그램 풀이라는 노드가 존재하고 있다면 현재 IIS 6.0은 작업자 프로세스 격리 모드로 실행중이라고 판단할 수 있다.

작업자 프로세스 격리 모드로 실행되고 있는 IIS 6.0

작업자 프로세스 격리 모드를 IIS 5.0 격리 모드로 전환하기 위해서는 다음과 같은 순서를 따른다. 인터넷 정보 서비스(IIS) 관리 스냅인을 실행하고 콘솔 트리에서 웹 사이트 노드를 마우스 오른쪽 버튼으로 클릭한 다음, 팝업 메뉴를 띄운 뒤 속성 메뉴를 선택한다. 그러면, 다음과 같은 웹 사이트 등록정보 대화 상자가 나타나는데 여기에서 서비스 탭을 선택하고 격리 모드 항목의 IIS 5.0 격리 모드에서 WWW 서비스 실행이라는 체크 박스를 설정한 다음 확인 버튼을 누른다. 그러나, 실제로 서비스 중인 사이트가 운영되고 있는 시스템에서는 절대로 이 작업을 수행하지 말기 바란다. 왜냐하면 IIS 서비스의 재시작이 요구될 뿐만 아니라 사이트에 따라서는 오류가 발생하거나 정상적으로 동작하지 않을 수도 있기 때문이다. 반드시 개발 서버나 자신의 머신을 대상으로만 작업할 것을 권장한다.

IIS 5.0 격리 모드에서 WWW 서비스 실행

다음과 같이 IIS 6.0 의 재시작을 확인하는 IIS 관리자 메세지 박스가 출력되면 버튼을 클릭해서 서비스를 재시작하도록 한다. 그리고 잠시 기다리면, IIS 서비스가 다시 시작되면서 응용 프로그램 격리 모드가 IIS 5.0 격리 모드로 전환되게 된다.

IIS 6.0 의 재시작을 확인하는 메세지 박스

이제 인터넷 정보 서비스(IIS) 관리 스냅인을 닫았다가 다시 실행시켜보면 다음과 같이 콘솔 트리에서 응용 프로그램 풀 노드가 사라졌다는 사실을 확인할 수 있을 것이다.

IIS 5.0 격리 모드로 실행되고 있는 IIS 6.0

마지막으로 다시 한 번 강조하지만 사이트가 서비스 되고 있는 운영 시스템에서는 이 작업을 수행하는 것을 절대로 권장하지 않는다. 만약, 해당 사이트가 IIS 6.0에서 새롭게 소개된 기능들을 사용하고 있다면 그 기능과 관련된 사이트의 모든 프로그램들이 정상적으로 동작하지 않거나 오류를 발생시킬 것이다. 단적으로, 지금 설명한 작업을 마치고 나면 응용 프로그램 풀 노드가 사라지는 이유도 바로 해당 기능이 IIS 6.0에서 작업자 프로세스 격리 모드를 기반으로 새롭게 소개된 기능이기 때문이다.

IIS 웹 응용 프로그램

필자로서는 상당히 의외라고 생각되는데 점이 하나 있는데 그것은 ASP 프로그래밍 경력이 꽤나 오래된 분들 중에서도 웹 응용 프로그램이란 용어를 모르고 계신 분들이 상당히 많다는 점이다. 그나마 최근에는 마이크로소프트 비주얼 스튜디오 .NET으로 ASP.NET 프로그램을 작성하는 경우, 웹 응용 프로그램의 설정이 필수적으로 요구되기 때문에 .NET 프로그래밍이 점차 확산되기 시작하면서 이런 추세가 많이 감소했다고 생각된다. 그러나, 웹 응용 프로그램이라는 개념 그 자체는 이미 IIS 4.0에서부터 존재하고 있었던 개념이며 알게 모르게 지금도 ASP 프로그래밍 환경에 많은 영향을 주고 있다.

프로그래밍적인 관점에서 몇 가지 관련 사례를 들어보도록 하겠다. 많은 분들이 이미 알고 계신 것처럼 임의의 가상 디렉터리와 또 다른 가상 디렉터리 간에는 세션 개체가 공유되지 않는데, 그 이유는 각각의 가상 디렉터리가 로드되는 웹 응용 프로그램이 서로 다르기 때문이다. 그리고, 익명 사용자 접속을 활성화시켜놓은 웹 사이트에 접속하는 모든 사용자는 IUSR_[MachineName] 계정의 보안 컨텍스트를 사용하여 리소스에 접근하게 되는데, 이것도 역시 웹 응용 프로그램의 프로세스 ID가 IUSR_[MachineName] 계정의 보안 컨텍스트를 사용해서 가장(Impersonation)되기 때문이다. 또한, ASP.DLL을 포함한 ISAPI 확장 프로그램이 로드되는 단위 역시, 바로 웹 응용 프로그램이 기준이 되며 응용 프로그램 보호 기능도 웹 응용 프로그램을 단위로 이루어진다.

이상의 몇 가지 간단한 사례들로부터 짐작할 수 있는 것처럼 IIS의 웹 응용 프로그램 개념을 이해하는 것은 기술적인 측면에서 IIS의 심장부에 접근하는 것과 마찮가지인 중요한 작업이다. 게다가 더욱 중요한 사실은 이런 기술적인 이슈들이 ASP.NET 환경에서 이미 크게 한 번 뒤집혀 졌으며, 윈도우즈 2003 제품군에 포함된 IIS 6.0에서 모든 구조가 다시 한 번 완벽하게 뒤집혀져 버렸다는 점이다. 따라서, 어떤 부분들이 어떻게 그리고 왜 변경되었는지 정확하게 이해하고 있어야만 각각의 환경에서 난해한 문제에 부딛히게 되는 경우 상황에 적합한 대처가 가능해진다. 그래서, 필자는 그 이해를 위한 가장 첫 번째 단계로 본문을 통해서 IIS 5.0 기반의 웹 응용 프로그램에 관하여 논의하고자 하는 것이다.

그렇다면 도대체 웹 응용 프로그램이라는 용어가 의미하는 것은 구체적으로 무엇일까? 일단 기본적으로 모든 가상 웹 서버는 각각 하나의 웹 응용 프로그램을 구성한다. 그리고, 웹 응용 프로그램이 설정된 가상 디렉터리 역시 각각 하나의 웹 응용 프로그램을 구성하는데, 가상 디렉터리라고해서 항상 웹 응용 프로그램을 구성하는 것은 아니라는 점에 주의하기 바란다. 즉, IIS 5.0의 웹 디렉터리에는 다음과 같이 모두 세 가지 종류의 웹 디렉터리가 존재한다.

  1. 일반 디렉터리
  2. 웹 응용 프로그램 설정이 되지 않은 순수한 가상 디렉터리
  3. 웹 응용 프로그램 설정이 된 가상 디렉터리

이와 관련된 내용은 다른 강좌에서도 이미 간단하게나마 언급한 적이 있으므로 관심 있는 분들은 이 문서를 참고하기 바란다. 이 세 종류의 웹 디렉터리들 중에서 단지 웹 응용 프로그램이 설정된 가상 디렉터리만 개별적인 하나의 웹 응용 프로그램을 구성하게 되는데, 여기서 주목해야 할 부분이 웹 응용 프로그램이 설정된 가상 디렉터리를 나타내는 아이콘이 바로 다음 섹션에서 살펴보게 될 COM+ 응용 프로그램의 아이콘과 색상만 조금 다를뿐 정확하게 동일한 형태를 갖고 있다는 점이다. 그다지 중요하게 생각되지 않을지도 모르겠지만 이 간단한 사실의 의미하는 바는 실로 대단한 것인데, 바로 이 부분에 대한 논의가 필자가 본문을 통해서 살펴보고자 하는 핵심이다. 그러나 이에 대한 논의는 잠시 후에 COM+ 응용 프로그램에 관해서 설명을 마치고 나서 다시 자세하게 다루도록 하겠다.

가상 웹 서버나 웹 응용 프로그램이 설정된 가상 디렉터리의 등록 정보 메뉴를 살펴보면, 다음과 같이 홈 디렉터리 탭의 응용 프로그램 설정 하위의 항목들이 대부분 활성화되어 있다. 그러나, 일반 디렉터리나 웹 응용 프로그램이 설정되지 않은 순수한 가상 디렉터리의 등록 정보 메뉴를 살펴보면 응용 프로그램 설정 하위의 항목들 중에서 실행 권한 항목을 제외한 나머지 항목들이 모두 비활성화되어 있을 뿐만 아니라, 특이하게도 제거 버튼 대신 만들기 버튼이 존재한다는 사실을 확인할 수 있다. 참고로 필자는 윈도우즈 2003 서버 엔터프라이즈 에디션을 운영체제로 사용하고 있으며, 아래의 이미지는 VMware Workstation에 설치된 윈도우즈 2000 프로페셔널에 설정된 IIS 5.0의 인터넷 정보 서비스 스냅인에서 캡춰한 것이다. 지금부터 특별하게 언급하지 않는 한 제시되는 모든 이미지들은 이와 동일한 환경에서 캡춰된 것이라고 생각하면 된다.

IIS 5.0 격리 모드로 실행되고 있는 IIS 6.0

웹 응용 프로그램과 관련된 항목들에 관해서 하나씩 살펴보도록 하자. 첫 번째로 응용 프로그램 이름 항목은 프로그래밍적으로는 그다지 별다른 의미가 없는 항목이다. 단순하게 해당 웹 응용 프로그램을 설명하는 일종의 친숙한 이름 정도로 생각하면 되고 실제로 내용을 설정할 때도 그저 본인이 기억하기 쉬운 이름 같은 것을 입력해주면 된다. 두 번째 항목인 실행 권한 항목은 대부분의 ASP 프로그래머분들이 이미 잘 알고 계실 것이라고 생각될뿐더러 본문의 주제와도 그다지 관련이 없으므로 이 항목은 일단 넘어가기로 한다.

그리고, 그 다음 항목인 응용 프로그램 보호 항목은 몹시 중요한 항목일뿐만 아니라 바로 본문에서 주의 깊게 다루고자 하는 핵심에 해당하는 부분이다. 자세한 내용은 잠시 후에 다시 깊게 다루겠지만 이 자리에서 먼저 여러분께 다음과 같은 질문을 드려보고자 한다. 물론 여러분도 이미 이 항목이 ASP 프로그램으로부터 IIS 시스템 자체나 다른 ASP 프로그램을 보호하는 수준의 정도를 설정하는 항목이라는 것 정도는 알고 계실 것이다. 이를테면 이 항목이 낮음(IIS 프로세스)으로 설정되면 ASP 프로그램의 전체적인 속도는 빨라지지만 해당 ASP 프로그램에 심각한 문제가 있는 경우 IIS 서비스 자체까지도 중단될 수 있다든가, 반대로 높음(격리됨)으로 설정되면 IIS 서비스의 안정성이 증가되고 다른 ASP 프로그램에 끼치는 영향은 줄어들지만 ASP 프로그램의 속도가 느려진다든가 하는 등등의 얘기들 말이다. 그러나, 어떻게 무엇 때문에 이러한 결과가 발생하게 되는지 알고 계시는 분이 계시는지? 잠시 후에 이 질문에 대한 답을 살펴보도록 하겠다.

나머지 세 개의 항목들은 모두 버튼인데 만들기제거 버튼은 이름 그대로 웹 응용 프로그램을 만들거나 제거하는 기능을 갖고 있다. 그리고, 그 아래에 위치한 구성 버튼은 해당 웹 응용 프로그램의 속성들을 설정하는 기능을 가지고 있는 버튼으로, 그 성격상 당연히 웹 응용 프로그램이 존재한지 않는 디렉터리에서는 활성화되지 않는다. 그런데, 이 점을 한 번 생각해보기 바란다. 이미 알고 계시겠지만 구성 버튼을 누르면 나타나는 응용 프로그램 구성 대화 상자에서 설정 가능한 항목들은 다음과 같은 항목들이다. 각각의 파일 확장자에 따른 ISAPI 응용 프로그램 매핑, 세션 사용 여부 및 유지 시간, 버퍼링 사용 여부, 기본 ASP 프로그래밍 언어 설정, ASP 스크립트 시간 제한 설정, 그리고 ASP 프로그램 디버깅 여부 설정 등. 이처럼 세션 사용 여부와 같은 핵심적인 사항들까지도 이 대화 상자의 설정에 따라 결정되는데 웹 응용 프로그램이 설정되지 않은 디렉터리에서는 응용 프로그램 구성 대화 상자 자체를 띄울 수가 없을 뿐더러 그 설정 자체도 당연히 웹 응용 프로그램을 단위로 이루어진다. 따라서, 이 모든 항목들이 웹 응용 프로그램으로부터 종속적인 영향을 받을 것이라는 점을 미루어 짐작할 수 있으며, 그렇다면 앞에서 얘기했던 가상 디렉터리간에 세션이 공유되지 않는 등의 현상들은 지극히 당연한 일들일뿐 전혀 신기한 일이 아닌 것이다.

마지막 항목인 언로드 버튼은 이해하기에 상당히 난해한 동작 패턴을 보여준다. 위의 이미지를 다시 한 번 자세하게 살펴보기 바란다. 분명히 웹 응용 프로그램이 설정되어 있음에도 불구하고 언로드 버튼은 여전히 비활성화 되어 있다. 그런데 본문을 읽고 계시는 분들중에서 어떤 분들의 경우에는 자신의 머신에서 임의의 가상 웹 서버나 가상 디렉터리의 언로드 버튼 상태를 확인해봤을 때, 이 버튼이 활성화되어 있는 것을 발견하실 수 있는 분들도 계실 것이다. 그렇다면 언로드 버튼은 도대체 어떤 경우에 활성화되고 어떤 경우에 비활성화되는 것일까? 언로드 버튼은 현재 웹 응용 프로그램이 메모리에 로드되어 실행되고 있는 경우에만 활성화된다. 일단 로드가 되어 있어야만 언로드를 할 수 있다는 점을 생각해보면 이는 당연한 일이다. 따라서, 위의 이미지 같은 경우는 IIS 서비스가 시작되고 나서 이 가상 웹 서버나 가상 디렉터리에 설정된 웹 응용 프로그램의 리소스에 접근한 사용자가 한 명도 없는 경우라고 볼 수 있을 것이다. 반면, 이 버튼이 활성화되어 있는 분들의 경우에는 해당 웹 응용 프로그램의 리소스가 최소한 한 번 이상은 메모리에 로드된 상태라고 생각할 수 있는 것이다. 이처럼 언로드 버튼은 현재 메모리에 로드되어 실행되고 있는 웹 응용 프로그램을 언로드하는 기능을 갖고 있으며 일종의 메모리 초기화 같은 역활을 수행한다.

그런데, 이 점을 한 번 생각해보자. 언로드 버튼이 임의의 웹 응용 프로그램을 선택적으로 언로드할 수 있다는 사실은, 해당 웹 응용 프로그램을 언로드해도 다른 웹 응용 프로그램들은 거의 아무런 영향을 받지 않을 것이라는 점을 짐작하게 해준다. 그러나, 언제나 그런 식으로 동작하는 것은 아닌데 만약 응용 프로그램 보호 항목이 현재 보통(풀링됨)으로 설정되어 있다면 선택된 웹 응용 프로그램뿐만 아니라 웹 응용 프로그램 풀에 로드되어 있는 모든 웹 응용 프로그램들이 모두 언로드된다. 그렇다면, 웹 응용 프로그램은 도대체 어떤 구조로 프로세스가 처리되기에 이와 같이 동작 패턴을 보이는 것일까? 재미있게도 비단 이 질문뿐만 아니라 본문에서 제기된 모든 의문과 모든 미결 논제들은 다음과 같은 한 문장으로 정리될 수 있다. 바로 다음 단원의 논제이기도 한 COM+ 응용 프로그램이 그것이다.

COM+ 응용 프로그램

필자가 생각하기에 평소 COM+ 기술 전반에 관해 지속적인 관심을 가지고 계셨던 분들이 아니라면, 아마 지금 본문을 통해서 COM+ 응용 프로그램이라는 용어 그 자체를 처음 접하시는 분들도 많으실 것이라고 생각된다. 제어판의 관리 도구에서 구성 요소 서비스 스냅인을 실행시키고 좌측의 콘솔 트리를 확장시켜보면 다음 이미지와 유사한 모습을 볼 수 있을 것이다. 콘솔 트리의 노드들 중에서 상자에 들어 있는 십자가 문양 구슬 아이콘 노드들 하나 하나가 각각 하나의 COM+ 응용 프로그램을 나타내는 노드들인데 예전에 MTS에서 패키지라는 이름으로 불리던 바로 그것이다. 그리고, 참고로 이 이미지는 운영체제를 설치하고 난 직후의 순수한 초기 상태인 구성 요소 서비스 스냅인의 모습을 보여주고 있다.

COM+ 응용 프로그램

본문에서 다루고자 하는 논제들을 명확하게 이해하기 위해서는 COM+ 응용 프로그램의 활성화 유형에 따른 컴포넌트 로딩 방식의 차이점을 먼저 이해하고 있어야만 한다. COM+ 응용 프로그램의 활성화 유형에는 라이브러리 응용 프로그램과 서버 응용 프로그램, 이렇게 두 가지 종류가 있는데 활성화 유형을 이 중에서 어떤 유형으로 설정하느냐에 따라 해당 COM+ 응용 프로그램에 등록된 컴포넌트가 로딩되는 장소, COM+ 응용 프로그램의 프로세스 ID, 각종 제약 사항 등 수 많은 부분들이 극과 극으로 달라진다. 그런데, COM+ 응용 프로그램의 활성화 유형과 관련된 기술적인 사항들을 이해하기 위해서는 그에 앞서 전통적인 COM 컴포넌트와 관련된 특성들을 어느 정도 이해하고 있어야만 한다. 일반적으로 COM 컴포넌트에 관해서 학습하는 경우 대부분 가장 처음에 소개되는 개념들 중에 하나가 바로 인-프로세스 컴포넌트(In-Process Component)와 아웃 오브 프로세스 컴포넌트(Out of Process Component)에 관한 내용이다.

인-프로세스 컴포넌트와 아웃 오브 프로세스 컴포넌트는 해당 컴포넌트의 인스턴스가 컴포넌트를 생성하는 클라이언트 프로세스의 영역과 같은 영역에 생성되느냐 아니면 별개의 다른 프로세스 영역에 생성되느냐를 기준으로 구분된다. 인-프로세스 컴포넌트의 경우에는 클라이언트 프로세스 영역 내부에 해당 컴포넌트의 인스턴스가 생성되므로 클라이언트측에서 컴포넌트에 존재하는 프로퍼티에 접근하거나 메서드를 호출할 때 상대적으로 속도가 빠르고 추가적인 작업이 전혀 요구되지 않는다. 그리고, 클라이언트와 컴포넌트가 동일한 메모리 영역을 공유하므로 메서드의 인자로 포인터나 레퍼런스를 전달하는 경우 성능이 극대화된다. 그러나 같은 이유로 인해서 혹시라도 컴포넌트에서 치명적인 오류가 발생하는 경우에는 클라이언트에까지 치명적인 결과를 초래하게 되며, 주로 DLL 파일의 형태를 가지고 있다.

반면, 아웃 오브 프로세스 컴포넌트는 EXE 파일의 형태를 갖고 있으며 클라이언트 프로세스 영역 외부에 컴포넌트의 인스턴스가 생성된다. 따라서, 클라이언트측에서 컴포넌트에 존재하는 프로퍼티에 접근하거나 메서드를 호출할 때, 프로세스와 프로세스간의 경계를 넘어야하므로 상대적으로 속도가 느려질 수 밖에 없을 뿐더러 마샬링이라는 이름으로 알려져 있는 고비용의 추가 작업이 요구된다. 마샬링이란 프로세스간의 경계를 넘어서는 메서드 호출 과정에서 메서드의 인자값들을 COM 인터페이스에 정의된 구조에 맞춰 넘겨주고 또 결과를 돌려받기 위해서 데이터들을 패키징하는 작업을 말하는데, 이 작업 자체가 상당히 고비용의 작업이며 그 과정 중에 프록시 개체와 스텁 개체가 관여하게 된다. 마샬링에 관해서 더 자세하게 알고 싶으신 분들은 관련 서적들을 참고하기 바란다. 그리고, 인-프로세스 컴포넌트와는 달리 메서드의 인자로 포인터나 레퍼런스를 전달하는 경우 오히려 성능에 악영향을 미치게 된다. 왜냐하면 아웃 오브 프로세스 컴포넌트의 인스턴스는 클라이언트의 프로세스와 다른 영역에 생성되므로, 가령 포인터를 메서드에 인자값으로 전달한다고 해도 그 포인터가 가리키는 주소는 클라이언트측의 메모리 영역에 위치한 주소 공간일 뿐이다. 따라서, 컴포넌트측에서는 클라이언트측의 해당 포인터가 가리키고 있는 모든 데이터를 자신의 영역에 복사하고 난 뒤, 자신의 메모리 공간에 재구축된 그 데이터 영역의 주소를 다시 메서드에 포인터로 넘겨주는 이중의 작업을 실행하게 되고, 결국 처음부터 값 자체를 넘겨주는 것만 못한 결과가 발생하게 된다. 그러나, 아웃 오브 프로세스 컴포넌트는 해당 컴포넌트에 심각한 오류가 발생하더라도 클라이언트 측에는 거의 영향을 미치지 않는다는 장점을 갖고 있다. 즉, 컴포넌트측의 프로세스 공간만 파괴될 뿐, 전혀 별개의 프로세스에서 실행되고 있는 클라이언트 프로그램에는 아무런 영향도 주지 않는 것이다. 극단적으로 말하자면 전혀 별개의 머신에서 실행되는 DCOM도 아웃 오브 프로세스 컴포넌트의 일종으로 볼 수 있다.

인-프로세스 컴포넌트 모델과 아웃 오브 프로세스 컴포넌트 모델

이 이미지는 지금까지 설명한 내용들을 모두 정리하여 도식화한 것이다. 다만 이 내용들은 어디까지나 전통적인 COM 컴포넌트에 관한 것으로 COM+에 관한 내용들은 아니라는 점을 다시 한 번 기억해두기 바란다. 물론, COM+도 역시 큰 범주에서 살펴보면 지금까지 설명한 내용들에서 크게 벗어나는 것은 아니지만 세부적인 구현에 있어서는 상당히 많은 차이점들을 갖고 있다. 또한, COM+에는 반드시 인-프로세스 컴포넌트, 즉 DLL 파일 형태로 작성된 컴포넌트만 등록할 수 있기 때문에 서로게이트(Surrogate) 역활을 하는 DLLHOST.EXE를 사용해서 아웃 오브 프로세스 컴포넌트 모델과 유사한 구현을 한다. 더불어, COM+로부터 제공되는 여러 가지 기반 서비스들의 총체적인 환경 정보 집합체인 컨텍스트(Context)에 대한 개념들까지 도입되어 그 복잡성은 더욱 심해진다.

앞에서도 잠시 설명했지만 COM+ 응용 프로그램의 활성화 유형에는 라이브러리 응용 프로그램과 서버 응용 프로그램의 두 가지 종류가 있다. 라이브러리 응용 프로그램에 등록된 컴포넌트들은 인-프로세스 컴포넌트와 유사하게 동작하고, 서버 응용 프로그램에 등록된 컴포넌트들은 아웃 오브 프로세스 컴포넌트와 유사하게 동작한다고 생각하면 이해가 매우 쉬울 것이다. 구성 요소 서비스 스냅인의 콘솔 트리에 존재하고 있는 COM+ 응용 프로그램들 중에서 IIS In-Process Applications 응용 프로그램의 등록 정보를 살펴보면 활성화 탭에 다음과 같이 라이브러리 응용 프로그램으로 설정되어 있다는 사실을 알 수 있다.

IIS In-Process Applications - 라이브러리 응용 프로그램

이처럼 라이브러리 응용 프로그램으로 설정된 COM+ 응용 프로그램에 등록된 컴포넌트의 인스턴스는 언제나 그 컴포넌트를 생성하는 클라이언트의 프로세스 영역에 생성된다. 인-프로세스 컴포넌트 모델과 결정적으로 다른 점은 앞에서도 잠시 얘기한 바와 같이 클라이언트와 컴포넌트 사이에 COM+ 컨텍스트 개체가 추가된다는 사실이다. 그러나, 이와 관련된 논제들은 COM+와 깊게 연관된, 본문에서 다루고자 하는 영역을 벗어나는 내용이므로 이 자리에서는 그다지 깊게 다루지는 않기로 한다.

그런데 쉽게 예상할 수 있겠지만, COM+ 응용 프로그램의 활성화 유형이 서버 응용 프로그램으로 설정된 경우에는 보다 상황이 더 복잡해진다. 콘솔 트리에서 IIS Out-Of-Process Pooled Applications 응용 프로그램을 선택하고 등록 정보를 살펴보면 활성화 탭에 다음처럼 서버 응용 프로그램으로 설정되어 있다는 사실을 알 수 있다. 겉으로만 보기에는 별다른 차이점이 없는 것 같지만 이 단순한 라디오 버튼 하나의 선택에 따라 내부적인 동작 패턴이 그야말로 엄청나게 달라진다.

IIS Out-Of-Process Pooled Applications - 서버 응용 프로그램

이처럼 서버 응용 프로그램으로 설정된 COM+ 응용 프로그램에 등록된 컴포넌트는 아웃 오브 프로세스 컴포넌트와 비슷한 동작 패턴을 보여준다. 즉, 해당 컴포넌트의 인스턴스가 언제나 그 컴포넌트를 생성하는 클라이언트의 프로세스 영역과 별개의 프로세스 영역에 생성되는 것이다. 그러나, 이미 설명했던 바와 같이 COM+에는 DLL 파일 형태의 컴포넌트만을 등록할 수 있을 뿐이고, 당연히 DLL 파일은 그 자체만으로는 프로세스를 생성할 수 없다. 따라서, 이 상태로는 클라이언트와 별개의 프로세스에서 실행되는 아웃 오브 프로세스 컴포넌트의 특성을 구현할 수가 없는데, 그래서 등장한 것이 바로 DLLHOST.EXE 파일이다. 즉, 컴포넌트를 호스트하기 위한 DLLHOST.EXE 파일의 프로세스가 먼저 실행되고 난 뒤에 그 프로세스 위에 컴포넌트의 인스턴스가 생성되는 것이다. 그리고, 서버 응용 프로그램으로 활성화 유형이 설정된 COM+ 응용 프로그램들은 각각 하나 씩의 DLLHOST.EXE 인스턴스에 연결되므로 결과적으로 같은 COM+ 응용 프로그램에 등록된 컴포넌트들은 모두 동일한 DLLHOST.EXE의 프로세스를 공유하게 된다.

라이브러리 응용 프로그램과 서버 응용 프로그램

지금까지 장황하게 설명하기는 했지만 결국 요점은 라이브러리 응용 프로그램과 서버 응용 프로그램에서의 컴포넌트 인스턴스 생성 위치에 따른 안정성 및 기타 특성들에 관한 것인데, 결론적으로 라이브러리 응용 프로그램의 성능이 더 우수하지만 컴포넌트에서 오류가 발생하는 경우에는 클라이언트 프로세스의 안전성을 보장받을 수 없으며, 반대로 서버 응용 프로그램은 성능 측면에서 추가적인 오버헤드가 발생하지만 컴포넌트에서 오류가 발생하더라도 클라이언트 프로세스는 비교적 영향을 받지 않는다는 것이 요점이다.

그리고, COM+ 응용 프로그램의 활성화 유형에 따라 밀접한 영향을 받게 되는 몇 가지 추가적인 특성들 중에는 프로세스 ID가 있는데, 프로세스 ID란, 단어의 뜻 그대로 해당 프로세스에 부여된 ID로서 프로세스에서 접근하고자 하는 시스템 리소스에 대한 권한을 가지고 있는지 여부를 판단하는 기준이 된다. 일반적으로 여러분이 윈도우즈 시스템에 로그인을 하고 임의의 프로그램을 실행시키면 해당 프로그램은 여러분들이 로그인할 때 사용한 계정의 권한을 그대로 이어 받은 상태로 실행이 된다. 따라서, 여러분의 계정이 어떤 시스템 리소스에 접근할 수 있는 권한을 갖고 있지 않다면 해당 프로그램에서도 권한 오류가 발생하게 되는데, 이런 경우 해당 프로그램의 프로세스 ID는 바로 여러분들의 계정이 되며, 결국 프로세스 ID에 적절한 권한이 존재하지 않기 때문에 오류가 발생하게 되는 것이다. 그런데, 특수한 경우에는 프로세스 ID를 다른 계정으로 잠시 동안 전환하여 사용할 수 있는 방법이 몇 가지 존재한다. 가령, 실제로는 임의의 프로세스에 A라는 계정으로 프로세스 ID가 설정되어져 있지만 해당 프로세스로부터 생성된 특정 쓰레드에 한해서 B라는 계정으로 프로세스 ID를 임시로 설정해서 실행시킬 수가 있다. 이러한 기법을 가장 또는 의인화(Impersonation)라고 부르는데 일단 본문에서는 마이크로소프트사의 한글 홈페이지에서 사용되는 가장이라는 용어로 통일하여 사용하도록 하겠다. 또다른 프로세스 ID의 특수한 사례로는 윈도우즈 서비스에 설정되는 프로세스 ID를 예로 들 수 있다. 모든 윈도우즈 서비스는 운영 체제의 일부인 SCM(Service Control Manager)에 의해서 제어되는데, 현재 시스템에 로그인한 사용자가 한 명도 없더라도 항상 정상적으로 실행되어야만 하는 특성을 가지고 있다. 그런데 아이러니하게도, 현재 시스템에 로그인한 사용자가 한 명도 존재하지 않는다는 얘기는 곧 프로세스 ID로 권한을 이어 받을 수 있는 계정이 전혀 존재하지 않는다는 의미가 된다. 그러나, 윈도우즈 시스템상에서 실행되는 모든 프로세스는 프로세스 ID를 갖고 있어야만 하고 이 규칙은 윈도우즈 서비스의 프로세스도 결코 예외가 될 수 없다. 따라서, 각각의 윈도우즈 서비스에는 해당 프로세스를 실행하기 위한 프로세스 ID가 강제로라도 지정되어야만 하는데, 대부분 윈도우즈 서비스에는 'SYSTEM'이라는 미리 운영 체제로부터 제공되어지는 계정이 프로세스 ID로 설정되는 것이 일반적이다. 다음 이미지는 제어판의 관리 도구에서 서비스 스냅인을 실행하고 World Wide Web Publishing Service, 즉 IIS 의 웹 서비스에 해당하는 윈도우즈 서비스의 등록 정보 설정을 살펴본 화면인데, 로컬 시스템 계정 라디오 버튼이 체크되어져 있다는 점을 확인할 수 있다. 여기에서 한 가지 주의해야 할 부분은 로컬 시스템 계정이라는 용어를 '현재 시스템에 존재하는 계정'이라고 오해하기가 매우 쉽다는 점인데, 사실 이 용어는 조금전에 설명했던 SYSTEM 계정을 뜻하는 것으로 혼동될 여지가 상당히 많은 부분이다.

World Wide Web Publishing Service 로그온 정보

그리고, SYSTEM 계정은 Administrator 그룹에 속한 계정과 완벽하게 동일한 수준의 권한을 가지고 있는 내부 계정인데, 사실 SYSTEM 계정은 일반 사용자가 아닌 윈도우즈 운영체제 자체에 의해서 사용되기 위한 목적으로 디자인된 계정으로, 지금과 같이 윈도우즈 서비스의 프로세스 ID로 사용되거나 윈도우즈 운영체제 자체를 설치하는 과정 중에서 내부적으로 사용된다 (Windows에서 시스템 계정 사용 방법). 그러나, 이처럼 SYSTEM 계정이 강력한 권한을 갖고 있다는 사실이 문제가 될 수도 있는데, 만약 SYSTEM 계정으로 실행되고 있는 프로세스가 '검사되지 않은 버퍼'로 알려진 보안상의 결함 등을 가지고 있다면 악의적인 사용자에게 시스템 전체의 권한을 침해받는 경우도 충분히 발생할 수가 있는 것이다. 따라서, 이런 문제점을 피하려면 가급적 해당 윈도우즈 서비스를 실행하기 위해서 필요한 최소한의 권한만을 할당한 별도의 계정을 생성하여 직접 지정해주는 것이 바람직하며, 이런 작업을 위해서는 계정 지정 라디오 버튼을 체크하고, 찾아보기 버튼을 클릭해서 적절한 계정을 선택하거나 직접 계정을 타이핑해서 입력하고 암호를 입력해주면 된다. 참고로 윈도우즈 2003 제품군에서는 NETWORK SERVICE라는 계정과 LOCAL SERVICE라는 두 가지 새로운 내부 계정을 지원하는 방식으로 이런 문제점을 해결한다. 이 중에서 NETWORK SERVICE 계정은 네트워크 상에 존재하는 다른 시스템의 리소스에 접근할 필요가 있는 윈도우즈 서비스를 위해 준비된 계정이고 LOCAL SERVICE 계정은 로컬 시스템의 리소스에만 접근하는 윈도우즈 서비스를 위해 준비된 계정으로, 두 계정 모두 SYSTEM 계정과는 달리 사용자들의 계정 정보를 변경하거나 임의로 시스템을 중지할 수 없으며 기타 관리와 관련된 권한들은 갖고 있지 않다.

그런데 재미있는 사실은 COM+ 응용 프로그램에도 이와 유사한 프로세스 ID의 개념이 존재하고 있으며 나름대로 관리가 가능하다는 점이다. 이는 어떤 면에서 생각해보면 매우 당연한 일이라고 말할 수 있다. 왜냐하면 활성화 유형이 라이브러리 응용 프로그램인 COM+ 응용 프로그램은 클라이언트의 프로세스 상에서 실행되므로 언제나 클라이언트 프로세스의 프로세스 ID를 상속받아 실행되기 때문에 독자적인 프로세스 ID를 선택하는 등의 처리가 애초에 불가능하지만, 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램은 클라이언트의 프로세스와는 별개로 독자적인 DLLHOST.EXE의 프로세스에서 실행되므로 각각의 프로세스에 대한 프로세스 ID 선택이 가능하기 때문이다. 구성 요소 서비스 스냅인에서 IIS In-Process Applications 응용 프로그램의 등록 정보를 열고 확인 탭을 살펴보면 다음 이미지와 유사한 결과가 출력되는 것을 확인할 수 있는데, 탭 안에 존재하는 모든 컨트롤들이 비활성화 되어 있다는 점에 주의하기 바란다.

IIS In-Process Applications - 라이브러리 응용 프로그램

이처럼 모든 컨트롤들이 비활성화 되어 있는 이유는 이 COM+ 응용 프로그램의 활성화 유형이 바로 라이브러리 응용 프로그램이기 때문이다. 방금 전에도 설명했던 바와 같이 활성화 유형이 라이브러리 응용 프로그램인 COM+ 응용 프로그램은 항상 클라이언트 프로세스 상에서 실행되므로 프로세스 ID에 대한 선택의 여지 자체가 없기 때문에 아예 모든 컨트롤들이 비활성화되어 나타나는 것이다.

반면 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램의 경우에는 사정이 조금 달라지는데 비교적 자유로운 프로세스 ID의 설정이 가능하다. 콘솔 트리에서 IIS Out-Of-Process Pooled Applications 응용 프로그램의 등록 정보를 열고 확인 탭을 살펴보면, 이번에는 다음 이미지와 같이 탭 안의 모든 컨트롤들이 활성화되어 있는 것을 확인할 수 있을 것이다. 그 이유는 여러분들도 쉽게 짐작할 수 있는 것처럼 이 COM+ 응용 프로그램의 활성화 유형이 서버 응용 프로그램이기 때문이다. 여기에서 선택할 수 있는 옵션에는 대화형 사용자 - 현재 로그온된 사용자다음 사용자, 이렇게 두 가지 종류가 있는데, 먼저 대화형 사용자 - 현재 로그온된 사용자 라디오 버튼을 선택한 경우에는 단어의 뜻 그대로 현재 시스템에 로그온된 사용자의 계정을 프로세스 ID로 사용하게 된다. '현재 로그온된 사용자' 라는 문장이 가지고 있는 의미 중에는 터미널 서비스 클라이언트를 사용해서 로그온한 사용자라는 뜻도 포함되는데 이런 특성 때문에 가끔 원하지 않는 상황이 발생하기도 한다. 즉, 개발자가 임의의 컴포넌트를 만들고 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램에 등록한 다음, 확인 탭에서 대화형 사용자 - 현재 로그온된 사용자 라디오 버튼을 선택했다고 가정해보자. 콘솔을 포함하여 시스템에 로그온한 사용자가 한 명도 없는 상태에서 개발자가 터미널 서비스 클라이언트를 통해서 시스템에 로그인하고 여러가지 설정을 하면서 동시에 자신의 머신에서는 방금 설명했던 컴포넌트를 사용하는 ASP 프로그램을 개발하거나 테스트하는 경우, 해당 ASP 프로그램은 아무런 이상 없이 정상적으로 동작할 것이다. 그러나, 개발자가 터미널 서비스 클라이언트에서 로그오프하면 그 때부터 갑자기 잘 동작하던 ASP 프로그램에서 오류가 발생하기 시작한다. 왜냐하면, 현재 시스템에 로컬 로그온한 사용자가 단 한 명도 없는 상태이므로 ASP 프로그램에서 사용된 컴포넌트가 등록된 COM+ 응용 프로그램의 서로게이트인 DLLHOST.EXE 프로세스의 프로세스 ID로 사용할 수 있는 '현재 로그온된 사용자'가 존재하지 않기 때문이다. 결과적으로 윈도우즈 응용 프로그램에서 사용되는 컴포넌트인 경우에는 대화형 사용자 - 현재 로그온된 사용자 옵션을 선택해도 무방하지만, ASP 프로그램에서 사용되는 컴포넌트인 경우에는 다음 사용자 옵션을 사용하여 특정 계정을 명확하게 지정해주는 것이 바람직하다. (PRB: Server Execution Failed When Calling MTS COM Component from ASP)

IIS Out-Of-Process Pooled Applications - 서버 응용 프로그램

반면, 다음 사용자 옵션을 사용하여 프로세스 ID로 사용될 계정을 직접 지정해주면 해당 COM+ 응용 프로그램의 프로세스는 항상 그 계정으로 실행되므로 대부분의 경우 클라이언트의 프로세스 ID와는 전혀 별개의 권한을 갖게 된다. 결국, 폭넓은 관점에서 생각해본다면 이런 결과 역시도 위에서 설명했던 가장의 일종으로 볼 수 있으며, 잘 활용하기만 한다면 전체적인 작업 진행 과정중에서 특정한 구간의 권한만을 조절하는 것이 가능해지므로 프로그램 보안의 관점에서 볼 때 상당히 유용하다고 말할 수 있을 것이다. 참고로 필자의 또 다른 글에서는 바로 이런 특성을 활용해서 ASP 프로그램에서 컴포넌트를 효과적으로 사용하는 방법에 관해서 다루고 있는데 이 논제에 관해서 보다 많은 관심을 갖고 계신 분들은 이 문서를 참고하시기 바란다.

마지막으로 COM+ 응용 프로그램의 프로세스 상태를 파악하는 방법에 대해서 몇 가지 간단한 설명을 마치고 본문의 핵심 주제를 다루고 있는 다음 단원으로 넘어가기로 한다. 구성 요소 서비스 스냅인을 실행시키고 콘솔 트리에서 COM+ 응용 프로그램 노드를 마우스로 선택한 다음 보기 메뉴에서 상태 보기를 선택하면 다음 이미지와 같이 우측 패인에 COM+ 응용 프로그램들에 대한 상태 정보가 출력된다.

COM+ 응용 프로그램 상태 정보 보기

그런데 재미있는 것은, 이 우측 패인을 자세히 살펴보면 최소한 하나 이상의 COM+ 응용 프로그램 아이콘들이 다음의 이미지와 같이 에니메이션 되고 있을 것이라는 점이다. 리스트 뷰의 실행 중 항목에 출력된 내용으로 미루어 쉽게 짐작할 수 있겠지만 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램은 실행되고 있는 동안 이처럼 아이콘에 그려진 구슬이 에니메이션 된다. 반면, 활성화 유형이 라이브러리 응용 프로그램인 COM+ 응용 프로그램 아이콘의 경우에는 그 실행 여부와는 상관없이 언제나 정지된 상태를 유지하는데 왜냐하면 활성화 유형이 라이브러리 응용 프로그램인 COM+ 응용 프로그램은 항상 클라이언트의 프로세스에서 활성화되므로 독자적인 프로세스 정보를 갖고 있지 않기 때문이다. 즉, 여기에 출력되는 정보들은 COM+ 응용 프로그램들의 프로세스, 즉 DLLHOST.EXE의 간단한 정보라고 보면 된다.

현재 실행되고 있는 COM+ 응용 프로그램의 아이콘 모습

그리고 그 옆의 PID 항목은 해당 DLLHOST.EXE의 프로세스 ID를 나타내는데, 이 곳의 프로세스 ID와 앞에서 논의했던 프로세스 ID를 혼동하지 말기 바란다. 지금 얘기하는 프로세스 ID는 운영체제가 모든 프로세스를 대상으로 일괄적으로 하나 씩 부여하는 일련번호 같은 것으로서 각각의 프로세스를 구분하는 기준이 되는 임의의 숫자값이고, 앞에서 논의했던 프로세스 ID는 해당 프로세스가 갖게 되는 권한을 부여하는 계정을 의미하는 것이다. 예를 들어서 필자의 경우에는 System Application 응용 프로그램의 PID 값이 1116으로 나타났으며 Ctrl + Shift + Esc 키를 누르고 작업 관리자를 실행시켜서 동일한 PID를 갖고 있는 DLLHOST.EXE의 프로세스 항목을 찾을 수 있었다.

COM+ 응용 프로그램 상태 정보 보기

이처럼 위에서 살펴본 두 가지 방법으로 얻어낼 수 있는 프로세스 정보는 서로 완벽하게 동일한 프로세스를 의미하는 것으로서 한 쪽 편에서 해당 프로세스를 중지시키면 다른 한 편에서도 즉시 영향을 받게 된다. 이를테면 작업 관리자에서는 프로세스 끝내기 버튼을 사용해서 프로세스를 중지시킬 수 있으며, 구성 요소 관리자에서는 해당 COM+ 응용 프로그램을 마우스 오른쪽 버튼으로 클릭하고 팝업 메뉴에서 시스템 종료 메뉴를 선택하면 프로세스를 중지시킬 수 있다. 그러나, 한 가지 예외로 System Application 응용 프로그램의 프로세스는 절대 중지가 불가능하다는 사실을 참고하기 바란다.

COM+ 응용 프로그램과 IIS 웹 응용 프로그램간의 상호 관계

결론적으로 말해서 모든 IIS 웹 응용 프로그램은 구성 요소 서비스의 COM+ 응용 프로그램을 기반으로 실행된다. 이는 비유적인 표현이나 상징적인 의미로서가 아니라 일말의 가감도 없이 문장을 구성하고 있는 단어들이 의미하는 바 그대로를 뜻한다. 보다 극단적으로 표현하자면 'COM+ 응용 프로그램을 기반으로 하지 않고서는 IIS 웹 응용 프로그램 그 자체가 성립되지 않는다.'라고까지 말할 수 있으며, 이론적으로 구성 요소 서비스를 기반으로 하지 않는 IIS 5.0 자체만으로는 단순히 HTML 파일을 비롯한 극히 일부의 몇 가지 유형의 컨텐츠들만을 처리할 수 있을 뿐이다. 예전에 윈도우즈 NT 서버 4.0을 기반으로한 IIS 4.0을 운영해본 경험을 가지고 있다면 Option Pack 4.0 설치하면서 MTS를 설치하지 않으면 IIS 4.0 역시도 정상적으로 설치되지 않는다는 것을 기억하고 있을 것이다. 그 원인 역시도 동일한 이유 때문이다.

조금 더 구체적인 내용들을 알아보기 위해, 먼저 IIS 웹 응용 프로그램에 설정된 응용 프로그램 보호 항목의 상태에 따른 INETINFO.EXE 프로세스와 DLLHOST.EXE 프로세스, 그리고 ASP.DLL ISAPI 확장 프로그램의 쓰레드간의 상관 관계에 대해서 알아보도록 하자. 익히 알고 있는 것처럼 IIS의 웹 서비스는 원도우즈 서비스의 형태로, 조금 더 구체적으로 말하자면 INETINFO.EXE 프로세스의 형태로 실행된다. 그리고, 만약 특정 IIS 웹 응용 프로그램의 응용 프로그램 보호 항목이 낮음(IIS 프로세스)으로 설정되어 있다면, 그 웹 응용 프로그램에 속해 있는 모든 ASP 프로그램들은 INETINFO.EXE 프로세스의 내부에서 실행된다. 그저 일반적인 관점으로 여기까지만 생각해보면 이런 과정들간에 COM+ 응용 프로그램이 개입될 여지는 그다지 없는 것처럼 보인다. 그러나, 사실은 전혀 다르다. 다시 한 번 구성 요소 서비스 스냅인의 콘솔 트리에서 이미 여러 차례 살펴봤던 IIS In-Process Applications 응용 프로그램을 찾아보기 바란다. 이 COM+ 응용 프로그램의 이름이 시사하는 바는 매우 큰데 하위의 구성 요소 노드를 확장해서 등록되어 있는 컴포넌트를 살펴보면 다음과 같이 IISWAM.W3SVC라는 하나의 컴포넌트만이 존재하고 있음을 알 수 있다.

IISWAM.W3SVC 컴포넌트

이 컴포넌트를 WAM, 즉 웹 응용 프로그램 관리자(Web Application Manager)라고 부르는데 그야말로 이름에 걸맞는 작업을 처리하는 컴포넌트라고 말할 수 있다. 가령, 클라이언트로부터 IIS에 일반 HTML 파일에 관한 새로운 요청이 접수되면 이 요청은 INETINFO.EXE 프로세스로 보내진다. 그러면, INETINFO.EXE 프로세스는 그다지 특별한 작업 없이 지정된 파일을 찾아 클라이언트로 전송하는 것으로 모든 작업이 마무리 된다. 그러나, 만약 클라이언트가 요청한 파일이 ASP 프로그램 파일이라면, 게다가 그 ASP 프로그램 파일이 응용 프로그램 보호 항목이 낮음(IIS 프로세스)으로 설정된 웹 응용 프로그램에 속해 있다면 양상이 크게 달라진다. 클라이언트의 요청을 받은 INETINFO.EXE 프로세스가 가장 먼저 하는 일이 바로 IISWAM.W3SVC 컴포넌트의 인스턴스를 생성하는 것이다. 그런데, 중요한 점은 기억하고 있는 것처럼 이 컴포넌트가 등록되어 있는 IIS In-Process Applications 응용 프로그램의 활성화 유형이 라이브러리 응용 프로그램이라는 점이다. 따라서, 이 컴포넌트의 인스턴스는 INETINFO.EXE 프로세스의 내부에 생성된다. 이제 WAM은 요청된 리소스가 ASP 프로그램 파일이라는 것을 파악하고 메타베이스를 검색해서 ASP 확장자를 대상으로 매핑된 ISAPI 확장 프로그램인 ASP.DLL을 로드한다. 이때, ASP.DLL의 인스턴스 역시 INETINFO.EXE 프로세스의 내부에 생성된다는 사실을 기억하기 바란다. 이제 마지막으로 ASP.DLL은 해당 ASP 프로그램 파일을 읽어들이고 페이지 상단의 LANGUAGE 지시자나 메타베이스에 설정된 기본 스크립트 언어의 스크립트 엔진을 로딩해서 처리를 하게 된다. 다음은 지금까지 설명한 내용을 도식화한 것이다. 앞으로 설명을 진행해 나감에 따라 이 이미지에 조금씩 더 복잡한 내용들이 추가될 것이기 때문에 스크립트 엔진과 같은 일부 항목들은 생략됐다는 점을 참고하기 바란다.

'응용 프로그램 보호' 항목이 '낮음(IIS 프로세스)'으로 설정되어 있는 IIS 웹 응용 프로그램

따라서, 만약 이 상태에서 ASP 프로그램 자체나 그 ASP 프로그램에서 사용하고 있는 컴포넌트로부터 치명적인 오류가 발생한다면, 그 오류는 INETINFO.EXE 프로세스 자체에까지 심각한 악영향을 미치게 되는데, 반면 앞에서 설명했던 것과 같은 인-프로세스 컴포넌트나 라이브러리 응용 프로그램으로 설정된 COM+ 응용 프로그램으로부터 얻을 수 있는 모든 성능상의 장점을 고스란히 얻을 수 있는 것이다. 그렇다면, 이번에는 이 ASP 프로그램이 COM 컴포넌트의 개체를 생성해서 사용하는 경우를 생각해보자. 일반적으로 생각할 수 있는 가능성에는 모두 세 가지 정도가 존재하는데, 일반적인 COM 컴포넌트를 사용하는 경우와 활성화 유형이 라이브러리 응용 프로그램인 COM+ 응용 프로그램에 등록된 COM 컴포넌트를 사용하는 경우, 그리고 마지막으로 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램에 등록된 COM 컴포넌트를 사용하는 경우가 바로 그것이다. 일반적인 COM 컴포넌트를 사용하는 경우나 라이브러리 응용 프로그램인 COM+ 응용 프로그램에 등록된 COM 컴포넌트를 사용하는 경우에는 이미 설명했던 바와 같이 컴포넌트의 인스턴스가 INETINFO.EXE 프로세스의 내부에 만들어지게 된다. 물론 컨텍스트 개체가 존재하느냐 존재하지 않느냐 하는 커다란 차이점이 존재하기는 하지만 인스턴스가 생성되는 위치라는 관점에서 볼 때, 이 두 가지 경우는 거의 동일한 결과를 보여준다고도 말할 수 있을 것이다.

그러나, 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램에 등록된 COM 컴포넌트를 사용하는 경우에는 다소 양상이 복잡해진다. 이미 설명했던 것처럼, 이런 경우 COM 컴포넌트의 인스턴스는 클라이언트인 INETINFO.EXE 프로세스가 아닌 별도의 DLLHOST.EXE 프로세스 내부에 만들어진다. 또한, 프로세스간에 이뤄지는 데이터의 이동을 처리하기 위한 프록시 개체와 스텁 개체가 생성되며 컴포넌트쪽에는 컨텍스트까지 생성된다. 결과적으로 상당히 복잡해지게 되는데, 다음은 지금까지 설명한 내용들을 도식화한 이미지로 위에서부터 차례로 일반적인 COM 컴포넌트를 사용하는 경우, 활성화 유형이 라이브러리 응용 프로그램인 COM+ 응용 프로그램에 등록된 COM 컴포넌트를 사용하는 경우, 그리고 마지막으로 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램에 등록된 COM 컴포넌트를 사용하는 경우를 나타내고 있다.

'응용 프로그램 보호' 항목이 '낮음(IIS 프로세스)'으로 설정되어 있는 IIS 웹 응용 프로그램과 컴포넌트

단순하게 위의 이미지를 한 번 살펴보는 것 만으로도 ASP 프로그램에서 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램에 등록된 COM 컴포넌트를 사용하는 경우에 발생되는 실행 속도의 손실이라는 것이 얼마나 큰 것인지 파악할 수 있을 것이다. 물론 이런식으로 발생되는 손실은 조건이 만족되는 경우 COM+ 서비스로부터 제공되어지는 여러가지 서비스들을 잘 활용하면 얼마든지 보상이 가능하고 경우에 따라서는 그저 단순하게 실행 속도가 향상되는 것 이상의 이득을 얻을 수도 있다. 그러나, COM+ 서비스로부터 제공되는 그 어떠한 서비스도 사용하지 않는 일반적인 컴포넌트를 아무런 고려도 없이 무조건 서버 응용 프로그램 유형의 COM+ 응용 프로그램에 설치하는 일은 가급적 피해야 한다. 물론, 디버깅 과정상의 편의를 목적으로 의도적으로 사용하는 경우처럼 예외적인 경우도 있을 수 있을 것이다. 즉 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램에 등록된 COM 컴포넌트를 사용하는 경우에는 DLLHOST.EXE 프로세스만 메모리로부터 내리는 것이 가능하므로 INETINFO.EXE 프로세스에 어떠한 영향도 주지 않고 현재 사용중인 컴포넌트를 다시 컴파일하는 것이 가능하다. 반면, 다른 두 가지 경우에는 컴포넌트의 인스턴스가 INETINFO.EXE 프로세스의 내부에 생성되므로 INETINFO.EXE 프로세스 자체를 재시작하지 않고서는 컴포넌트를 다시 컴파일하는 것이 불가능하므로 IIS의 웹 서비스를 다시 시작해야만 하기 때문이다. 이런 이유 때문에 가끔 의도적으로 서버 응용 프로그램 유형의 COM+ 응용 프로그램에 컴포넌트를 등록해서 개발상의 편의를 얻기도 한다.

이번에는 응용 프로그램 보호 항목이 보통(풀링됨)으로 설정된 IIS 웹 응용 프로그램의 실행 과정에 관해서 생각해보자. 이 경우에는 지금까지와는 또 다른 관점에서 상당히 흥미로운 결과가 나타나게 되는데, 대체적으로 IISWAM.W3SVC 컴포넌트의 인스턴스가 생성되는 부분까지는 응용 프로그램 보호 항목이 낮음(IIS 프로세스)으로 설정된 IIS 웹 응용 프로그램이 실행되는 일련의 과정과 거의 동일하다고 볼 수 있다. 그러나, 이번에는 IISWAM.W3SVC 컴포넌트의 인스턴스가 ASP.DLL ISAPI 확장 프로그램을 로드하는 것이 아니라, 시스템으로부터 지원되는 또 다른 유형의 WAM인 IISWAM.OutofProcessPool 컴포넌트의 인스턴스를 생성한다. 이 컴포넌트에 관해서 간단하게 설명을 하자면 IISWAM.W3SVC 컴포넌트의 아웃 오브 프로세스 대응용 버전이라고 생각하면 되는데, 또 다른 COM+ 응용 프로그램인 IIS Out-Of-Process Pooled Applications 응용 프로그램에 미리 준비되어져 있다. 다음의 이미지를 참고하기 바란다. 그리고, 지금에서야 하는 얘기지만 눈치가 빠르신 분들은 이미 이 COM+ 응용 프로그램의 이름을 보고 어느 정도는 미리 짐작하고 있었을 것이라고 생각한다.

IISWAM.OutofProcessPool 컴포넌트

그런데 한 가지 주의해야 할 점은, 이 컴포넌트가 등록된 COM+ 응용 프로그램이 서버 응용 프로그램 유형의 COM+ 응용 프로그램이라는 사실이다. 따라서, IISWAM.OutofProcessPool 컴포넌트의 인스턴스는 웹 서비스 그 자체의 프로세스인 INETINFO.EXE 프로세스가 아니라 분리된 별도의 DLLHOST.EXE 프로세스에서 생성되게 되고, 이 컴포넌트가 ASP.DLL ISAPI 확장 프로그램을 자신이 존재하고 있는 프로세스와 같은 DLLHOST.EXE 프로세스에 로드한다. 그리고 최종적으로는 이 ASP.DLL ISAPI 확장 프로그램이 ASP 프로그램 파일을 읽어들인 다음, 페이지 상단의 LANGUAGE 지시자나 메타베이스에 설정된 기본 스크립트 언어에 대응하는 스크립트 엔진을 로딩해서 처리하는 것으로 모든 과정이 마무리된다. 다음은 이 과정을 도식화한 이미지이다.

'응용 프로그램 보호' 항목이 '보통(풀링됨)'으로 설정되어 있는 IIS 웹 응용 프로그램과 컴포넌트

결과적으로 INETINFO.EXE 프로세스쪽의 구성이 비교적 단순해지고 DLLHOST.EXE 프로세스로 대부분의 처리가 넘어갔다는 사실을 알 수 있다. 참고로 IISWAM.W3SVC 컴포넌트와 IISWAM.OutOfProcessPool 컴포넌트간에 존재하는 프록시 개체와 스텁 개체는 도식에서 생략했다는 점을 염두에 두기 바란다. 이런 형태는 웹 서비스 자체의 프로세스인 INETINFO.EXE 프로세스의 안정성을 크게 향상시킨다. 그리고, 그 안정성에 대한 대가라고 말하기는 조금 뭐하지만 대신 ASP 프로그램을 처리하는 속도는 비교적 많이 느려지게 된다. 그런데, 지금 상황에서 클라이언트로부터 응용 프로그램 보호 항목이 보통(풀링됨)으로 설정된 다른 IIS 웹 응용 프로그램의 프로그램에 대한 요청을 받는다면 어떻게 될까? 이쯤되면 여러분들도 대충 짐작할 수 있겠지만 이미 풀링을 위해 준비된 DLLHOST.EXE 프로세스가 존재하므로 새로운 DLLHOST.EXE 프로세스를 생성하는 것이 아니라 현재의 DLLHOST.EXE 프로세스를 공유하게 된다. 즉, 다음과 같이 하나의 DLLHOST.EXE 프로세스를 두 개 이상의 IIS 웹 응용 프로그램들에서 공유하게 되는 것이다.

'응용 프로그램 보호' 항목이 '보통(풀링됨)'으로 설정되어 있는 IIS 웹 응용 프로그램과 컴포넌트

이제 IIS 웹 응용 프로그램이 풀링된다는 말의 의미가 확실하게 와 닿을 것이라고 생각한다. 그런데, 이 모델의 단점은 하나의 IIS 서버에 응용 프로그램 보호 항목이 보통(풀링됨)으로 설정된 IIS 웹 응용 프로그램이 몇 개가 존재하던지, 즉 단 한 개만 존재하던지 아니면 수 백개 이상이 존재하던지 상관하지 않고 고지식할 정도로 단 하나의 DLLHOST.EXE 프로세만을 공유한다는 사실이다. 따라서, 만약 그 중에서 단 하나의 IIS 웹 응용 프로그램이라도 치명적인 오류를 발생시킨다면 나머지 수 십, 수 백개의 IIS 웹 응용 프로그램들도 역시 고스란히 그 영향을 받게 된다는 결론이 나온다. 윈도우즈 2003 제품군의 IIS 6.0에서는 응용 프로그램 풀이라는 개념을 도입해서 관리자가 직접 복수의 풀을 관리하고 특정 IIS 웹 응용 프로그램을 그 응용 프로그램 풀에 직접 할당할 수 있는 기능을 제공해줌으로서 이런 단점을 개선하고 있다. 즉, 관리자가 판단한 중요도에 따라서 IIS 웹 응용 프로그램을 임의대로 특정한 응용 프로그램 풀에 그룹핑 할 수 있으며, 만약 적당한 응용 프로그램 풀이 없다면 새로 생성하거나 또는 필요에 따라서는 기존에 존재하는 응용 프로그램 풀을 삭제할 수도 있는 것이다. 아무튼 이번에는 응용 프로그램 보호 항목이 보통(풀링됨)으로 설정된 IIS 웹 응용 프로그램의 ASP 프로그램에서 컴포넌트를 사용하는 경우의 실행 과정에 대해서 한 번 생각해보자. 지금까지 설명했던 내용들과 그 기본적인 원칙은 대체로 동일하기 때문에 별도로 설명을 한다거나 하지는 않을 것이다. 다음은 이와 관련된 내용들을 도식화한 것이다.

'응용 프로그램 보호' 항목이 '보통(풀링됨)'으로 설정되어 있는 IIS 웹 응용 프로그램과 컴포넌트

그저 한 눈에 살펴보기만 해도 이전의 도식과 비교하여 무지막지할 정도로 복잡해졌다는 사실을 알 수 있을 것이다. 위에서부터 차례대로 일반적인 COM 컴포넌트를 사용하는 경우와 활성화 유형이 라이브러리 응용 프로그램인 COM+ 응용 프로그램에 등록된 COM 컴포넌트를 사용하는 경우, 그리고 가장 마지막이 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램에 등록된 COM 컴포넌트를 사용하는 경우를 나타내고 있는데 특히나 가장 복잡한 구성을 보여주고 있는 마지막 도식과 같은 구성은 반드시 사용해야만 할 특별한 이유가 없다면 가급적 피하는 것이 바람직하다. 그러나, 앞에서도 한 번 언급했던 것처럼 개발 기간 도중이라던가 프로세스 ID 가장을 사용하고자 하는 경우와 같은 일부 특수한 상황에서는 역으로 이러한 구성이 엄청난 이점을 안겨주므로 무조건 나쁘기만 한 구성이라고는 말할 수 없을 것이다. 이런 내용들에 관해서는 본문의 뒷 부분에서 다시 한 번 다루도록 할 것이다.

이제 마지막으로 응용 프로그램 보호 항목이 높음(격리됨)으로 설정된 IIS 웹 응용 프로그램의 실행 과정에 대해서 생각해보자. 이 경우 기본적으로 처리되는 과정 자체는 응용 프로그램 보호 항목이 보통(풀링됨)으로 설정된 IIS 웹 응용 프로그램이 처리되는 과정과 거의 동일하다. 그러나, 결정적인 한 가지 부분에 있어서 근본적으로 차이가 나게 되는데, 그것은 바로 IISWAM.OutOfProcessPool 컴포넌트가 활성화되는 COM+ 응용 프로그램이 별도로 생성되게 된다는 점이다. 결론부터 얘기하자면 응용 프로그램 보호 항목이 높음(격리됨)으로 설정된 각각의 IIS 웹 응용 프로그램들마다 각각 그에 대응하는 COM+ 응용 프로그램도 하나씩 대응되게 된다. 다음은 시스템에 응용 프로그램 보호 항목이 높음(격리됨)으로 설정된 IIS 웹 응용 프로그램이 하나도 존재하지 않을 때의 구성 요소 서비스 스냅인의 콘솔 트리 모습이다.

'응용 프로그램 보호' 항목이 '높음(격리됨)'으로 설정된 IIS 웹 응용 프로그램이 하나도 존재하지 않을 때의 '구성 요소 서비스' 스냅인의 콘솔 트리 모습

그다지 특이한 점은 눈에 띄지 않는다. 그렇다면 이번에는 테스트를 위해서 가상 디렉터리를 하나 생성하고 이 가상 디렉터리에 응용 프로그램 보호 항목이 높음(격리됨)으로 설정된 IIS 웹 응용 프로그램을 설정해 보도록 하자. 먼저 C 드라이브에 isolation이라는 임시 폴더를 하나 생성하고 이 폴더를 사용하여 가상 디렉터리를 생성한다. 가상 디렉터리의 이름도 편의상 isolation이라고 하고 다음의 이미지와 같이 등록 정보에서 응용 프로그램 보호 항목을 높음(격리됨)으로 설정한다.

isolation 가상 디렉터리

이제 다시 구성 요소 서비스 스냅인으로 돌아가서 콘솔 트리의 모습을 살펴본다. COM+ 응용 프로그램 노드를 선택하고 F5 키를 누르거나, 마우스 오른쪽 버튼으로 COM+ 응용 프로그램 노드를 선택하여 팝업 메뉴를 띄우고 새로 고침 메뉴를 선택하면 화면이 다음과 같은 최신 정보로 갱신되는데, 방금전까지만 해도 존재하지 않던 'IIS-{기본 웹 사이트//Root/isolation}'이라는 이름의 새로운 COM+ 응용 프로그램이 새로 생성되어 있다는 것을 알 수 있을 것이다.

isolation 가상 디렉터리에 대한 COM+ 응용 프로그램이 생성된 '구성 요소 서비스' 스냅인의 콘솔 트리 모습

그런데 더 흥미로운 부분은 다음과 같이 'IIS-{기본 웹 사이트//Root/isolation}' 응용 프로그램에 등록되어 있는 IISWAM.1__Root__isolation 컴포넌트다. 이 컴포넌트 역시 WAM이며 오직 isolation 가상 디렉터리에 설정되어 있는 IIS 웹 응용 프로그램만을 위해서 준비된 것으로 그 본질은 다른 WAM 컴포넌트와 동일한 것이다. 등록 정보를 보면 다른 WAM 컴포넌트들처럼 C:\WINNT\system32\inetsrv\wam.dll 파일을 가리키고 있다는 점이 그 사실을 증명해준다.

IISWAM.1__Root__isolation 컴포넌트

결과적으로 응용 프로그램 보호 항목이 높음(격리됨)으로 설정된 IIS 웹 응용 프로그램의 ASP 프로그램이 클라이언트로부터 요청을 받으면 INETINFO.EXE 프로세스에 생성된 IISWAM.W3SVC 컴포넌트의 특정 IIS 웹 응용 프로그램을 위해서 준비된 IISWAM.1__Root__isolation 컴포넌트 같은 WAM 컴포넌트의 인스턴스를 생성한다. 그런데, 이 컴포넌트는 활성화 유형이 서버 응용 프로그램인 별도로 준비된 COM+ 응용 프로그램에 등록되어 있으므로 이 컴포넌트의 인스턴스를 호스팅하기 위한 DLLHOST.EXE 프로세스가 생성되고, 이 IIS 웹 응용 프로그램에 대한 모든 요청은 결국 이 DLLHOST.EXE 프로세스로 라우트된다. 그 다음에는 지금까지와 마찬가지로 ASP.DLL ISAPI 확장 프로그램이 동일한 DLLHOST.EXE 프로세스에 로드되고 클라이언트가 요청한 ASP 프로그램 파일이 읽어들여진 후 LANGUAGE 지시자나 메타베이스에 설정된 기본 스크립트 언어에 대응되는 스크립트 엔진이 로딩되어 처리가 되는 것으로 모든 과정이 마무리된다. 다음은 이 과정을 도식화한 이미지인데 기본적인 부분들은 응용 프로그램 보호 항목이 보통(풀링됨)으로 설정된 IIS 웹 응용 프로그램의 실행 과정을 정리한 도식과 거의 동일하다.

'응용 프로그램 보호' 항목이 '높음(격리됨)'으로 설정되어 있는 IIS 웹 응용 프로그램

이 도식에서도 알 수 있는 것처럼 IIS 웹 응용 프로그램이 처리되는 DLLHOST.EXE 프로세스가 풀링을 위해서 준비된 공용의 프로세스가 아닌 전용의 DLLHOST.EXE 프로세스라는, 즉 지금과 같은 경우에는 'IIS-{기본 웹 사이트//Root/isolation}' 응용 프로그램의 프로세스라는 점만 제외한다면 그 밖의 기본적인 처리 과정은 응용 프로그램 보호 항목이 보통(풀링됨)으로 설정된 이전의 IIS 웹 응용 프로그램이 처리되는 과정과 완벽하게 동일하다. 그러나, 이 격리 모델이 가지고 있는 보다 진정한 가치는 응용 프로그램 보호 항목이 높음(격리됨)으로 설정되어 있는 또 다른 IIS 웹 응용 프로그램에 대한 요청이 클라이언트로부터 발생할 때 비로소 드러나게 된다. 가령, 응용 프로그램 보호 항목이 높음(격리됨)으로 설정된 isolation2라는 또 하나의 가상 디렉터리가 존재한다고 생각해보자. 만약 클라이언트가 이 isolation2 가상 디렉터리에 포함된 ASP 응용 프로그램을 요청한다면 역시 이번에도 이 IIS 웹 응용 프로그램만을 위해 준비된 별도로 분리된 DLLHOST.EXE 프로세스가 시작되게 된다. 다음은 이 내용들을 도식화한 것이다.

'응용 프로그램 보호' 항목이 '높음(격리됨)'으로 설정되어 있는 IIS 웹 응용 프로그램

따라서, 만약 임의의 IIS 시스템에 응용 프로그램 보호 항목이 높음(격리됨)으로 설정된 IIS 웹 응용 프로그램이 모두 n개가 존재하고 있다면, DLLHOST.EXE 프로세스도 최소한 n + 2개 이상 생성될 수 있는 가능성이 존재하는 셈이다. 여기서 + 2는 풀링을 위해 준비된 IIS Out-Of-Process Pooled Applications 응용 프로그램과 거의 항상 실행중인 System Application 응용 프로그램을 위한 DLLHOST.EXE 프로세스를 의미한다. IIS가 운영되고 있는 시스템에서 작업 관리자로 살펴볼 수 있는 DLLHOST.EXE 프로세스의 거의 대부분이 지금까지 본문을 통해서 논의한 과정들을 거쳐서 생성된 것이라고 생각해도 큰 무리는 없을 것이다. 그리고, 응용 프로그램 보호 항목이 높음(격리됨)으로 설정되어 있는 IIS 웹 응용 프로그램의 ASP 프로그램에서 컴포넌트를 사용하는 경우의 실행 과정에 대해서는 어떠한 COM+ 응용 프로그램의 DLLHOST.EXE 프로세스가 생성되느냐 하는 점을 제외하고는 응용 프로그램 보호 항목이 보통(풀링됨)으로 설정된 IIS 웹 응용 프로그램의 경우와 완전히 동일하므로 별도로 설명하거나 하지는 않도록 하겠다.

COM+ 응용 프로그램과 IIS 웹 응용 프로그램 전반에 걸친 보안 문제

마지막으로 COM+ 응용 프로그램과 IIS 웹 응용 프로그램의 전반에 걸친 보안 관련 문제, 즉 구체적으로 말하자면 프로세스 ID에 관해서 알아보고 본문을 마무리 하도록 하겠다. 프로세스 ID와 관련된 기본적인 내용들이 잘 기억나지 않는 분들은 먼저 앞 부분을 다시 읽어보고 나서 이 부분을 읽어보시기 바란다. 그리고, 지금부터 다루고자 하는 논제들은 어떤 면에서 볼때 필자가 예전에 작성했던 이 문서에서 다루었던 내용들을 보다 심화한 것이라고 볼 수 있으므로 개인적으로 관심을 가지고 있는 분들은 이 문서를 먼저 참고해보는 것도 좋을 것이다. 그러면, 우선 응용 프로그램 보호 항목이 낮음(IIS 프로세스)으로 설정되어 있는 IIS 웹 응용 프로그램과 그에 대응하는 프로세스 ID 간의 보안 문제에 관해서 자세히 알아보도록 하자.

지금까지의 논의를 통해서 이미 잘 알고 있겠지만 응용 프로그램 보호 항목이 낮음(IIS 프로세스)으로 설정되어 있는 IIS 웹 응용 프로그램은 ASP 프로그램에서 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램에 등록된 컴포넌트를 사용하는 경우만을 제외하고는 클라이언트로부터 받은 요청을 처리하는 모든 과정이 INETINFO.EXE 프로세스의 내부에서 이루어진다. 그런데 INETINFO.EXE 프로세스의 프로세스 ID는 분명히 위에서 설명한대로 SYSTEM 이라는 Administrator 계정과 거의 동일한 권한을 갖고 있는 계정이다. 그렇다면 여기서 한 가지 의문점이 생기게 된다. 대부분의 ASP 프로그래머들이 알고 있듯이 IIS는 보안과 관련하여 인증 방법을 여러가지 방식으로 제어할 수 있는데, 예를 들어서 익명 엑세스를 허용하는 경우에는 미리 정의된 계정들 중의 하나인 IUSR_[MachineName] 계정을 사용해서 모든 리소스에 접근을 하게 된다. 그런데, 이 계정은 Guests 그룹에 속한 계정으로서 리소스에 접근하는데 있어서 많은 제약을 받게 되고, 그래서 ASP 프로그래머들은 문서를 업로드하는 경우와 같이 서버에 파일을 써야하는 경우라던가 관리자급의 계정으로만 접근이 가능한 중요한 데이터 리소스들을 조작하고자 할 때 사용할 수 있는 여러가지 기법들을 학습하게 되는 것이 일반적인 경우다.

바로 여기에 중대한 모순이 감춰져 있는데, 앞에서는 IIS의 프로세스인 INETINFO.EXE 프로세스가 거의 모든 권한을 가지고 있는 SYSTEM 계정으로 실행된다고 말하고 있으면서, ASP 프로그램 그 자체는 고작 Guests 그룹에 속해 있는 IUSR_[MachineName] 계정의 권한으로 모든 리소스에 접근을 하기 때문에 많은 제약 사항들이 존재한다고 다시 번복하여 말하고 있는 것이다. 그렇다면 전체 처리 과정중의 어디쯤에서 프로세스 ID가 변경되기라도 한다는 얘기일까? 쉽게 믿기 어렵겠지만 바로 그것이 진실이다. 이미 알고 있는 것처럼 INETINFO.EXE 프로세스는 SYSTEM 계정으로 실행되지만 INETINFO.EXE 프로세스가 로드하는 ISAPI 확장 프로그램의 인스턴스가 실행되는 쓰레드는 익명 엑세스가 허용되어 있는 경우 IUSR_[MachineName] 계정으로 동작한다. 다시 말해서, 특정 쓰레드만 프로세스 ID와 별개의 계정으로 실행되는 '가장'의 실제 사례인 것이다. 물론 지금의 경우는 익명 엑세스가 허용되어 있는 경우만을 설명한 것이고 윈도우즈 통합 인증 등 보안과 관련된 또 다른 설정이 되어 있는 경우라면 그 세부적인 처리는 약간 달라지게 되겠지만, 그런 경우에도 역시 '가장'이 발생한다는 점에는 변함이 없다. 다음은 지금까지 설명한 내용들을 도식화한 것이다.

'응용 프로그램 보호' 항목이 <strong>낮음(IIS 프로세스)</strong> 으로 설정되어 있는 IIS 웹 응용 프로그램과 가장

여기서도 드러나듯이 보안적인 측면에서도 이 모델은 결코 좋은 모델이 아니다. '검사되지 않은 버퍼'와 같은 보안상의 취약점으로 인하여 악의적인 사용자에게 제어권이 넘어가는 경우, 관리자와 동일한 권한을 가지고 있는 SYSTEM 계정으로 모든 작업이 처리되게 되므로 이러한 시나리오에서는 단지 시스템의 일부분만이 아니라 거의 모든 부분에 걸친 시스템 전반의 제어권이 넘어간다고 보는 편이 맞을 것이다. 그런데, 응용 프로그램 보호 항목이 보통(풀링됨)이나 높음(격리됨)으로 설정되어 있는 IIS 웹 응용 프로그램의 경우에는 그 전체적인 양상이 조금 달라진다. 이 두 가지 경우는 거의 동일한 처리 과정을 갖고 있으므로 함께 설명을 하도록 할 것이다. 이 경우에도 INETINFO.EXE 프로세스가 SYSTEM 계정으로 실행된다는 부분까지는 이전의 경우와 크게 다르지 않다. 그러나, 응용 프로그램 보호 항목이 보통(풀링됨)으로 설정된 IIS 웹 응용 프로그램을 호스팅하는 IIS Out-Of-Process Pooled Applications COM+ 응용 프로그램의 DLLHOST.EXE 프로세스가 실행되거나, 응용 프로그램 보호 항목이 높음(격리됨)으로 설정된 IIS 웹 응용 프로그램만을 위해 생성되는 COM+ 응용 프로그램의 DLLHOST.EXE 프로세스가 실행되면서 프로세스 ID가 전혀 다른 계정으로 변경된다. 어떤 면에서 생각해본다면 이것은 매우 당연한 결과일 수 있는데, 왜냐하면 이 두 가지 경우에 활성화되는 COM+ 응용 프로그램은 그 활성화 유형이 서버 응용 프로그램으로, INETINFO.EXE 프로세스와는 전혀 별개의 프로세스인 DLLHOST.EXE 프로세스로 실행될뿐만 아니라, 해당 COM+ 응용 프로그램의 등록 정보에 지정되어 있는 프로세스 ID, 즉 활성 탭의 다음 사용자 탭에 설정된 계정의 기본값이 전혀 별개의 계정이기 때문이다. 다음의 이미지에서도 알 수 있는 것처럼 그 계정은 바로 IWAM_[MachineName]이라는 계정이다.

IWAM_[MachineName] 계정으로 설정된 'IIS Out-Of-Process Pooled Applications' 응용 프로그램

대부분 이 계정에 대해서 한 번쯤은 들어본 적이 있을 것으로 생각한다. 기본적으로 시스템에 IIS를 설치하면 두 개의 계정이 자동으로 생성되는데, 그 중에 하나가 IUSR_[MachineName] 계정이고 다른 하나가 바로 지금 논의하고 있는 IWAM_[MachineName] 계정이다. 거의 대부분의 ASP 프로그래머들이 IUSR_[MachineName] 계정의 특징이나 그 역활에 관해서는 깊이 파악하고 있다고 생각한다. 그렇지만 의외로 IWAM_[MachineName] 계정에 관해서 정확하게 파악하고 있는 ASP 프로그래머들은 그리 많지 않은데, 이 계정은 Guests 그룹에 속한 계정으로 바로 지금과 같이 응용 프로그램 보호 항목이 보통(풀링됨)이나 높음(격리됨)으로 설정되어 있는 IIS 웹 응용 프로그램을 호스팅하는 COM+ 응용 프로그램의 프로세스 ID로 사용되는 계정이다. 특히 IWAM_[MachineName] 계정이 Guests 그룹에 속해 있다는 점은 굉장히 중요한 의미를 지니고 있다. 먼저 지금까지의 내용들을 정리한 다음의 도식을 보기 바란다.

'응용 프로그램 보호' 항목이 '보통(풀링됨)'이나 '높음(격리됨)'으로 설정되어 있는 IIS 웹 응용 프로그램과 가장

이 경우에도 역시 마지막 단계에서는 IUSR_[MachineName] 계정으로 '가장'이 발생하게 된다. 그러나, 응용 프로그램 보호 항목이 낮음(IIS 프로세스)으로 설정되어 있는 IIS 웹 응용 프로그램의 경우와는 달리 '검사되지 않은 버퍼'와 같은 보안상의 취약점으로 인해 악의적인 사용자에게 제어권이 넘어가게 되더라도 결과적으로 악의적인 사용자에게 허용되는 계정은 고작해야 Guests 그룹에 속해 있는 IWAM_[MachineName] 계정에 불과할 뿐이다. 이 계정으로는 시스템에 위협적인 작업을 실행하는 것이 거의 불가능하다고 말할 수 있으므로 보안적인 측면에서 얻게 되는 이점은 실로 엄청난 것이라고 말할 수 있다. 결국 문제의 핵심은 프로그래머가 개발한 사용자 코드가 로드되는 프로세스가 어떤 작업을 처리하는 프로세스인가 하는 점과 해당 프로세스의 프로세스 ID에 따른 보안 측면에서의 위험 수준이라고 말할 수 있을 것이다. 결론적으로 이러한 점들을 종합하여 판단해 본다면 응용 프로그램 보호 항목이 낮음(IIS 프로세스)으로 설정되어 있는 IIS 웹 응용 프로그램의 사용은 그다지 권장되지 않는다. 지금까지 살펴본 것처럼 사용자 코드가 SYSTEM 계정으로 실행되는 INETINFO.EXE 프로세스에 직접 로드되므로 보안상의 심각한 위험 요소가 될뿐만 아니라 프로그램에 문제가 발생하는 경우 웹 서비스 전체에 걸친 심각한 영향을 미치게 되기 때문이다. 앞으로는 IIS를 설정하면서 이러한 특징들을 반드시 명심하기 바란다.

재미있는 사실은 지금까지 논의한 COM+ 응용 프로그램과 프로세스 ID 간의 특성들을 잘 이용하기만 한다면 매우 유용하게 활용할 수도 있다는 점이다. 예를 들어서 여러분이 작성한 ASP 프로그램에서 시스템의 레지스트리에 저장된 일련의 값들을 읽어야만 하는 상황이라고 가정해보자. 물론, 이 값들을 실제로 읽게 되는 사용자는 윈도우즈 시스템에 등록된 사용자는 아니다. 그저 우리들이 흔히 주변에서 볼 수 있는 것처럼 별도의 데이터베이스에 정보가 저장되는 특정 사이트의 회원인 경우인데, 만약 이런 사용자들을 모두 윈도우즈 시스템에 등록하려고 한다면 그 라이센스 비용만도 엄청날 것이다. 아무튼 결과적으로 이런 경우에 개발자들은 한 가지 문제에 직면하게 된다. 즉, 모든 사용자들이 IUSR_[MachineName] 계정으로 시스템의 리소스에 접근하는 반면, 관리자에게만 허락되는 리소스인 레지스트리에 접근을 시도하는 경우 당연한 얘기지만 권한 오류가 발생한다는 점이다. 그러면 이 문제를 어떻게 해결해야 할까? 아까도 얘기한 것처럼 라이센스 비용과 관련된 문제로 인해서 모든 사용자들에게 윈도우즈 계정을 부여하는 것은 불가능하다. 아니 만약 가능하다고 가정한다고 하더라도 모든 사용자들에게 관리자 권한을 줄 수는 없는 노릇이다. 그렇다면 익명 엑세스에 사용되는 계정을 관리자급의 계정으로 변경하는 방법은 어떨까? 실제로 많은 개발자들이 편의를 핑계로 이렇게 작업하고 있다고 알고 있다. 그러나 이는 보안을 포기하는 결과나 마찮가지인 방법으로 절대 권장되지 않는다.

지금 필요로 하는 최적의 방법은 기본적인 리소스 접근에 대한 권한은 기존의 방식을 그대로 유지하면서도 정말 필요한 리소스만을, 정말로 필요한 시점에만 잠시 열고 작업이 끝나고 나면 다시 원래의 상태로 돌아올 수 있는 방법이다. 이런 방법은 위의 도식을 가만히 분석해보면 의외로 쉽게 찾을 수 있다. 가장 먼저 활성화 유형이 서버 응용 프로그램인 COM+ 응용 프로그램을 하나 생성한다. 그리고, 레지스트리에서 일련의 데이터들을 읽어오기 위한 컴포넌트를 비주얼 베이직과 같은 프로그래밍 언어를 사용해서 필요에 따라 개발하고 방금 생성한 COM+ 응용 프로그램에 등록한다. 만약, 비주얼 베이직과 같은 언어를 사용하여 컴포넌트를 개발하는 작업에 익숙하지 않아서 부담이 된다면 마이크로소프트에서 제공하는 윈도우즈 스크립트 컴포넌트 같은 기술을 사용하는 것도 좋은 대안이다 (Windows 스크립트 컴포넌트). 이 기술은 소개된 시점도 상당히 오래되었고 그 유용성이 뛰어남에도 불구하고 그다지 널리 알려지지 않은 마이크로소프트의 스크립트 기술들 중의 하나인데 스크립트에 관심을 가지고 계신 분들은 한 번쯤 주의 깊게 살펴볼만한 가치가 충분한 기술이다. 아무튼 이제 마지막으로 해당 COM+ 응용 프로그램의 등록 정보를 열고 확인 탭에서 다음 사용자 항목에 충분한 권한을 가진 사용자 계정을 등록하도록 한다. 일단 이 자리에서는 본문 진행상의 편의를 위해서 다음 사용자 항목에 Administrator 계정을 설정했다고 가정해보도록 하겠다. 다음은 지금까지 논의한 내용들을 도식으로 작성한 것이다.

COM+ 응용 프로그램, 가장, 그리고 프로세스 ID 의 응용

결과적으로 레지스트리에 접근하는 컴포넌트는 항상 Administrator 계정을 통해서 실행되고, 그 밖의 모든 일반적인 ASP 프로그램들은 여전히 IUSR_[MachineName] 계정을 사용해서 모든 리소스에 접근한다. 목표대로 정말 필요한 리소스만을, 정말로 필요한 시점에만 허용할 수 있게 된 것이다. 게다가 보너스격으로 COM+ 서비스로부터 제공되는 선언적 보안을 구현할 수 있는 선택의 여지가 주어질 뿐만 아니라, 원한다면 스스로 컴포넌트의 내부에서 프로젝트의 성격에 부합하는 자체적인 보안 코드를 구현하는 것도 얼마든지 가능하다.

ASP.NET 과 IIS 5.0 그리고 IIS 6.0

본문의 서두에서 밝힌 바와 같이 본문에서 설명한 내용들은 IIS 5.0과 ASP 프로그래밍 환경만을 그 대상으로 하고 있다. 가령, IIS 5.0에서 운영되는 ASP.NET 프로그램을 한 번 생각해보자. 과연 이와 같은 환경에서도 'DLLHOST.EXE 프로세스'라는 단어로 대변되는 IIS 웹 응용 프로그램과 COM+ 응용 프로그램간의 상호 관계가 그대로 유지되는 것일까? 이 질문에 대한 정답은 '아니오'다. 심지어 Keith Brown라는 테크니컬 라이터는 2001년 11월호 MSDN 매거진에서 'ASP .NET 응용 프로그램을 구축할 때에 IIS에서 응용 프로그램 보호 설정를 구성하는데 시간을 낭비하지 마십시오.'라고까지 말하고 있으며, 이 얘기는 당연히 논리적인 근거를 갖고 있다 (ASP.NET 보안 문제). 게다가 IIS 6.0의 기본 격리 모드인 작업자 프로세스 격리 모드에서는 지금까지 설명한 내용들이 무색할 정도로 근본적인 부분의 아키텍처까지 모두 바뀌었다. 사실 필자는 개인적으로 IIS 5.0에서 실행되는 ASP.NET의 작업자 프로세스는 IIS 6.0의 작업자 프로세스 격리 모드 형태로 점진적으로 이전하기 위한 중간 단계에 불과한 것이라고 생각하고 있다. 그리고, ASP.NET 자체도 IIS 5.0에서 실행될 때와 IIS 6.0에서 실행될 때의 내부 구성에 현격한 차이가 나기 때문에 IIS 6.0에서는 환경 설정 파일인 Machine.config 파일의 <processModel> 요소의 구성 설정 중에서 maxWorkerThreads를 비롯한 단 세 가지 항목만 제외하고는 모두 무시된다. 간단하게 말해서 최근의 상황은 IIS 기반의 개발자들에게는 반드시 습득해야만 할 기술들이 엄청나게 산적해 있는 상태다. 이런 상황에서 본문을 통해 얻고자 한 것은 먼저 현시점에서 가장 주류로 사용되고 있는 IIS 버전인 5.0의 내부 구조를 이해하고, 그에 더해서 ASP.NET과 IIS 6.0의 아키텍처를 이해할 수 있는 기반으로서 역활을 할 수 있게 되기를 바란 것이다. 본문에서 다루지 못한 ASP.NET과 IIS 6.0의 아키텍처에 관한 더 깊은 주제들에 대해서는 추후 필자의 지식이 지금보다 훨씬 무르익게 되면 따로 논의할 수 있는 기회를 마련하도록 하겠다.