EgoCube.IISWebAdmin 컴포넌트 01.

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

필자가 김태영님의 Taeyo's ASP & ASP.NET에 ADSI 관련 강좌를 연재했던 것이 어느새 만 2년이 다 되어간다. 많은 분들께 죄송스럽게도 개인적인 사정으로 인해서 강좌를 깔끔하게 마무리하지 못했었는데 항상 그 점이 마음 한 구석에 남아 있었다. 가끔 메일을 보내주시는 분들이 '다음 강좌는 언제 올라오나요?'하고 물어볼 때마다 항상 죄송스러운 마음을 금치 못했다.

그래서, 이번 기회에 당시 마무리하지 못했던 부분을 먼저 매듭짓고 다른 주제로 넘어가고자 한다. 이 글들은 Taeyo's ASP & ASP.NET에 연재되었던 강좌를 기준으로 LECTURE 메뉴 하위의 ASP 섹션의 ASP & ADSI 강좌들 중에서 ASP와 VB 컴포넌트를 이용한 IIS 관리 자동화 강좌 이후부터 다시 이어지는 글이라고 생각하면 무리가 없을 것이다.

기억이 가물거리는 분들을 위해서 이 글들의 목적을 다시 상기해보면 ASP 프로그래밍으로 IIS의 설정을 제어하는 것이다. 즉, ASP 프로그래밍을 통해서 로컬 콘솔(Local Console)에서 인터넷 서비스 관리자를 사용하는 것과 동일한 결과를 얻어내고자 하는 것이다. 그런 이유로 본문에서는 이해를 돕기 위해서 IIS를 사용하여 웹 호스팅을 구축하는 경우를 가정했고, 그 중에서도 WWW 서비스를 자동화하는 부분에 중점을 두고 있다.

물론, 실무에서 사용할 수 있을 정도로 진정한 의미로서의 웹 호스팅 자동화를 구현하기 위해서는, 비단 WWW 서비스뿐만 아니라 FTP 서비스, DNS 서비스, Windows 계정 관리 서비스 등의 기타 영역 또한 병행해서 자동화가 이루어져야 하는 것이 사실이다. 하지만 어디까지나 본문의 목적은 학습이므로 여타 다른 부분에 대해서는 일단 논외로 하기로 한다.

다음의 링크들은 Microsoft Visual Basic 6.0 SP5로 작성한 EgoCube.IISWebAdmin COM 컴포넌트의 소스 코드와 설치 파일이다.

IISWebAdmin_Src.zip (25k)
IISWebAdmin_Setup.zip (1,547k)

노트: EgoCube.IISWebAdmin 컴포넌트의 최신 버전은 1.2.0.60으로 여기에서 다운로드 받을 수 있다.

한 가지 유의해야 할 점은 EgoCube.IISWebAdmin 컴포넌트가 액티브 디렉터리(Active Directory)는 전혀 고려되지 않은 상태로 제작됐다는 점이다. 물론, 액티브 디렉터리가 구성된 Windows 2000 도메인에서는 사용이 불가능하다던가 한 것은 아니고, 다만 액티브 디렉터리에 최적화되지는 않았다는 점을 강조하려는 것이다. 같은 맥락에서 ADSI 제공자(ADSI Provider) 역시 'LDAP://' 제공자가 아닌 'WinNT://' 제공자가 사용되었다.

그 가장 큰 이유는 현재까지도 Windows NT Server 4.0 시스템을 운영하고 계시는 분들을 배려하기 위한 것이다. 더불어, 국내에서는 액티브 디렉터리를 활용해서 네트워크가 구축된 곳을 찾아보기가 매우 힘들고, 혹은 구축되었다고 할지라도 웹 서버까지 액티브 디렉터리에 묶인 경우를 필자로서는 본 적이 없기 때문인데, 업체들이 보유한 대부분의 웹 서버들 중 상당수가 IDC에서 호스팅되고 있다는 점을 고려해본다면, 그런 서버들이 모두 액티브 디렉터리하에서 운영되고 있다고 생각하기에는 무리가 있지 않을까 한다.

그러나, 이론적으로 EgoCube.IISWebAdmin 컴포넌트는 액티브 디렉터리 도메인상에서도 무리 없이 동작하므로 이 얘기는 그저 필자의 컴포넌트 제작 방침이 어떠하다는 사족일 뿐 그다지 신경쓸 문제는 아닌 것 같다.

다음의 표는 EgoCube.IISWebAdmin 컴포넌트에서 제공되는 모든 메서드들과 그 기능들을 간략하게 정리한 것이다. 모두 열 개의 Public 메서드와 한 개의 Private 메서드를 갖고 있으며 대부분의 메서드들은 Get과 Set의 한 쌍으로 구성된 이름을 갖고 있다. 이 중에서 Private 메서드인 GetLocalMachineName() 메서드는 현재 컴포넌트가 실행되고 있는 서버의 이름을 리턴하는 간단한 유틸리티 메서드이므로 이 메서드에 대한 자세한 설명은 생략하기로 한다.

Public 메서드

GetWebServerState() 지정한 가상 웹 서버의 현재 상태를 리턴한다.
SetWebServerState() 지정한 가상 웹 서버의 현재 상태를 설정한다.
GetWebServerDefaultDoc() 지정한 가상 웹 서버의 기본 문서 정보를 리턴한다.
SetWebServerDefaultDoc() 지정한 가상 웹 서버의 기본 문서 정보를 설정한다.
GetWebServerAccessPermit() 지정한 가상 웹 서버의 Access 권한 정보를 리턴한다.
SetWebServerAccessPermit() 지정한 가상 웹 서버의 Access 권한 정보를 설정한다.
GetLastWebServerIndex() 가장 큰 가상 웹 서버의 Index 값을 리턴한다.
GetWebServerBindings() 지정한 가상 웹 서버의 Binding 정보를 리턴한다.
CreateWebServer() 지정한 머신에 새로운 가상 웹 서버를 생성한다.
GetWebServerList() 지정한 머신에 존재하는 가상 웹 서버들의 정보 목록을 리턴한다.

Private 메서드

GetLocalMachineName() 로컬 머신의 NetBIOS 이름을 리턴한다.

먼저, EgoCube.IISWebAdmin 컴포넌트를 설치하도록 한다. 일단 위의 링크에서 다운로드 받은 설치 프로그램을 사용하여 설치한다. 그러나, 이 설치 프로그램으로 설치를 하다보면 간혹 오류가 발생하면서 설치가 제대로 되지 않는 경우가 있는데, 이는 필자가 Microsoft Visual Basic 6.0에 포함된 패키지 및 배포 마법사로 만든 설치 프로그램이 그리 충실하지 못한 탓으로, 그런 경우에는 설치 프로그램에 포함된 IISWebAdmin.CAB 파일의 압축을 풀어서 RegSvr32.exe 유틸리티를 사용해서 IISWebAdmin.dll을 직접 등록해도 무방하다.

이때, 반드시 %SystemRoot%\System32 폴더에 VB6KO.DLL 파일이 존재하는지 확인하도록 한다. 이 파일이 없으면 컴포넌트가 정상적으로 동작하지 않는다. VB6KO.DLL 파일도 IISWebAdmin.CAB 파일 안에 포함되어 있다. VB6KO.DLL 파일은 COM DLL이 아니므로 레지스트리에 등록할 필요가 없으며 단순히 복사하기만 하면 된다. 만약, 이 방법도 여의치가 않고 PC에 Microsoft Visual Basic 6.0이 설치되어 있다면, 단순하게 컴파일을 한 번 하는 것도 또 다른 방법이다.

그리고, IISWebAdmin.dll이 설치될 머신의 운영 체제가 Windows 2000 제품군이 아니라면, 다음 페이지에서 해당 머신의 운영 체제와 그 버전에 맞는 ADSI 2.5를 다운로드 받아서 설치해야 한다. 비록 한글 버전이 제공되고 있지는 않지만 영문 버전을 설치해도 무방하다.

Active Directory Services Interfaces 2.5 : [Microsoft Windows NT Server 4.0; ADSI 2.5.] (영문)

일단 컴포넌트의 설치가 끝나고 나면 다음과 같이 ASP 프로그램상에서 EgoCube.IISWebAdmin 컴포넌트의 객체를 생성할 수 있다. 이 코드에서는 주석문 처리의 결과로 단지 컴포넌트의 인스턴스를 생성만 할 뿐, 실제로는 어떠한 작업도 실행되지 않고 있다는 점에 유의하기 바란다. 브라우저로 이 ASP 프로그램을 실행시켜보면 어떠한 오류도 발생하지 않고, 아무런 작업도 진행하고 있지 않으므로 그저 하얀 공백 화면만이 출력될 것이다.

<%
    
Dim oIISAdmin
    
Set oIISAdmin = Server.CreateObject("EgoCube.IISWebAdmin")
'** Response.Write "<font size=2>Debug :: " & oIISAdmin.GetWebServerState(1) & "</font><br>"
Set oIISAdmin = Nothing
    
%>

이제 다음과 같이 GetWebServerState() 메서드를 사용하는 줄의 주석을 제거한 후, 브라우저에서 F5 키를 눌러서 페이지를 갱신해보기 바란다.

<%
    
Dim oIISAdmin
    
Set oIISAdmin = Server.CreateObject("EgoCube.IISWebAdmin")
Response.Write "<font size=2>Debug :: " & oIISAdmin.GetWebServerState(1) & "</font><br>"
Set oIISAdmin = Nothing
    
%>

그러면, 아마도 다음 그림과 같이 'EgoCube (0x800A0046) 사용 권한이 없습니다.'라는 오류가 발생하면서 정상적으로 동작하지 않을 것이다. 이 오류는 IUSR_[MachineName] 계정의 권한과 메타베이스에 관련된 문제 때문에 발생하는데, 기존에 Taeyo's ASP & ASP.NET 사이트에 연재한 강좌에서도 이 문제에 관해 언급한 바 있다. 간단하게 말해서 관리자 그룹에 속한 계정으로만 접근이 가능한 IIS의 메타베이스를 IUSR_[MachineName] 계정으로 접근하려고 하기 때문에 발생하는 오류인 것이다.

'EgoCube (0x800A0046) 사용 권한이 없습니다.' 오류 화면

이 오류를 해결할 수 있는 가장 간단하면서도 명확한 방법은 COM+의 역할 기반 보안 기능을 활용하는 것이다. 그 방법에 관해서는 ASP와 VB 컴포넌트를 이용한 IIS 관리 자동화 강좌에서도 이미 한 번 설명했고, 최근에 작성한 COM+의 역할 기반 보안(Role-Based Security)과 ASP에서 컴포넌트 사용하기 강좌에서도 다시 한 번 자세하게 논의했으므로 해당 문서들을 참고하기 바란다.

만약, EgoCube.IISWebAdmin 컴포넌트를 ASP 프로그램이 아닌, Microsoft Visual Basic 6.0 등으로 제작한 Windows 응용 프로그램에서 사용하는 경우라면 이런 후속 조치는 필요 없을 것이다. 그런 경우에는 현재 로그인한 사용자의 권한에 응용 프로그램의 권한이 종속되기 때문이다. 물론 원한다면 Windows 응용 프로그램상에서도 COM+의 역할 기반 보안 기능을 사용할 수 있다.

위의 문서들을 참고로 COM+의 역할 기반 보안을 올바르게 설정했다면 반드시 서비스 관리 도구에서 IIS Admin 서비스를 중지시킨 후 다시 재시작해서, IIS Admin 서비스와 그 종속 서비스들을 초기화시켜야한다. 그 이유는 일단 IIS Admin 서비스 상에 로드된 컴포넌트의 객체는 서비스를 재시작하거나 운영 체제 자체를 재시작하기 전까지 인스턴스가 IIS Admin 서비스의 메모리에 그대로 남아있기 때문이다.

GetWebServerList() 메서드

먼저 GetWebServerList() 메서드의 사용법부터 살펴보자. GetWebServerList() 메서드는 프로그래머가 인자를 통해서 지정한 IIS가 설치된 서버에 존재하는 모든 가상 웹 서버들의 기본적인 정보를 RecordSet 형식의 객체로 리턴해주는데 그 시그니처(Signature)는 다음과 같다.

Public Function GetWebServerList(Optional WebServerName As String = "") As ADODB.RecordSet

이 때, WebServerName 인자는 가상 웹 서버들의 정보를 얻고자 하는, IIS가 설치된 서버의 NetBIOS 이름으로, 이 인자를 생략하는 경우에는 내부적으로 현재 컴포넌트가 실행되고 있는 서버의 이름이 사용된다. ASP 프로그램에서 사용하는 방법은 다음 코드와 같다. 여기에서는 캡춰 화면을 고려해서 일부 Field들만 출력하도록 프로그래밍했다. 메서드 실행의 결과로 리턴되는 RecordSet 객체의 모든 Field들의 이름과 데이터 타입 등의 정보는 코드의 상단 주석부에 나와 있으므로 별도의 설명은 생략한다.

<%

  '******************************************************
  '*
  '* 리턴되는 RecordSet 의 모든 Field 들의 이름과 데이터 타입
  '*
  '*    Index      :: adInteger :: 가상 웹 서버의 인덱스
  '*    Name       :: adVarChar :: 가상 웹 서버의 이름
  '*    ADsPath    :: adVarChar :: 가상 웹 서버의 ADsPath
  '*    State      :: adInteger :: 가상 웹 서버의 현재 상태
  '*                  1 - 시작 중, 2 - 시작됨, 3 - 정지 중, 4 - 정지됨
  '*                  5 - 일시 정지 중, 6 - 일시 정지됨, 7 - 계속
  '*    DefaultDoc :: adVarChar :: ',' 로 구분된 가상 웹 서버의 기본 문서 목록
  '*    Path       :: adVarChar :: 가상 웹 서버 Root 의 물리적인 경로
  '*    AccRead    :: adBoolean :: 가상 웹 서버 Root 의 읽기 권한
  '*    AccWrite   :: adBoolean :: 가상 웹 서버 Root 의 쓰기 권한
  '*    AccScript  :: adBoolean :: 가상 웹 서버 Root 의 스크립트 실행 권한
  '*    AccExecute :: adBoolean :: 가상 웹 서버 Root 의 실행 권한
  '*
  '******************************************************

  Dim oIISAdmin
  Dim oRec
  Dim sHTML

  Set oIISAdmin = Server.CreateObject("EgoCube.IISWebAdmin")
  
  '** Set oRec = oIISAdmin.GetWebServerList("[머신이름]") 과 같이 사용할 수도 있다.
  Set oRec = oIISAdmin.GetWebServerList()

  '** 가상 웹 서버의 정보를 HTML 문자열로 생성
  Do Until oRec.EOF
      sHTML = sHTML & "<tr bgcolor=""#FFFFFF"">" & _
              "<td><font size=""2"">&nbsp;" & oRec("Index") & "&nbsp;</font></td>" & _
              "<td><font size=""2"">&nbsp;" & oRec("Name") & "&nbsp;</font></td>" & _
              "<td><font size=""2"">&nbsp;" & oRec("ADsPath") & "&nbsp;</font></td>" & _
              "<td><font size=""2"">&nbsp;" & oRec("State") & "&nbsp;</font></td>" & _
              "<td><font size=""2"">&nbsp;" & oRec("DefaultDoc") & "&nbsp;</font></td>" & _
              "<td><font size=""2"">&nbsp;" & oRec("Path") & "&nbsp;</font></td>" & _
              "</tr>"
      oRec.MoveNext
  Loop

  '** 반드시 RecordSet 객체를 Nothing 해준다.
  Set oRec = Nothing
  Set oIISAdmin = Nothing

%>

  <table border="0" cellpadding="3" cellspacing="1" bgcolor="#555555">
  <tr bgcolor="#AAAAAA">
      <td><font size="2">&nbsp;Index&nbsp;</font></td>
      <td><font size="2">&nbsp;Name&nbsp;</font></td>
      <td><font size="2">&nbsp;ADsPath&nbsp;</font></td>
      <td><font size="2">&nbsp;State&nbsp;</font></td>
      <td><font size="2">&nbsp;DefaultDoc&nbsp;</font></td>
      <td><font size="2">&nbsp;Path&nbsp;</font></td>
  </tr>
  <%= sHTML %>
  </table>

이미 설명했던 것처럼 GetWebServerList() 메서드는 실행 결과를 RecordSet 객체로 리턴하는데, 이 RecordSet 객체는 일반적인 데이타베이스 쿼리 집합으로서의 RecordSet이 아니고 직접 구성한 Custom RecordSet의 각각의 Row에 수작업으로 값을 입력한 후 Disconnected RecordSet으로 설정해서 리턴한 것이다. 따라서, 객체의 사용이 끝나고 나면 반드시 Nothing을 설정해서 참조를 해제시켜주어야 한다. 이런 방식의 RecordSet 사용법은 마치 ADO.NET의 DataSet을 연상시키는 면이 있는데, 사실 두 기술 간에 어느 정도의 연관성은 있다고 봐야 할 것 같다.

다음 그림은 위의 ASP 코드를 필자의 PC 상에서 브라우저로 실행시키고 그 결과를 캡춰한 화면이다. 이미지가 흐릿해서 정확한 내용을 알아 볼 수는 없지만 모두 두 개의 가상 웹 서버 정보가 출력된 것을 확인할 수 있다. 필자의 머신에는 '기본 웹 사이트'와 '관리 웹 사이트'만 설치되어 있는 상태이므로 이 결과 화면이 올바르게 출력되었다는 것을 알 수 있다.

샘플 코드의 실행 결과

그리고, 다소 번거로울 수는 있겠지만 GetWebServerList() 메서드를 비롯한 EgoCube.IISWebAdmin 컴포넌트의 모든 메서드들을 작성하면서 인자들의 데이터 타입을 간단히 Variant로 설정하는 대신 String이나 Integer 등으로 데이터 타입을 명확하게 선언했기 때문에 다음과 같은 ASP 코드는 오류를 발생시킨다.

<%

  ...
  
  Dim sServerName
  sServerName = "MyServerName"
  
  '** 이 줄에서 오류가 발생한다.
  Set oRec = oIISAdmin.GetWebServerList(sServerName)

  ...
  
%>

이 오류는 String 타입의 변수를 인자로 받는 GetWebServerList() 메서드에 Variant 타입의 변수를 대입했기 때문에 발생하는 것이므로, 오류를 방지하기 위해서는 다음과 같은 두 가지 방법 중 한 가지 방법을 선택해서 코드를 변경해야만 한다.

<%

  ...
  
  Dim sServerName
  sServerName = "MyServerName"
  
  '** 방법 1. 정확하게 형 변환을 해준다.
  Set oRec = oIISAdmin.GetWebServerList(CStr(sServerName))
  oRec.Close

  '** 방법 2. 인자의 데이터 타입과 일치하는 값을 직접 입력한다.
  Set oRec = oIISAdmin.GetWebServerList("MyServerName")

  ...
  
%>

이는 순전히 필자의 코딩 취향에 따른 것으로 특별히 별다른 이유가 있어서 이런 스타일의 코드를 작성한 것은 아니다. 다만 ASP뿐만 아니라 Microsoft Visual Basic 6.0도 염두에 두고 코딩을 하다보니 이렇게 된 것일뿐, 불편을 느끼는 분이 계시다면 각자의 편의대로 컴포넌트의 코드를 수정하여 사용해도 무방하다.

본문을 읽으면서 혹시 .NET에서는 ADSI라든가 IIS의 메타베이스에 관한 기술들의 중요성이 상대적으로 떨어지게 되는 것은 아닐까 염려하는 분들이 계시다면 필자는 그렇지 않다라고 말씀드리고 싶다. 왜냐하면 가령 Windows.NET Server의 경우에는 어떻게 변할지 모르겠지만 현재 XP를 포함해서 Windows 2000을 기본으로 하는 운영 체제에서는 메타베이스를 통하지 않고서는 가상 웹 서버를 설정할 수 있는 방법 자체가 전무하다. 단적으로 말해서 ASP.NET의 web.config만으로는 이미 정의된 가상 웹 서버의 속성 등을 설정할 수 있을 뿐 새로운 가상 웹 서버 그 자체나 가상 디렉터리를 생성하지는 못한다. 필자의 판단으로는 이런 부분들은 COM+ 등과 깊은 연관성을 가지고 있고 따라서 운영 체제 전반에 걸쳐 영향을 미치는 부분이므로 단시일 내에 파격적인 변화가 일어나기는 힘들 것이다.

그뿐만 아니라 단순하게 ADSI의 경우만을 놓고 본다면 System.DirectoryServices 네임스페이스를 통해서 새롭게 DirectoryEntrie 클래스나 DirectoryEntries 클래스, 또는 DirectorySearcher 클래스 등이 지원되므로 오히려 Visual Basic Script나 Microsoft Visual Basic 6.0에서 갖고 있던 제약을 극복할 수 있는 환경으로 발전했다고도 말할 수 있을 것이다. 이 주제에 관해서는 EgoCube.IISWebAdmin 컴포넌트에 관한 글들을 마져 마무리 짓고나서 따로 글을 마련할 생각이다. 다음글에서는 나머지 메서드들에 관한 이야기를 진행해 나가도록 하겠다.