.NET 프레임워크로 IIS 7 모듈 및 헨들러 개발하기

등록일시: 2009-03-30 11:33,  수정일시: 2013-11-29 16:08
조회수: 10,862
이 문서는 IIS 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.

개요

본문에서는 .NET 프레임워크로 IIS 7 웹 서버의 기능을 개발하는 방법을 소개합니다. 다음과 같은 내용들을 살펴보려고 합니다:

  1. IIS 7 모듈을 개발할지 아니면 IIS 7 헨들러를 개발할지를 결정하는 방법.
  2. 비주얼 스튜디오나 비주얼 C# 익스프레스, 또는 .NET 프레임워크 명령 프롬프트 도구를 사용해서 개발환경을 구성하는 방법.
  3. 첫 번째 프로젝트를 생성하는 방법.
  4. 간단한 모듈 및 헨들러를 개발하는 방법.
  5. 간단한 모듈 및 헨들러를 IIS 7 서버에 배포하는 방법.

그리고, 필자의 블로그(http://www.mvolo.com/)에서 IIS 7 모듈 개발에 대한 다양한 자료와 팁을 살펴보거나, 응용 프로그램에 적용할 수 있는 여러 가지 IIS 7 모듈들을 다운로드 받을 수 있습니다. 가령, HttpRedirection 모듈을 사용해서 응용 프로그램에 대한 요청 리디렉션하기, DirectoryListingModule 모듈을 사용해서 세련된 IIS 웹 사이트 디렉터리 목록 출력하기, IconHandler를 사용해서 세련된 ASP.NET 응용 프로그램 파일 아이콘 출력하기, 그리고 IIS 와 ASP.NET을 사용해서 핫-링크 막기 등을 살펴보시기 바랍니다.

본문에서 설명하는 모듈과 헨들러의 소스 코드 프로젝트는 여기에서 다운로드 받으실 수 있습니다.

서론: ASP.NET을 이용한 IIS 7 기능 개발

지금까지 IIS 7 이전 버전의 IIS에서는 일반적으로 ISAPI라고 알려진 C API를 웹 서버 기능을 구현하기 위한 핵심적인 확장 API로 사용했습니다. 반면, IIS 7에서는 철저히 재설계되었으며 이미 제품의 모든 초기 기능들의 기반으로 사용된, 웹 서버의 모든 런타임 확장 기능을 구현할 수 있는 새로운 C++ API가 제공됩니다.

더군다나 IIS 7에서는 새로운 C++ API와 정확하게 동일한 기능을 제공해주고 ASP.NET 2.0과 긴밀하게 통합되어 웹 서버 확장 기능을 개발할 수 있게 지원해주는 .NET API가 최초로 제공됩니다. 결국, 이 얘기는 친숙한 ASP.NET 2.0 API로 새로운 웹 서버 기능을 개발해서 IIS 7을 확장할 수 있다는 뜻입니다. 뿐만 아니라, 기존에 만들어 놨던 ASP.NET 2.0 모듈이나 헨들러를 IIS 7에서도 그대로 사용할 수 있으며, 새로운 코드를 작성하지 않고서도 ASP.NET 통합 기능을 이용해서 응용 프로그램의 성능을 향상시킬 수 있습니다. IIS 7의 ASP.NET 통합에 대한 더 자세한 내용은 이 기사를 참고하시기 바랍니다.

작업도구: 개발환경 결정하기

기본적으로 IIS 7 기반의 모듈이나 헨들러를 개발하려면 .NET 어셈블리를 작성하고 컴파일 할 수 있는 개발환경이 필요합니다. 보통 다음과 같은 개발환경이 필요합니다:

  1. 비주얼 스튜디오 2005나 다운로드 받은 비주얼 스튜디오 2008의 최신 베타 버전
  2. 비주얼 C# 2005 익스프레스 에디션의 무료 다운로드 버전 (또는, 비주얼 스튜디오 2005 익스프레스를 포함한 다른 익스프레스 도구들)
  3. .NET 프레임워크 런타임에 포함된 C# 명령 프롬프트 컴파일러(csc.exe), 그리고 각자 친숙한 텍스트 편집기 (SDK를 다운로드 받아야 합니다.)

본문에서 살펴볼 샘플 코드는 C#으로 작성됐지만 그 밖의 다른 .NET 언어로도 IIS 7 확장 컴포넌트를 작성할 수 있습니다. (관리되는 C++은 해당되지 않습니다.) 본문에서는 이 일반적인 세 가지 환경에서 IIS 7 확장 컴포넌트를 개발하는 방법을 살펴봅니다.

노트: IIS 7은 기존의 ASP.NET API로 사용해서 .NET 확장을 개발하기 때문에 윈도우 XP나 윈도우 서버 2003에서도 .NET 프레임워크 2.0으로 IIS 7 .NET 모듈이나 헨들러를 개발할 수는 있습니다. 그러나, IIS 7의 기능들을 지원하기 위한 목적으로 추가된 몇 가지 새로운 ASP.NET API들 중 한 가지를 사용하려면, 윈도우 비스타에서 개발하거나, 윈도우 비스타 및 최신 버전의 .NET 프레임워크 3.5에 포함된 System.Web.dll을 사용해야만 코드를 컴파일 할 수 있습니다. 더 자세한 내용은 이 문서를 참고하시기 바랍니다.

IIS 7 확장을 위한 두 가지 방법: 모듈 vs. 헨들러

본질적으로 IIS 7의 모든 웹 서버 기능들은 모듈과 헨들러라는 두 가지 범주 중 한 가지에 포함됩니다.

모듈은 이전 버전의 IIS에서 ISAPI 필터가 수행하던 작업과 비슷하게 모든 요청의 처리 과정에 개입해서 여러 가지 다양한 방법으로 그 동작을 변경하거나 처리를 추가합니다. 예를 들어서, IIS 7에서 제공하는 기본 모듈 중에서 인증 모듈은 요청의 인증 상태를 제어하고, 압축 모듈은 출력 응답을 압축하며, 로깅 모듈은 요청에 대한 정보를 요청 로그에 기록합니다.

더 구체적인 관점에서 살펴보자면 모듈은 ASP.NET의 System.Web.IHttpModule 인터페이스를 구현한 .NET 클래스라고 정의내릴 수 있으며, System.Web 네임스페이스에서 제공하는 API를 이용해서 하나 이상의 ASP.NET 요청 처리 단계에 관여할 수 있습니다.

반면 헨들러는 이전 버전의 IIS에서 ISAPI 확장이 수행하던 작업과 비슷하게 특정 콘텐츠 유형에 대한 요청 처리를 담당하고 그 응답을 생성합니다. 기본적으로 헨들러가 모듈과 구분되는 가장 큰 차이점은 특정 요청 경로 및 확장자와 맵핑되며, 해당 경로나 확장자에 대응하는 특정 서버 리소스에 대한 처리만 지원한다는 점입니다. 가령, IIS 7에서 제공하는 기본 헨들러들 중 ASP 헨들러는 ASP 스크립트를 처리하고, 정적 파일 헨들러는 정적 파일 요청에 대한 응답을 담당하며, ASP.NET 페이지 헨들러는 ASPX 파일들에 대한 요청을 처리합니다.

마찮가지로 구체적인 관점에서 살펴본다면 헨들러는 ASP.NET의 System.Web.IHttpHandler 인터페이스나 System.Web.IAsyncHttpHandler 인터페이스를 구현하는 .NET 클래스로 정의내릴 수 있으며, System.Web 네임스페이스에서 제공하는 API를 사용해서 해당 헨들러가 지원하는 특정 콘텐츠에 대한 HTTP 응답을 생성합니다. *

결론적으로 IIS 7의 기능을 개발하고자 할 때 가장 먼저 생각해봐야 할 점은, 바로 해당 기능이 특정 URL이나 확장자에 대한 요청만 전담해서 처리하면 되는지, 아니면 임의의 규칙을 근거로 전체나 일부 요청에 적용되야 하는지 입니다. 만약, 전자의 경우라면 헨들러를 선택하는 것이 적합할 것이고, 후자라면 모듈이 정답일 것입니다.

본문에서는 간단한 모듈과 헨들러를 작성하는 방법을 모두 살펴볼 것입니다. 프로젝트를 생성하거나 컴파일하는 단계는 모듈과 헨들러 모두 동일하지만 결과물을 서버에 배포하는 단계는 서로 다릅니다.

노트: 만약, 모듈을 개발하고자 한다고 해서 반드시 헨들러까지 개발해야 한다는 뜻은 아닙니다. 그 반대도 역시 마찮가지 입니다.

* 여기서 "System.Web.IAsyncHttpHandler 인터페이스"는 "System.Web.IHttpAsyncHandler 인터페이스"를 원문 저자의 오타인 것으로 보입니다.

시작하기: 비주얼 스튜디오 프로젝트 생성

모듈이나 헨들러를 작성하려면 모듈 및 헨들러 클래스를 포함하는 .NET 어셈블리(DLL)을 만들어야 합니다. 비주얼 스튜디오나 비주얼 스튜디오 익스프레스 도구를 사용하고 있다면 가장 먼저 할 일은 클래스 라이브러리 프로젝트를 생성하는 것입니다. (만약, 그 밖의 텍스트 편집기와 명령 프롬프트 컴파일러를 사용하고 있다면 비주얼 스튜디오 없이 프로젝트를 컴파일하는 방법에 관해 설명하고 있는 본문의 모듈 및 헨들러 컴파일하기 섹션을 참고하시기 바랍니다:

  1. 먼저, "파일" 메뉴에서 "새로 만들기", "프로젝트…" 메뉴를 순서대로 선택하고, 새 프로젝트 대화 상자에서 "Visual C#" 프로젝트 형식을 선택한 다음, 우측의 비주얼 스튜디오에 설치되어 있는 템플릿 목록에서 "클래스 라이브러리"를 선택합니다.
  2. 그런 다음 IIS 7 모듈과 헨들러를 개발에 반드시 필요한 API를 제공하는 "System.Web.dll" 어셈블리를 참조합니다. 솔루션 탐색기에서 프로젝트 노드 하위의 "참조" 노드를 마우스 오른쪽 버튼으로 클릭하고, "참조 추가…" 메뉴를 선택한 다음, 다음과 같이 .NET 탭에서 2.0 버전의 System.Web 어셈블리를 선택합니다.

노트: 만약, IIS 7에 특화된 ASP.NET API의 기능을 사용할 계획이 없다면, 윈도우 XP나 윈도우 서버 2003에서도 System.Web 어셈블리 버전 2.0을 사용할 수 있습니다. 이 버전의 어셈블리를 사용해서 컴파일된 모듈이나 헨들러도 아무런 문제 없이 윈도우 비스타나 윈도우 서버 2008의 IIS 7에 배포할 수 있고 정상적으로 동작도 합니다. 반면, 모듈이나 헨들러에서 IIS 7에 특화된 ASP.NET API 기능들을 사용하고자 한다면, 반드시 윈도우 비스타나 윈도우 서버 2008에서 개발하거나, .NET Framework 3.5에 포함된 System.Web.dll 어셈블리를 사용해서 개발해야 합니다. 이처럼 IIS 7에 특화된 API에는 HttpServerUtility.TransferRequest, HttpResponse.Headers 컬렉션, HttpApplication.LogRequest 이벤트 등이 있습니다.

코드작성: 간단한 모듈 개발하기

먼저 간단한 모듈을 작성해보도록 하겠습니다. 본문의 뒷 부분에서는 간단한 헨들러도 작성해 볼 텐데, 헨들러 작성 방법을 먼저 살펴보고 싶다면 간단한 헨들러 작성하기 섹션을 참고하십시오.

모듈을 작성하려면 System.Web.IHttpModule 인터페이스를 구현하는 클래스를 정의해야 합니다.

  1. 먼저, 프로젝트에서 자동 생성된 "class1.cs" 파일을 삭제하고, 솔루션 탬색기에서 MyIIS7Project 프로젝트를 마우스 오른쪽 버튼으로 클릭해서 "추가", 새 항목…" 메뉴를 선택한 다음, "클래스"를 선택하고 이름란에 "MyModule.cs"를 입력해서 MyModule이라는 이름으로 C# 클래스를 추가합니다.
  2. 개발상의 편의를 위해 System.Web 네임스페이스를 임포트해서 이 네임스페이스에 포함된 형식들에 대한 접근을 용이하게 합니다.
  3. 그리고, MyModule 클래스가 IHttpModule 인터페이스를 구현하도록 지정하고 IHttpModule 인터페이스 멤버인 Dispose() 와 Init() 메서드를 정의합니다. 이 때, IHttpModule 인터페이스를 마우스 오른쪽 버튼으로 클릭하고 "인터페이스 구현" 옵션을 선택해서 이 처리를 신속하게 수행할 수 있습니다:

    인터페이스의 멤버 메서드 중 Dispose() 메서드는 모듈이 언로드되는 시점에 해당 모듈에서 사용한 관리되지 않는 리소스들을 정리하기 위한 목적으로 사용되며, 결과적으로 이 메소드를 호출하면 가비지 컬렉터에 의해 모듈의 인스턴스가 파이널라이즈 되기 이전에도 리소스 해제가 가능합니다. 그러나, 모듈에서 관리되지 않는 리소스를 사용하지 않으면 대부분의 경우 이 메서드는 구현할 필요가 없습니다.

    그리고, Init(HttpApplication context) 메서드가 작업의 핵심입니다. 이 메서드는 모듈을 초기화하고 HttpApplication 클래스가 제공하는 하나 이상의 요청 처리 이벤트들을 모듈과 연결합니다. 그러면, 요청이 처리되는 각각의 단계에서 이 메서드에 기술된 해당 이벤트들에 연결된 메소드가 호출되어 실행됨으로서 서비스를 수행하게 됩니다. 이를 구현하려면:
  4. 모듈 클래스에 존재하는 임의의 메서드를 HttpApplication 인스턴스에서 제공해주는 이벤트들 중 한 이벤트와 연결해서 하나 이상의 요청 처리 이벤트를 기술합니다. 연결에 사용되는 모듈의 메서드는 반드시 System.EventHandler 델리게이트 시그니쳐의 형태여야만 합니다. OnPreExecuteRequestHandler라는 이름으로 새로운 메서드를 정의하고, 이 메서드를 서버가 특정 요청에 대한 요청 헨들러를 호출하기 직전에 발생하는 HttpApplication.PreRequestRequestHandlerExecute 이벤트와 연결합니다:
    public void Init(HttpApplication context) 
    { 
        context.PreRequestHandlerExecute += 
            newEventHandler(OnPreRequestHandlerExecute) 
    }

    결과적으로 모듈은 매번 요청이 발생할 때마다 PreRequestHandlerExecute 이벤트를 수신하게 됩니다. 이와 동일한 요령으로 수신하고자 하는 이벤트에 대해서 반복해서 이벤트 핸들러를 등록할 수 있습니다.
  5. 이제 모듈에서 뭔가 의미있는 작업을 처리하도록 모듈에서 사용 가능한 ASP.NET API를 활용해서 간단한 기능을 구현해보겠습니다. 즉, 요청의 리퍼러 헤더를 검사하고 만약 이 헤더에 값이 존재하면 요청을 거부하는데, 이 방법은 다른 웹 사이트에서 웹 사이트를 직접 링크하는 것을 방지하는 가장 단순하고도 과격한 방법입니다. 모든 요청에 대해 헨들러가 실행되기 직전에 호출되는 OnPreRequestHandlerExecute 메서드에서 이 작업을 수행하는 것이 적당할 것입니다: *
    public void OnPreRequestHandlerExecute(Object source, EventArgs e) 
    { 
        HttpApplication app = (HttpApplication)source; 
        HttpRequest     request = app.Context.Request; 
        
        if (!String.IsNullOrEmpty( request.Headers["Referer"] )) 
        { 
            throw new HttpException(403, "Uh-uh!"); 
        } 
    }

    노트: HttpApplication 인스턴스는 source 인자를 통해서 모듈에 전달되며 정상적으로 사용하기 위해서는 캐스팅이 필요합니다. 이 HttpApplication 인스턴스를 사용해서 HttpContext 개체나 요청에 대한 내용을 담고 있는 그 내부의 HttpRequest 개체를 비롯한 요청 개체 모델의 나머지 영역에 접근이 가능합니다.

    이 코드는 리퍼러 헤더를 검사하고, 만약 그 값이 지정되었다면 403 권한 없음 오류 코드와 함께 해당 요청을 거부합니다.

* 이는 말 그대로 샘플 코드에 불과합니다. 실제로 업무에 사용할 모듈을 이런 식으로 구현한다면 그야말로 무책임한 일일 것입니다.

코드작성: 간단한 헨들러 개발하기

이번에는 간단한 헨들러를 작성해보겠습니다. 이미 모듈을 작성하는 방법에 대해서는 살펴봤으므로, 만약 모듈 작성 방법에 대해 살펴보고 싶으시다면 참고하시기 바랍니다.

기본적으로 헨들러를 작성하려면 System.Web.IHttpHandler 인터페이스를 구현하는 클래스를 정의해야 합니다. (헨들러가 비동기적으로 실행돼야 한다면 System.Web.IHttpAsyncHandler 인터페이스를 구현합니다.) 이를 구현하려면:

  1. 만약, 프로젝트에 자동으로 생성된 "class1.cs" 파일이 존재한다면 삭제하고, 솔루션 탐색기 트리뷰에서 MyIIS7Project 프로젝트를 마우스 오른쪽 버튼으로 클릭해서 "추가", 새 항목…" 메뉴를 선택한 다음, "클래스"를 선택하고 이름란에 "MyHandler.cs"를 입력해서 MyHandler라는 이름으로 C# 클래스를 추가합니다.
  2. 개발의 편의를 위해 System.Web 네임스페이스를 임포트해서 이 네임스페이스에 포함된 형식들에 대한 접근을 용이하게 합니다.
  3. 그리고, MyHandler 클래스가 IHttpHandler 인터페이스를 구현하도록 지정하고, IHttpHandler 인터페이스의 멤버인 IsReusable 속성과 ProcessRequest() 메서드를 정의합니다. IHttpHandler 인터페이스를 마우스 오른쪽 버튼으로 클릭한 뒤 "인터페이스 구현" 옵션을 선택해서 처리를 신속하게 수행할 수 있습니다:

    먼저, IsReusable 속성은 한 번 생성된 헨들러의 인스턴스가 뒤이어 발생한 다른 요청에서 다시 사용될 수 있는지 여부를 지정합니다. 만약 헨들러의 이 속성이 재사용 가능하도록 지정되어 있고, 임의의 요청을 처리하면서 발생한 데이터가 클래스 멤버 변수에 저장되도록 헨들러가 작성되어 있다면, 헨들러의 인스턴스가 첫 번째 요청을 처리하고 난 다음 또 다른 요청을 처리하려고 할 때, 올바르지 않은 변수값이 멤버 변수에 저장되어 있을 수도 있습니다. 그러나, 런타임은 결코 이런 경우에도 동시에 수행되는 두 개의 요청을 처리하기 위해서 헨들러의 같은 인스턴스를 사용하지는 않는다는 점에 주의하십시오. 헨들러가 특정 요청에 대한 데이터를 멤버 변수에 저장하지 않고 ProcessRequest 메서드가 빈번하게 호출된다면 이 속성이 true를 리턴하도록 작성해서 재사용 가능하도록 지정합니다.

    다음으로 ProcessRequest() 메서드는 바로 헨들러가 수행하는 제반 작업을 처리하는 핵심 메서드입니다. 이 메서드는 인자로 전달된 HttpContext 인스턴스로부터 제공되는 HttpRequest 인스턴스에 지정된 요청들을 처리한 다음, 역시 HttpContext를 통해서 제공되는 HttpResponse 인스턴스를 사용해서 알맞은 응답을 생성합니다. 그러나, 이 ProcessRequest() 메서드는 요청이 작성한 헨들러에 맵핑되도록 헨들러 맵핑이 설정된 경우에만 런타임에 의해서 ExecuteRequestHandler 요청 처리 시점에 호출됩니다. 바로 이 점이 특정 응용 프로그램에 대한 모든 요청에 대해 이벤트 통보를 받는 모듈과 구분되는 점입니다.
  4. 먼저 IsReusable 속성을 구현해보도록 하겠습니다. 지금 작성중인 헨들러는 요청에 대한 어떠한 상태 정보도 멤버 변수에 저장하지 않으며, 각각의 요청들에 대해 ProcessRequest() 메서드가 반복 호출되더라도 아무 문제가 없으므로 true를 리턴해서 재사용 가능하도록 지정합니다.
    public bool IsReusable
    {
        get { return true; }
    } 
  5. 마지막으로, ProcessRequest() 메서드가 뭔가 의미있는 작업을 처리하도록 구현해보겠습니다. 단순하고 명확한 예제 구현을 위해 서버의 현재 시간을 출력하되 쿼리스트링을 통해서 시간대를 선택적으로 지정할 수 있도록 헨들러를 작성할 것입니다. 목표는 http://myserver/time.tm과 같은 형식으로 URL을 입력해서 서버의 현재 시간을 리턴받는 것입니다. 또는, http://myserver/time.tm?utc=true와 같은 형식으로 URL을 입력해서 국제 표준시로 서버의 현재 시간을 리턴받을 수도 있어야 합니다. 따라서, 다음과 같이 메서드를 구현합니다:
    public void ProcessRequest(HttpContext context) 
    { 
        DateTime dt; 
        String useUtc = context.Request.QueryString["utc"]; 
        if (!String.IsNullOrEmpty(useUtc) && useUtc.Equals("true")) 
        { 
            dt = DateTime.UtcNow; 
        } 
        else 
        { 
            dt = DateTime.Now; 
        } 
        context.Response.Write(String.Format("<h1>{0}</h1>", dt.ToLongTimeString())); 
    }
    이 코드는 HttpRequest.QueryString 컬렉션을 통해서 쿼리스트링 변수를 가져오고 HttpResponse.Write 메서드를 사용해서 현재 시간을 응답에 기록하고 있습니다. 그러나, 이 코드는 어디까지나 헨들러에서 처리할 수 있는 수 많은 작업들 중 하나의 사례를 소개하기 위한 단순한 샘플일 뿐입니다. HttpRequest 클래스는 요청에 대해 무수히 다양한 정보들을 제공해주며, HttpResponse 클래스는 클라이언트에게 보낼 응답을 가공하기 위한 수 많은 다른 방법들을 제공해줍니다.

이것으로 헨들러 작성이 끝났습니다.

코드 마무리: 모듈 및 헨들러 컴파일하기

이제 모듈과 헨들러의 구현이 모두 마무리됐으므로, 프로젝트를 컴파일해서 ASP.NET이 런타임에 로드할 수 있도록 어셈블리를 만들어야 합니다. 비주얼 스튜디오나 비주얼 스튜디오 익스프레스를 사용하고 있다면 "Ctrl-Shift-B" 키를 입력해서 프로젝트를 컴파일하거나 솔루션 탐색기에서 마우스 오른쪽 버튼으로 프로젝트를 클릭하고 "빌드" 메뉴를 선택해서 컴파일 할 수 있습니다.

프로젝트를 컴파일하면 .PDB 심볼 파일과 함께 .DLL 어셈블리 파일이 <프로젝트 디렉터리>\bin\debug 폴더에 생성됩니다. .PDB 심볼 파일은 서버에서 어셈블리를 디버깅할 때 사용할 수 있으며, 프로젝트의 디버깅 과정 중 예외가 발생한 소스 코드의 라인 정보 등을 담고 있습니다.

운영 서버에 어셈블리를 업로드 할 때는 먼저 솔루션 탐색기에서 솔루션 노드를 마우스 오른쪽 버튼으로 클릭하고 구성 관리자 메뉴를 선택해서 실행한 다음, 솔루션 구성을 "Release"로 변경하고 다시 컴파일합니다. 그리고, 이렇게 디버깅 정보가 제거되어 보다 빠른 코드로 최적화된 릴리즈 버전 어셈블리를 PDB 파일은 제외하고 업로드합니다.

비주얼 스튜디오를 사용하고 있지 않다면, .NET 프레임워크 런타임에 포함된 명령 프롬프트 C# 컴파일러를 사용해서 프로젝트를 컴파일합니다. 프로젝트를 컴파일하려면 명령 프롬프트를 열고(윈도우 비스타나 윈도우 서버 2008을 사용중이라면 "관리자 권한으로 실행" 옵션을 사용해서 명령 프롬프트를 실행해야 합니다) 다음 명령을 입력합니다:

> %windir%\Microsoft.NET\Framework\v2.0.50727\csc.exe /t:library /out:MyIIS7Project.dll /debug *.cs /r:System.Web.dll

이 명령은 MyIIS7Project.DLL 파일과 MyIIS7Project.PDB 파일을 생성합니다. 릴리즈 버전을 컴파일하려면 /debug 스위치를 생략하고 대신 어셈블리 최적화를 위해 /o 스위치를 추가합니다.

서버에 어셈블리 배포하기

이제 구현된 사용자 정의 모듈과 헨들러를 웹 응용 프로그램에 배포해보도록 하겠습니다. 모듈이나 헨들러를 응용 프로그램에 배포하거나 설정하는 방법에는 일반적으로 선택할 수 있는 몇 가지 방법이 존재하는데, 그 중에서 상황에 알맞은 방법을 선택하시면 됩니다. 본문에서는 그 중 가장 기본적인 배포 방법에 대해서 살펴보겠습니다. 그 밖에 전체 서버에 모듈이나 헨들러를 한 번에 배포하는 방법 등의 배포와 구성 설정에 대한 보다 자세한 논의는 Deploying IIS 7 Modules and Handlers (미공개) 기사를 참고하시기 바랍니다.

지금부터 설명드릴 내용들은 모듈이나 헨들러를 IIS 7 서버에 존재하는 기존에 만들어진 응용 프로그램에 배포한다고 가정합니다. 만약, 미리 만들어진 응용 프로그램이 없다면 보통 %systemdrive%\inetpub\wwwroot 폴더에 위치해 있는 Default Web Site 루트 응용 프로그램으로 테스트하면 됩니다. 여기에서는 Default Web Site 하위의 "MyIIS7Project"라는 이름의 응용 프로그램에 모듈 및 헨들러를 배포해 보겠습니다. *

모듈이나 헨들러를 배포하려면 먼저 ASP.NET 응용 프로그램에서 사용가능한 어셈블리를 생성합니다.

  1. 컴파일된 MyIIS7Project.dll 어셈블리 파일을 웹 응용 프로그램 루트 하위의 /BIN 디렉터리에 복사합니다. 만약, /BIN 디렉터리가 존재하지 않는다면 새로 만들면 됩니다.
  2. 그 다음에는 응용 프로그램이 모듈이나 헨들러를 로드하도록 구성을 설정해야 합니다. 시작 메뉴에서 빠른 검색창에 inetmgr.exe를 입력하고 엔터키를 눌러 IIS 7 관리 도구를 실행합니다. 그리고, 좌측 트리뷰에서 서버 노드를 더블 클릭해서 확장하고 "사이트" 노드를 확장한 다음, 모듈 및 헨들러를 설치하고자 하는 사이트나 응용 프로그램을 찾아 선택합니다.
  3. "모듈" 기능 아이콘을 더블 클릭해서 선택하고 작업 패인에서 "관리되는 모듈 추가..." 링크 버튼을 클릭해서 대화 상자를 띄운 다음, 대화 상자의 이름 텍스트 박스에는 적당한 모듈의 이름을, 종류 드롭다운 박스에는 "MyIIS7Modules.MyModule"을 입력합니다. 참고로 종류 드롭다운 박스에 직접 값을 입력하는 대신 드롭다운 박스 목록에서 적절한 값을 선택할 수도 있는데, IIS 7 관리 도구가 자동적으로 /BIN 폴더에 존재하는 어셈블리들 중에서 IHttpModule 인터페이스를 구현한 어셈블리를 인식해서 이 목록에 출력합니다. 마지막으로 확인 버튼을 클릭하면 모듈이 추가됩니다.
  4. 다시 좌측 트리뷰에서 사이트나 응용 프로그램 노드를 클릭한 다음, "처리기 매핑" 기능 아이콘을 더블 클릭해서 헨들러를 추가합니다. 작업 패인에서 "관리되는 처리기 추가..." 링크 버튼을 클릭해서 대화 상자를 띄우고, 대화 상자의 요청 경로 텍스트 박스에는 "time.tm"을 입력하고, 형식 드롭다운 박스에는 "MyIIS7Modules.MyHandler"를, 그리고 이름 텍스트 박스에는 적당한 헨들러의 이름을 입력합니다. 마찮가지로 이번에도 형식 드롭다운 박스의 값은 관리 도구가 어셈블리로부터 자동으로 감지하여 목록에 출력한 값을 선택해서 입력할 수도 있습니다. 확인 버튼을 클릭해서 헨들러를 추가합니다.

여기까지 설정을 마치고 나면 응용 프로그램에 의해 MyModule 모듈이 로드되어 이 응용 프로그램을 대상으로 한 모든 요청에 대해 실행되며, 응용 프로그램에 전달된 요청 중 time.tm에 대한 요청과 MyHandler 헨들러가 맵핑됩니다.

그런데, 주의해야 할 점은 지금까지 설명한 모듈과 응용 프로그램에 대한 구성 설정은 IIS 7 통합 모드로 설정된 응용 프로그램에서만 동작한다는 사실입니다. 모듈과 헨들러를 IIS 7 클래식 모드 응용 프로그램이나 이전 버전의 IIS에서 실행하려면 반드시 모듈과 헨들러에 대한 클래식 구성 설정이 필요합니다. 더군다나, 헨들러를 IIS 7 클래식 모드 응용 프로그램이나 이전 버전의 IIS에서 실행하려면, 먼저 IIS의 스크립트 맵에 .tm 확장자를 ASP.NET에 맵핑하는 스크립트 맵을 만들어 추가해야 하며, 모듈도 ASP.NET과 맵핑된 확장자를 가진 파일들에 대한 요청들만을 대상으로 동작합니다. 이 부분에 관한 보다 자세한 정보는 Deploying IIS 7 Modules and Handlers (미공개) 기사를 참고하시기 바랍니다.

모듈이나 헨들러에 대한 구성 설정은 새로운 IIS 7 명령 프롬프트 도구인 AppCmd.exe를 이용해서 처리할 수도 있으며, 스크립트나 관리되는 코드를 사용해서 조작할 수도 있고, 직접 수작업으로 web.config 파일을 편집해서 설정할 수도 있습니다. 이런 추가적인 방법에 대한 보다 자세한 내용은 Deploying IIS 7 Modules and Handlers (미공개) 기사를 참고하시기 바랍니다.

* 이 섹션에서 얘기하고 있는 "웹 응용 프로그램"이나 "응용 프로그램"은 간단하게 말해서 웹 사이트 루트나 가상 디렉터리라고 생각하시면 됩니다. 이 두 개념 간의 상관 관계가 잘 이해되지 않는 분들은 이 문서를 참고하시기 바랍니다.

모듈 및 헨들러 테스트하기

모듈 및 헨들러를 배포하고 구성 설정까지 마쳤다면, 이번에는 테스트를 해 볼 차례입니다:

  1. 먼저, 웹 브라우저로 헨들러가 배포된 응용 프로그램 내부에 존재하는 "time.tm" 파일에 대한 요청을 전달해서 헨들러를 테스트 해 보겠습니다. 만약 테스트가 성공한다면 웹 브라우저 화면에 서버의 현재 시간이 출력될 것입니다. 가령, Default Web Site 하위에 존재하는 MyIIS7Project 응용 프로그램에 헨들러를 배포했다면 http://localhost/MyIIS7Project/time.tm과 같은 요청을 응용 프로그램에 전송합니다.

    만약, 헨들러가 정상적으로 응용 프로그램에 배포되었다면 다음과 같이 서버의 현재 시간이 출력됩니다:

    그리고, http://localhost/MyIIS7Project/time.tm?utc=true와 같이 쿼리스트링으로 옵션을 지정하는 요청을 전송해서 국제 표준시가 출력되는지도 확인해봅니다.
  2. 그러면 이번에는 모듈을 테스트 해 보겠습니다. 먼저, page.html이라는 이름으로 간단한 HTML 페이지를 작성하고 /time.tm 파일에 대한 링크를 추가합니다:

    page.html
    <html>
        <body>
            <a href="time.tm">View current server time</a>
        </body>
    </html>
    그리고, 웹 브라우저에 http://localhost/MyIIS7Project/page.html를 입력해서 이 페이지를 띄우고 링크를 클릭합니다. 링크를 클릭해보면 다음과 같이 오류가 발생하는 것을 확인할 수 있을 것입니다:

    아마 방금전까지 정상적으로 동작하던 페이지가 단순히 링크를 걸었다고 해서 오류가 발생한다는 사실이 이상하게 느껴질 수도 있을 것입니다. 이런 결과가 발생하는 이유는 본문에서 작성한 모듈이 리퍼러 헤더에 값이 존재하는 경우 요청을 거부하도록 작성되었으며, 웹 브라우저에 직접 URL을 입력하지 않고 링크를 클릭해서 웹 사이트에 접근하는 경우 항상 리퍼러 헤더 값이 설정되기 때문입니다. 따라서, URL을 직접 입력해서 페이지를 요청하면 정상적으로 접근이 가능하지만, 다른 페이지로부터 링크를 클릭해서 페이지에 접근하면 항상 모듈에 의해 요청이 거부되는 것입니다.

요약

본문에서는 친숙한 ASP.NET API를 사용해서 모듈과 헨들러를 개발하고 응용 프로그램에 배포하는 기본적인 단계들을 살펴봤습니다. 또한 개발환경에 알맞은 방법 선택과 어떤 경우에 모듈을 작성해야하고, 또 어떤 경우에 헨들러를 작성해야 하는지에 대해서도 살펴봤습니다. 본문의 이런 정보들은 IIS 7 응용 프로그램에 배포 가능한 첫 번째 모듈과 헨들러를 개발할 때 많은 도움이 될 것입니다.

본문에서 살펴본 모듈과 헨들러의 소스 코드 프로젝트는 여기에서 다운로드 받으실 수 있습니다. ASP.NET의 멤버쉽 제공자 기반 기본 인증 모듈 구현 샘플에 관한 내용을 다루고 있는 .NET을 이용한 모듈 개발 기사도 참고해보시기 바랍니다.

그리고, 필자의 블로그(http://www.mvolo.com/)에서 IIS 7 모듈 개발에 대한 다양한 자료와 팁을 살펴보거나, 응용 프로그램에 적용할 수 있는 여러 가지 IIS 7 모듈들을 다운로드 받을 수 있습니다. 가령, HttpRedirection 모듈을 사용해서 응용 프로그램에 대한 요청 리디렉션하기, DirectoryListingModule 모듈을 사용해서 세련된 IIS 웹 사이트 디렉터리 목록 출력하기, IconHandler를 사용해서 세련된 ASP.NET 응용 프로그램 파일 아이콘 출력하기, 그리고 IIS 와 ASP.NET을 사용해서 핫-링크 막기 등을 살펴보시기 바랍니다.

관련 자료