달력

42024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

출처 : MSDN

HTTP 모듈과 처리기를 사용하여 플러그형 ASP.NET 구성 요소 만들기

Scott Mitchell, 4GuysFromRolla.com
Atif Aziz, Skybow AG

2004년 9월

요약: 이 기사에서는 Scott Mitchell과 Atif Aziz가 HTTP 모듈과 처리기를 사용하여 오류 로깅을 ASP.NET 응용 프로그램에 추가하는 방법에 대해 설명합니다.

MSDNElmah.msi 샘플 파일을 다운로드하십시오.

목차

소개
ELMAH: Error Logging Modules And Handlers
HTTP 처리기 및 모듈에 대한 간략한 개요
ELMAH의 아키텍처 검토
ASP.NET 웹 응용 프로그램에 ELMAH 추가
결론
참고 자료
관련 서적

소개

ASP.NET 응용 프로그램에서 작업을 수행한 적이 있으며 다른 ASP.NET 응용 프로그램에서 간편하게 재사용할 수 있도록 유용한 일부 기능 집합을 디자인한 적이 있으십니까? ASP.NET은 다른 유형의 기능을 구성 요소화하기 위한 다양한 도구를 제공합니다. ASP.NET에서의 재사용을 위한 가장 일반적인 두 가지 도구는 다음과 같습니다.

  • 사용자 인터페이스 요소 및 기능을 위한 사용자 컨트롤 및 컴파일된 사용자 지정 서버 컨트롤
  • 비즈니스 논리 및 데이터 액세스 코드를 위한 .NET 클래스 라이브러리

별다른 주목을 끌지 못하는 두 개의 ASP.NET 재사용 도구는 HTTP 모듈과 처리기입니다(이 기사에는 영문 페이지 링크가 포함되어 있습니다).

HTTP 처리기와 모듈에 익숙하지 않더라도 걱정하실 필요는 없습니다. 이 기사의 뒷부분에서 좀더 자세하게 설명할 것입니다. 지금은 우선 ASP.NET 리소스 요청 도중에 발생하는 이벤트에 응답하여 실행하도록 구성할 수 있는 HTTP 모듈과 클래스에 대해 살펴보겠습니다. HTTP 처리기는 특정 리소스나 특정 유형의 리소스를 렌더링하는 클래스입니다. 실제로 ASP.NET 웹 페이지를 프로젝트에 추가할 때마다 필수적으로 HTTP 처리기를 작성하게 됩니다. 이는 ASP.NET 웹 페이지의 HTML 부분이 런타임에 동적으로 컴파일될 때 결과적으로 HTTP 처리기가 구현되는 System.Web.UI.Page에서 직접 또는 간접적으로 상속이 이루어지기 때문입니다. 이것은 인라인 전략을 사용하는지 아니면 코드 숨김 전략을 사용하는지와는 무관합니다.

아시다시피 ASP.NET 응용 프로그램은 일반적으로 최종 사용자의 브라우저에서 요청 시에 호출되는 웹 페이지 집합으로 구성됩니다. ASP.NET 개발자가 작성하는 대부분의 코드는 특정 웹 페이지에 대한 요청과 관련됩니다. 예를 들면 일부 검색 쿼리에 기초하여 데이터베이스 결과를 표시하기 위한 특정 페이지의 코드 숨김 클래스에 있는 코드 등이 이에 속합니다. 그러나 경우에 따라서는 단일 웹 페이지와 관련된 코드, 즉 응용 프로그램의 모든 페이지에 적용되는 코드를 작성해야 할 수도 있습니다. 예를 들어 각 사용자가 웹 사이트에서 이동한 순서를 추적해야 할 수 있습니다. 이렇게 하려면 요청 시간과 사용자를 식별하는 정보가 각 페이지에 기록되도록 해야 합니다.

이러한 로깅 기능을 제공하는 방법 중 하나는 사이트의 각 웹 페이지에 대해 Page_Load 이벤트 처리기에서 관련 데이터를 데이터베이스에 기록하는 코드를 추가하는 것입니다. 그러나 이 방법은 유지 관리하거나 재사용하는 데 어려움이 있습니다. 사이트에서 새 ASP.NET 페이지를 추가할 때마다 적절한 로깅 코드가 포함되었는지 확인해야 합니다. 비슷한 기능을 다른 사이트에 추가하려는 경우 해당 사이트의 각 페이지에서 필요한 코드를 추가해야 합니다. 이상적인 경우라면 로깅 기능은 각 개별 페이지의 기능과 논리 및 물리적으로 구별되어야 하며 로깅 기능을 다른 사이트에 추가하는 것은 사이트의 /bin 디렉터리에서 어셈블리를 삭제하는 것만큼 간단할 것입니다.

이러한 재사용과 관리 용이성은 HTTP 모듈과 처리기를 통해 가능합니다. 이 기사에서는 오류 로깅을 매우 쉽게 관리하고 재사용할 수 있게 만들도록 설계된 일련의 HTTP 모듈과 처리기를 살펴보도록 하겠습니다. 이 기사의 목적은 HTTP 처리기와 모듈을 매우 높은 수준의 구성 요소화 형태로 사용함으로써 전체 기능을 웹 응용 프로그램과 무관한 단일 단위로 개발, 패키지화 및 배포할 수 있음을 보여 주는 것입니다. HTTP 처리기와 모듈을 통한 재사용 및 구성 요소화 이점을 사용하는 응용 프로그램이 이러한 목적을 설명하는 데 주로 사용됩니다.

ELMAH: Error Logging Modules And Handlers(오류 로깅 모듈 및 처리기)

이 기사에서 살펴볼 ELMAH(Error Logging Modules And Handlers(오류 로깅 모듈 및 처리기))는 공동 저자인 Atif Aziz(http://www.raboof.com/ 가 작성한 것이며, 오류 로깅 기능을 ASP.NET 웹 응용 프로그램에 간단하게 추가할 수 있는 방법을 제공합니다. ELMAH에서는 응용 프로그램 전체 로깅과 같은 웹 응용 프로그램 관련 코드를 위한 높은 수준의 구성 요소화를 HTTP 모듈과 처리기를 사용하여 제공하는 방법을 보여 줍니다. ELMAH는 플러그형 솔루션이므로 재컴파일이나 재배포할 필요 없이 실행 중인 ASP.NET 웹 응용 프로그램에 동적으로 추가할 수 있습니다.

특정 웹 응용 프로그램을 완벽하게 작성하고 테스트했더라도, 문제가 발생할 가능성은 여전히 존재합니다. 이것은 코드에 오류가 있기 때문이 아니라 전자 메일 서버가 응답하지 않거나 일부 데이터 손상으로 인해 암호화 오류가 발생하기 때문일 수 있습니다. 어떤 이유든 간에 예외가 발생할 경우 특히 라이브 사이트에서는 문제 진단을 지원하기 위해 예외에 대한 세부적인 정보를 기록하는 것이 중요합니다. ELMAH는 중앙화된 오류 로깅 및 알림을 위한 메커니즘을 제공합니다. ASP.NET 응용 프로그램에서 catch되지 않는 예외가 발생할 때마다 ELMAH는 알림을 받게 되며 Web.config 파일에 지정된 대로 예외를 처리합니다. 예외의 세부 정보를 데이터베이스에 기록하거나, 전자 메일을 관리자에게 보내거나, 두 작업을 모두 수행하는 것이 여기에 포함될 수 있습니다.

ELMAH는 처리되지 않은 예외에 적절하게 대응하도록 디자인된 것이 아니라 단순히 처리되지 않은 예외의 세부 정보만을 기록합니다. 따라서 ELMAH를 ASP.NET 웹 응용 프로그램에 추가하면 이 응용 프로그램에서 발생한 처리되지 않은 모든 예외가 기록됩니다. 처리되지 않은 예외가 발생하더라도 ELMAH는 최종 사용자의 작업에 영향을 주지 않습니다. 최종 사용자에게는 여전히 "서버 오류" 페이지가 표시되며, HTTP 500 오류를 처리하도록 사용자 지정 오류를 구성한 경우 다른 페이지로 이동합니다. 그러나 배후에서 ELMAH는 처리되지 않은 예외가 발생했음을 감지하고 세부 정보를 기록합니다.

ELMAH는 HttpApplication 개체의 Error 이벤트를 통해 처리되지 않은 예외를 검색합니다. Error 이벤트는 .NET 클래스 라이브러리 또는 ASP.NET 웹 페이지로부터의 요청을 처리하는 동안 catch되지 않은 예외가 버블링될 때마다 발생합니다. 많은 ASP.NET 응용 프로그램이 Server.ClearError() 메서드를 호출하여 사용자 지정 오류 페이지 및 처리를 잘못 구현한다는 점에 주의해야 합니다. 오류를 지우면 Error 이벤트가 발생하지 않을 뿐만 아니라 클라이언트에게 보고되지 않으므로 ELMAH는 예외를 기록할 수 있는 기회가 없습니다. 달리 말해서 사용자 지정 오류 페이지에서 ClearError()를 사용하면 사용자는 문제가 발생했음을 알게 되지만 관리자 자신은 이러한 사실을 알 수 없습니다.

참고   사용자 지정 오류 페이지를 만드는 방법에 대한 자세한 내용은 Eli Robillard의 Rich Custom Error Handling with ASP.NET  기사를 참조하십시오.
참고   ASP.NET 웹 서비스에서 처리되지 않은 예외가 발생하면 Error 이벤트가 HTTP 모듈에 버블링되지 않으며, 따라서 ELMAH에도 버블링되지 않습니다. 대신에 ASP.NET 런타임이 예외를 인터셉트하고 SOAP 오류가 클라이언트에게 반환됩니다. 웹 서비스에서 오류가 기록되게 하려면 SOAP 오류를 수신 대기하는 SOAP 확장  을 만들어야 합니다.

처리되지 않은 예외의 세부 정보를 기록하는 것 외에도 오류 로그를 볼 수 있는 일련의 HTTP 처리기가 ELMAH에 포함되어 있습니다. 처리되지 않은 모든 오류의 목록뿐만 아니라 특정 오류에 대한 세부 정보를 볼 수 있는 로그에 대한 웹 인터페이스가 제공됩니다(그림 1 및 2 참조).

그림 1. 오류 로그 보기

그림 2. 오류 보기

또한 오류 로그를 RSS로 렌더링할 수 있습니다. 이렇게 하면 관리자는 오류가 발생했을 때 자신이 선호하는 RSS 애그리게이터를 통해 알림을 받을 수 있습니다(그림 3 참조).

그림 3. 오류의 RSS 피드

참고   Really Simple Syndication의 약어인 RSS는 뉴스 및 변경되는 기타 유형의 콘텐츠를 배포하는 데 널리 사용되는 XML 서식 표준입니다. RSS를 사용하여 콘텐츠를 배포하는 방법이나 웹 기반의 RSS 판독기를 만드는 방법을 비롯하여 RSS에 대한 자세한 내용은 Creating an Online News Aggregator with ASP.NET  을 참조하십시오.

이 기사에서는 간결하게 하기 위해서 주요 구성 요소를 중심으로 ELMAH의 일부 기능만 살펴봅니다. 전체 코드는 이 기사에서 다운로드할 수 있으며, 가능하면 전체 코드를 검토하여 구현 세부 정보를 확인하는 것이 좋습니다. 또한 http://workspaces.gotdotnet.com/elmah 에는 토론, 문제 보고, 최신 변경 내용 확인 등을 위한 ELMAH용 GotDotNet Workspace 설치 프로그램이 있습니다.

중앙화된 오류 로깅을 위한 기존 솔루션

ASP.NET이 오류 로깅 및 보기 기능을 기본적으로 제공하지 않지만 Microsoft의 Patterns & Practices Group  은 오픈 소스 오류 로거인 EMAB(Exception Management Application Block 를 만들었습니다. EMAB는 데스크톱 및 웹 기반 .NET 응용 프로그램에서 모두 작동하도록 설계되었지만, 기본적으로 EMAB가 예외 세부 정보를 Windows 이벤트 로그에 게시하기 때문에 EMAB는 주로 웹 응용 프로그램이 있는 데스크톱 응용 프로그램용으로 추가적으로 설계된 것처럼 보입니다. 이벤트 로그가 데스크톱 응용 프로그램의 간략한 예외 정보를 저장하기에 적절한 백업 저장소이기는 하지만 대부분의 웹 응용 프로그램, 특히 웹 호스팅 회사의 공유 서버에서 호스팅되는 응용 프로그램은 이벤트 로그를 사용하려 하지 않습니다. 이벤트 로그를 사용하려면 ASP.NET 응용 프로그램이 이벤트 로그에 기록할 수 있도록 특수한 권한을 설정해야 하기 때문입니다. 물론 EMAB는 데이터베이스에 정보를 기록하는 사용자 지정 게시자를 만들 수 있는 충분한 유연성을 제공하지만 이것은 개발자의 개입이 요구되는 별도의 작업 단계입니다.

참고   ELMAH는 Microsoft SQL Server 2000용의 데이터베이스 로깅 모듈을 제공합니다. 이에 대해서는 뒤에 설명할 것입니다. 또한 ELMAH를 사용하면 웹 서버의 파일 시스템에 있는 XML 파일에 예외 세부 정보를 기록하는 로거와 같은 사용자 지정 예외 로거를 만들 수 있습니다. 실제로, 사용하려는 EMAB에 대해 사용자 지정 게시자를 이미 작성한 경우에는 ELMAH를 확장하여 Exception Management Application Block을 사용할 수 있습니다.

EMAB를 사용하여 예외 정보를 기록하는 방법은 웹 응용 프로그램의 관리 용이성과 재사용 가능성에 큰 영향을 끼칩니다. 예를 들어 예외 정보를 기록하기 위한 간단한 방법은 각 ASP.NET 웹 페이지에서 각 코드 블록 주위에 try ...catch 블록을 배치하여 catch 섹션에서 EMAB를 호출하는 것일 수 있습니다.

private void Page_Load(object sender, EventArgs e) { try { // 예외를 일으킬 
수 있는 코드 } catch (Exception ex) { // 예외 로거 라이브러리를 호출하여 예외 정보를
기록합니다. } }(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사
에는 설명을 위해 번역문으로 제공됩니다.)

이 방법은 각각의 모든 ASP.NET 웹 페이지에 예외 로깅을 긴밀하게 결합하기 때문에 관리 용이성이나 재사용 가능성이 전혀 없다는 점에서 매우 비효율적입니다. Global.asaxApplication_Error 이벤트에서 EMAB를 사용한다면 더 나은 방법이 될 것입니다. 이 방법은 예외 게시 코드가 각 ASP.NET 웹 페이지에 포함되는 대신에 중앙화된 단일 장소에 위치하기 때문에 관리 용이성과 재사용 가능성이 존재하는 더 느슨하게 결합된 아키텍처를 제공합니다. 이 방법의 단점은 플러그형이 아니라는 것입니다. 이 오류 로깅 기능을 다른 ASP.NET 웹 응용 프로그램에 추가하려면 응용 프로그램의 Global.asax를 수정해야 하므로 응용 프로그램을 재컴파일 및 재배포해야 합니다.

이 기사에서 중점적으로 다루려는 내용은 EMAB를 대체하는 수단을 소개하는 것이 아니라 HTTP 처리기와 모듈을 통해 가능해지는 구성 요소화를 강조하려는 것입니다. ELMAH는 중앙화된 오류 로깅과 같은 일반적인 작업을 가져와 구성 요소화함으로써 쉽게 관리할 수 있게 만들고 높은 수준의 재사용 가능성을 제공하는 방법을 보여 줍니다. ELMAH의 목적은 적용 가능한 기능을 구성 요소화하는 것에 대한 지침을 제공하는 것입니다.

HTTP 처리기 및 모듈에 대한 간략한 개요

ELMAH의 아키텍처와 구현에 대한 구체적인 내용을 검토하기 전에 HTTP 처리기와 모듈을 잠깐 살펴보도록 하겠습니다. IIS 웹 서버에 요청이 도착하면 IIS는 요청의 확장을 검사하여 처리 방법을 결정합니다. HTML 페이지, CSS 파일, 이미지, JavaScript 파일 등의 정적 콘텐츠의 경우 IIS는 요청 자체를 처리합니다. ASP 페이지, ASP.NET 웹 페이지, ASP.NET 웹 서비스 등의 동적 콘텐츠의 경우 IIS는 요청을 지정된 ISAPI 확장에 위임합니다. ISAPI 확장은 특정 유형의 요청을 렌더링하는 방법을 알고 있는 관리되지 않는 코드입니다. 예를 들어 asp.dll ISAPI 확장은 전통적인 ASP 웹 페이지의 요청을 렌더링하며 aspnet_isapi.dll ISAPI 확장은 ASP.NET 리소스에 대한 요청이 있을 때 호출됩니다.

ISAPI 확장 외에도 IIS는 ISAPI 필터를 허용합니다. ISAPI 필터는 IIS에 의해 발생한 이벤트에 응답하여 실행할 수 있는 관리되지 않는 코드입니다. 요청 수명 주기 동안에 IIS는 해당 이벤트를 발생시키는 여러 단계를 거칩니다. 예를 들어 요청이 처음 IIS에 도달했을 때, 요청을 인증하려고 할 때, 렌더링된 콘텐츠를 다시 클라이언트에게 보내려고 할 때와 같은 여러 경우에 이벤트가 발생합니다. ISAPI 필터는 일반적으로 URL 재작성, 압축, 특수한 인증 및 권한 부여, 특수한 로깅 등의 기능을 제공하는 데 사용됩니다.

ASP.NET 리소스에 대한 요청은 IIS에 도달하면 ASP.NET 엔진에 라우팅되며 ASP.NET 엔진은 요청된 리소스에 대한 콘텐츠를 렌더링합니다. ASP.NET 엔진은 요청이 ASP.NET HTTP 파이프라인을 통과할 때 여러 이벤트를 발생시킨다는 점에서 IIS와 유사하게 작동합니다. 게다가 ASP.NET 엔진은 요청된 리소스의 렌더링을 특정 클래스에 위임합니다. IIS가 관리되지 않는 ISAPI 확장 및 필터를 사용하는 것과 달리 ASP.NET은 HTTP 처리기 및 모듈이라고 부르는 관리되는 클래스를 사용합니다.

HTTP 처리기는 특정 유형의 리소스를 렌더링하는 클래스입니다. 예를 들어 ASP.NET 웹 페이지를 위한 코드 숨김 클래스는 특정 웹 페이지의 태그를 렌더링하는 방법을 알고 있는 HTTP 처리기입니다. 처리기를 특정 유형의 리소스에 대한 태그를 만드는 방법을 알고 있는 특수한 렌더러로 생각하면 이해가 빠를 것입니다.

참고   실제적인 몇 가지 처리기 응용 프로그램을 비롯하여 HTTP 처리기에 대한 자세한 내용은 Serving Dynamic Content with HTTP Handlers  를 참조하십시오.

HTTP 모듈은 요청이 서버에서 해당 수명 주기의 단계를 통과하는 동안에 발생한 다양한 이벤트를 사용할 수 있는 클래스입니다. ASP.NET 응용 프로그램 이벤트와 같은 이벤트는 ELMAH 이벤트가 관심을 가지는 처리되지 않은 예외가 발생했을 때 발생하는 Error 이벤트입니다.

참고   HTTP 모듈을 사용하여 URL 재작성을 구현하는 방법을 비롯하여 HTTP 모듈에 대한 자세한 내용은 URL Rewriting in ASP.NET  을 참조하십시오.

그림 4는 ASP.NET HTTP 파이프라인을 그래픽으로 표현한 것입니다. IIS에 도착하는 요청으로부터 프로세스가 시작된다는 점에 주의해야 합니다. 요청된 리소스가 ASP.NET ISAPI 확장에 의해 처리되도록 구성되었다고 가정하면 IIS는 요청을 관리되지 않는 aspnet_isapi.dll ISAPI 확장으로 디스패치합니다. 이 ISAPI 확장은 요청을 관리되는 ASP.NET 엔진에 전달합니다. 요청 수명 주기 동안에 하나 이상의 HTTP 모듈이 실행될 수 있습니다(등록된 모듈과 이러한 모듈이 구독한 이벤트에 따라 달라짐). 마지막으로 ASP.NET 엔진은 콘텐츠 렌더링, 처리기 호출 및 생성된 콘텐츠를 IIS로 반환하는 작업을 수행하는 HTTP 처리기를 결정합니다(IIS는 해당 콘텐츠를 다시 요청 클라이언트에게 반환함).

그림 4. 오류 로거를 통과하는 데이터 흐름

ELMAH는 Error 이벤트에 대한 이벤트 처리기를 가진 HTTP 모듈을 통해 중앙화된 오류 로깅을 제공합니다. 이벤트가 발생하면 ELMAH는 예외 세부 정보를 기록합니다. 또한 ELMAH는 주로 HTML 및 RSS 태그를 생성하여 오류 로그의 정보를 표시하는 역할을 수행하는 HTTP 처리기를 사용합니다.

모듈 또는 처리기 어셈블리를 웹 응용 프로그램의 /bin 디렉터리에 복사하고 몇 줄의 구성을 Web.config 파일에 복사하는 방법을 통해 다양한 처리기나 모듈을 사용하도록 기존의 웹 응용 프로그램을 구성합니다.

웹 응용 프로그램에 대해 HTTP 모듈을 구성하려면 추가할 모듈의 유형을 지정하는 <httpModules> 섹션Web.config 파일에 포함시켜야 합니다.

<httpModules> <add name="ModuleName" type="ModuleType" /> </httpModules> 

ModuleType은 모듈의 유형을 지정하는 문자열로서 어셈블리 이름이 뒤에 오는 정규화된 클래스 이름(Namespace.ClassName)입니다. 또한 type 특성에는 강력한 이름의 어셈블리에 필요한 공개 키 토큰과 함께 버전 지정 및 culture 정보가 포함될 수 있습니다. 다음 코드는 ELMAH의 오류 로깅 모듈을 ASP.NET 응용 프로그램에 포함하기 위해 사용해야 하는 실제 <httpModules> 설정을 보여 줍니다.

<httpModules> 
<add name="ErrorLog" type="GotDotNet.Elmah.ErrorLogModule,
GotDotNet.Elmah, Version=1.0.5527.0,
Culture=neutral, PublicKeyToken=978d5e1bd64b33e5" />
</httpModules>

Web.config 파일에 <httpHandlers> 섹션을 추가하여 웹 응용 프로그램에서 HTTP 처리기를 사용할 수 있습니다. HTTP 처리기가 특정 유형 리소스의 콘텐츠를 렌더링하므로 <httpHandlers> 요소는 type 특성 외에 path 특성을 포함합니다. 이 특성은 이 HTTP 처리기에 매핑해야 하는 파일 경로나 확장을 나타냅니다. 또한 GET 또는 POST 요청에서와 같이 특정 유형의 HTTP 요청에 한하여 처리기를 사용하도록 제한할 수 있는 verb 특성이 있습니다. 다음 예제는 .ashx 확장명을 가진 파일에 대한 모든 요청에서 호출되는 HTTP 처리기를 만듭니다.

<httpHandlers> 
<add verb="*" path="*.ashx" type="HandlerType" />
</ httpHandlers >

HTTP 처리기에 대한 type 특성은 HTTP 모듈과 동일한 구문 옵션을 사용하여 표현합니다. Web.config의 이러한 설정은 machine.config 파일에 포함할 수도 있습니다. 이렇게 하면 서버의 모든 웹 응용 프로그램에 대해 처리기와 모듈이 활성화되는 효과가 있습니다. 다음 코드는 이 기사의 다운로드에 포함된 데모의 Web.config 파일에 있는 <httpHandlers> 요소를 보여 줍니다. ErrorLogPageFactory 클래스가 /elmah/default.aspx에 대한 모든 들어오는 요청을 렌더링하도록 지정된다는 것에 주의해야 합니다.

<httpHandlers> 
<add verb="POST,GET,HEAD" path="elmah/default.aspx"
type="GotDotNet.Elmah.ErrorLogPageFactory, GotDotNet.Elmah,
Version=1.0.5527.0, Culture=neutral, PublicKeyToken=978d5e1bd64b33e5" />
</httpHandlers>

위에서 볼 수 있듯이 HTTP 모듈과 처리기를 ASP.NET 웹 응용 프로그램에 추가하는 것은 매우 간단하기 때문에 불과 몇 초 만에 끝낼 수 있으며 ASP.NET 응용 프로그램을 재컴파일하거나 재배포하지 않아도 됩니다. 이는 HTTP 모듈과 처리기가 재사용을 위한 뛰어난 도구일 뿐만 아니라 관리가 용이한 느슨하게 결합된 조각으로 응용 프로그램을 구성 요소화할 수 있는 수단을 제공하기 때문입니다.

ELMAH의 아키텍처 검토

ELMAH의 아키텍처는 다음 세 개의 하위 시스템으로 구성됩니다.

  • 오류 로깅 하위 시스템
  • HTTP 모듈 하위 시스템
  • HTTP 처리기 하위 시스템

오류 로깅 하위 시스템은 두 개의 작업, 즉 오류를 로그에 기록하는 작업과 로그에서 오류 정보를 검색하는 작업을 수행합니다. HTTP 모듈 하위 시스템은 ASP.NET 응용 프로그램에서 처리되지 않은 예외가 발생할 경우의 오류 기록을 수행합니다. HTTP 처리기 하위 시스템은 오류 로그를 태그로 렌더링하여 오류 로그뿐만 아니라 RSS 피드에 대한 웹 기반 인터페이스를 구성할 수 있는 수단을 제공합니다.

그림 5에 나온 것처럼 HTTP 모듈 및 처리기 하위 시스템 모두 오류 로깅 하위 시스템을 사용합니다. HTTP 모듈 하위 시스템은 예외 정보를 오류 로깅 하위 시스템으로 보내고 HTTP 처리기 하위 시스템은 오류 정보를 읽어 렌더링합니다.

그림 5. 오류 로깅 시스템의 올바른 위치

ELMAH의 아키텍처를 제대로 이해하기 위해 이러한 세 개의 하위 시스템을 좀더 자세히 살펴보도록 하겠습니다.

오류 로깅 하위 시스템

오류 로깅 하위 시스템은 오류를 로그에 기록할 뿐만 아니라 특정 오류 또는 오류의 하위 집합에 대한 세부 정보를 검색하는 기능을 제공합니다. 이 기능은 다음과 같은 여러 클래스를 통해 가능합니다.

  • ErrorLog: 이 추상 클래스는 로그에서 읽고 쓰기 위한 계약상의 방법을 제공합니다.
  • Error: 이 클래스는 특정 오류의 세부 정보를 설명하는 속성을 포함합니다.
  • ErrorLogEntry: 이 클래스는 특정 ErrorLog에 대한 특정 Error 인스턴스를 나타냅니다. ErrorLogEntry는 본질적으로 Error 인스턴스가 시작된 ErrorLog 인스턴스와 함께 Error 인스턴스를 그룹화합니다.

이러한 세 가지 클래스에 대한 개요와 중앙화된 완벽한 예외 로깅 유틸리티를 제공하기 위해서 이러한 클래스가 HTTP 모듈 및 HTTP 처리기 하위 시스템과 함께 작동하는 방법에 대해 살펴보도록 하겠습니다.

ErrorLog 클래스 검토

특정 프로젝트 설정 또는 전략에 따라서 서로 다른 백업 저장소를 오류 로그에 사용할 수 있습니다. 예를 들어 프로덕션 서버에서는 예외를 Microsoft SQL Server에 기록하지만 개발 서버에서는 오류를 단순히 XML 파일 집합이나 Microsoft Access 데이터베이스에 저장하기를 원할 수 있습니다. 다른 백업 저장소를 사용하는 기능을 제공하기 위해 오류 로깅 하위 시스템은 추상 기본 클래스인 ErrorLog를 제공합니다. 이 클래스는 모든 ELMAH 오류 로거가 구현해야 하는 기본 메서드를 정의합니다. 이러한 메서드는 다음과 같습니다.

  • Log(Error): 오류를 백업 저장소에 기록합니다. Error 클래스는 처리되지 않은 예외에 대한 정보를 나타냅니다. 이 Error 클래스에 대해서는 좀더 자세하게 설명할 것입니다. 오류 정보를 기록하면서 Log() 메서드는 또한 고유 식별자를 오류에 할당해야 합니다.
  • GetError(id): 로그의 특정 오류에 대한 정보를 반환합니다.
  • GetErrors(...): 로그에서 오류의 하위 집합을 반환합니다. HTTP 처리기 하위 시스템은 이 메서드를 사용하여 모든 오류를 한 번에 표시하는 대신에 오류 로그를 페이지 방식으로 표시합니다.

ELMAH는 다음과 같은 두 개의 ErrorLog 구현을 제공합니다.

  • SqlErrorLog: System.Data.SqlClient 공급자를 사용하여 오류를 Microsoft SQL Server 2000 데이터베이스에 기록합니다. SqlErrorLog는 SQL Server 2000의 XML 기능 중 일부를 활용하기 때문에 SQL Server 2000이 필요하지만 이는 변경이 가능한 구현 세부 정보입니다.
  • MemoryErrorLog: 응용 프로그램의 메모리(RAM)에 오류를 기록합니다. 다시 말해서 AppDomain에 바인딩됨으로써 각 응용 프로그램은 고유한 개인 로그를 받게 됩니다. 물론 이 로그는 응용 프로그램이 다시 시작되거나 수명이 끝나면 더 이상 유지되지 않으므로 다른 구현이 실패할 수 있는 경우에 테스트 및 임시 문제 해결 목적에 가장 적합합니다.

일부 줄의 텍스트를 ASP.NET 웹 응용 프로그램의 Web.config 파일에 추가하는 간단한 방법으로 이러한 예외 로거 중 하나를 사용할 수 있습니다. 오류 세부 정보를 SQL Server나 응용 프로그램 메모리가 아닌 다른 장소에 저장해야 할 경우에는 고유한 사용자 지정 로거를 만들 수 있습니다. ELMAH에 대한 오류 로거를 구현하려면 ErrorLog를 확장하는 클래스를 만들고 원하는 저장소에 대해 Log(), GetError()GetErrors()의 구현을 제공해야 합니다.

ELMAH의 HTTP 모듈 및 처리기 하위 시스템이 지정된 ErrorLog 클래스(SqlErrorLog, MemoryErrorLog 또는 고유한 사용자 지정 로그 클래스)와 직접 상호 작용한다는 것에 주의해야 합니다. HTTP 모듈은 Error 인스턴스를 만들어 ErrorLog 메서드의 Log() 메서드에 전달하는 방법으로 예외 정보를 기록합니다. HTTP 처리기는 특정 ErrorLogEntry 인스턴스나 ErrorLogEntry 인스턴스 집합을 반환하는 ErrorLogGetError()GetErrors() 메서드를 통해 하나 이상의 오류에 대한 세부 정보를 읽습니다.

Error 클래스 검토

ErrorLogLog() 메서드에는 Error 유형의 입력 매개 변수가 필요합니다. Exception 클래스는 코드 스택에서 응용 프로그램 수명 주기 동안에 예외 정보를 전달하는 데 더 적합하기 때문에 .NET Framework에서 제공되는 Exception 클래스 대신에 사용자 지정 Error 클래스가 사용됩니다. 그러나 Exception 개체는 저장, 입력 및 이식성 문제로 인하여 예외 로그를 저장하기에는 이상적이지 않습니다. 물론 이진 serialization을 사용하여 Exception 인스턴스를 저장할 수 있지만 이 경우에는 사용 가능한 동일한 유형 및 어셈블리 집합을 사용하여 Exception 개체를 시스템에서 deserialize할 수 있어야 합니다. 로그와 로그의 내용은 이식 가능해야 하며 특정 런타임 또는 구성을 가진 시스템에서만 볼 수 있는 것이 아니어야 하므로 이러한 제한은 특히 관리 및 운영 측면에서 볼 때 받아들일 수 없습니다. 게다가 Exception 인스턴스는 웹 응용 프로그램에 대한 고유한 주변 정보(예: 현재 웹 요청의 ServerVariables 컬렉션에 대한 값)가 부족한 경우가 자주 있는데 이러한 정보 중에서 일부는 진단을 위해 반드시 필요한 것입니다. 따라서 한 마디로 말하자면, Error 클래스는 웹 응용 프로그램에서 발생한 예외에 대한 정보를 보유하면서 모든 예외 유형을 대체하는 역할을 수행합니다.

표 1에는 Error 속성의 전체 목록이 나와 있습니다.

속성설명
Exception이 오류가 나타내는 Exception 인스턴스입니다. 클래스의 인스턴스와 함께 유지되지 않는 런타임 전용 속성입니다.
ApplicationName이 오류가 발생한 응용 프로그램의 이름입니다.
HostName이 오류가 발생한 호스트 시스템의 이름입니다. 기본값은 Environment.MachineName입니다.
Type오류의 유형, 클래스 또는 범주입니다. 일반적으로 예외의 전체 유형 이름(어셈블리 자격 제외)입니다.
Source오류의 소스입니다. 일반적으로 Exception 개체의 Message 속성과 동일합니다.
Message오류를 설명하는 간단한 텍스트입니다. 일반적으로 Exception 개체의 Message 속성과 같습니다.
Detail오류에 대한 자세한 텍스트(예: 전체 스택 추적)입니다.
User오류 발생 시에 응용 프로그램에 로그인한 사용자입니다(예: Thread.CurrentPrincipal.Identity.Name에 의해 반환된 사용자).
Time오류가 발생한 날짜와 시간입니다. 항상 현지 시간입니다.
StatusCode오류의 결과로 응답 헤더에서 반환되는 상태 코드입니다. 예를 들어 FileNotFoundException의 경우 404입니다. 그러나 이 값은 ASP.NET 내에서 항상 정확하게 결정되지는 않습니다. 경우에 따라 이 StatusCode 값은 0으로 보고될 수 있습니다.
WebHostHtmlMessage사용자 지정 오류 페이지가 없을 경우 웹 호스트(ASP.NET)가 생성한 기본 HTML 메시지입니다.
ServerVariablesHttpRequest.ServerVariables에 포함되어 있는 것과 같은 웹 서버 변수의 NameValueCollection입니다.
QueryStringHttpRequest.QueryString에 포함되어 있는 것과 같은 HTTP 쿼리 문자열 변수의 NameValueCollection입니다.
FormHttpRequest.Form에 포함되어 있는 것과 같은 양식 변수의 NameValueCollection입니다.
CookiesHttpRequest.Cookies에 포함되어 있는 것과 같은 클라이언트가 보낸 쿠키의 NameValueCollection입니다.

WebHostHtmlMessage 속성에 대해서는 약간의 설명이 필요합니다. ASP.NET 웹 응용 프로그램에서 처리되지 않은 예외가 발생했으며 응용 프로그램이 사용자 지정 오류 페이지를 사용하도록 구성되지 않은 경우 그림 6과 비슷한 화면이 표시됩니다. 이 화면은 모든 ASP.NET 개발자에게는 익숙한 화면입니다.

그림 6. 표준 오류 페이지

예외가 발생하면 해당 화면의 실제 HTML 태그가 액세스되어 Error 클래스의 WebHostHtmlMessage 속성에 저장됩니다. 특정 예외에 대한 세부 정보를 표시하는 페이지를 방문했을 때 해당 Error 인스턴스가 WebHostHtmlMessage 속성에 값을 갖고 있는 경우 그림 6과 유사한 실제 예외 정보 화면을 표시하는 페이지에 대한 링크가 방문자에게 제공됩니다. 여기에서는 기록된 예외를 확인할 수 있을 뿐만 아니라 나중에 로그 검사 시에 ASP.NET에 의해 생성된 원래 오류 페이지를 방문할 수 있습니다. 또한 이와 함께 사용자 지정 오류도 활성화되어 있습니다.

Error 클래스는 또한 XML 형식과의 사이에서 해당 상태를 serialize 및 deserialize할 수 있는 방법을 제공합니다. 자세한 내용은 함께 제공되는 코드에서 FromXmlToXml을 참조하십시오.

ErrorLogEntry 클래스: Error를 ErrorLog와 연결

오류 로깅 하위 시스템의 마지막 클래스는 Error 인스턴스를 ErrorLog 인스턴스와 연결하는 ErrorLogEntry 클래스입니다. HTTP 처리기 하위 시스템이 특정 예외에 대한 정보를 검색하기 위해 GetError() 메서드를 호출하면 GetError() 메서드는 특정 백업 저장소에서 정보를 검색하여 ErrorLogEntry 인스턴스에서 해당 정보를 채웁니다. ErrorLogEntry 클래스에는 다음 세 개의 속성이 포함되어 있습니다.

  • Id: 예외 세부 정보에 대한 고유 ID입니다.
  • Log: 백업 저장소를 나타내는 ErrorLog 인스턴스에 대한 참조입니다.
  • Error: 특정 오류의 세부 정보를 포함하는 채워진 Error 클래스의 인스턴스입니다.

GetError() 메서드가 단일 ErrorLogEntry 인스턴스를 반환하는 것과 달리 GetErrors()ErrorLogEntry 인스턴스의 목록을 반환합니다. GetErrors()는 특히 한 번에 n개의 레코드씩 오류를 페이징할 수 있도록 설계되었습니다.

그림 7은 업데이트된 ELMAH의 아키텍처를 보여 주며, 오류 로깅 하위 시스템이 더 자세히 나와 있습니다.

그림 7. 업데이트된 아키텍처

HTTP 모듈 하위 시스템

ELMAH는 두 개의 HTTP 모듈, 즉 ErrorLogModuleErrorMailModule로 구성됩니다. ErrorLogModule은 응용 프로그램의 Error 이벤트에 대한 이벤트 처리기를 만드는 HTTP 모듈입니다. 처리되는 않은 예외가 발생할 경우 이 HTTP 모듈은 응용 프로그램의 구성에 지정된 대로 적절한 오류 로거를 가져와 Log() 메서드를 호출함으로써 현재 요청에 대한 HttpContext와 예외 정보로 채워진 Error 인스턴스를 전달합니다. 다음 소스 코드는 ErrorLogModule 클래스의 관련 코드를 보여 줍니다.

public class ErrorLogModule : IHttpModule 
{
public virtual void Init(HttpApplication application)
{
application.Error += new EventHandler(OnError);
}
protected virtual ErrorLog ErrorLog
{
get { return ErrorLog.Default; }
}
protected virtual void OnError(object sender, EventArgs args)
{
HttpApplication application = (HttpApplication) sender;
LogException(application.Server.GetLastError(), application.Context);
}
protected virtual void LogException(Exception e, HttpContext context)
{
try
{ this.ErrorLog.Log(new Error(e, context)); }
catch (Exception localException)
{ Trace.WriteLine(localException); }
}
}

ErrorLogModule의 실행은 Init() 메서드에서 시작되는데, 이 메서드는 Error 이벤트가 발생할 때마다 OnError() 메서드를 호출해야 함을 ASP.NET 런타임에 표시합니다. OnError() 메서드는 HttpApplication 개체를 참조하며 LogException() 메서드를 호출하여 마지막 예외에 대한 세부 정보뿐만 아니라 특정 요청과 관련된 HttpContext 인스턴스를 전달합니다. LogException()은 간단하게 해당 ErrorLog 클래스의 Log() 메서드를 호출하여 새 Error 인스턴스를 전달합니다. Error 인스턴스의 생성자는 ExceptionHttpContext 인스턴스를 가지며 이에 따라서 속성을 채웁니다. 자세한 내용은 다운로드할 수 있는 소스 코드를 참조하십시오.

ErrorLogModule은 읽기 전용 ErrorLog 속성을 포함하며 ErrorLog.Default에 의해 반환된 ErrorLog 인스턴스를 반환합니다. DefaultErrorLog 클래스에 있는 ErrorLog 유형의 정적 속성입니다. 이 속성은 웹 응용 프로그램의 구성을 참조하여 예외 로깅에 사용할 클래스(SqlErrorLog, MemoryErrorLog 또는 사용자 지정 예외 로깅 클래스)를 결정합니다.

참고   ASP.NET 웹 응용 프로그램에 ELMAH 추가 절에서는 특정 예외 로거를 사용하도록 웹 응용 프로그램을 구성하는 방법을 검토합니다. 이 작업은 줄의 일부를 Web.config 또는 machine.config 파일에 추가하기만 하면 되므로 아주 간단합니다.

HTTP 모듈 하위 시스템의 다른 HTTP 모듈은 예외 발생 시에 관리자에게 전자 메일을 보내는 ErrorMailModule 클래스입니다. ELMAH의 이 모듈에 대해서는 여기에서 언급하지 않겠지만 이 기사에서 다운로드할 수 있는 코드 샘플에서 이 모듈을 사용하는 방법을 확인할 수 있습니다.

HTTP 처리기 하위 시스템

앞에서 언급한 것처럼 HTTP 처리기의 목적은 특정 리소스 유형의 콘텐츠를 렌더링하는 것입니다. ASP.NET HTTP 파이프라인에 요청이 들어오면 ASP.NET 엔진은 요청된 경로를 검토하여 요청된 리소스를 처리하는 데 사용해야 할 HTTP 처리기를 결정합니다. 특히 HTTP 처리기나 HTTP 처리기 팩토리에 의해 처리되는 특정 경로를 가지도록 ASP.NET 응용 프로그램을 구성할 수 있습니다. HTTP 처리기 팩토리는 콘텐츠 렌더링을 직접적으로 수행하는 것이 아니라 HTTP 처리기 인스턴스의 선택과 반환을 담당하는 클래스입니다. 요청된 리소스를 렌더링하는 작업은 반환된 이 HTTP 처리기 인스턴스가 수행합니다.

ELMAH의 HTTP 처리기 하위 시스템은 단일 HTTP 처리기 팩토리 클래스와 함께 기록된 오류를 표시하기 위해 태그를 생성하도록 설계된 여러 HTTP 처리기 클래스로 구성됩니다. HTTP 처리기 팩토리 클래스인 ErrorLogPageFactory는 요청된 URL의 PathInfo 부분을 검사하여 출력을 생성해야 하는 HTTP 처리기를 결정합니다.

참고   URL의 PathInfo 부분은 파일 이름 뒤에 오는 추가 콘텐츠이며 Request 개체의 PathInfo 속성을 통해 사용할 수 있습니다. 예를 들어 http://www.example.com/someDir/somePage.aspx/somePath URL에서 somePath는 URL의 PathInfo 부분입니다. URL의 다양한 부분에 사용되는 용어와 해당 Request 개체 속성에 대한 자세한 내용은 Rick Strahl  의 블로그 항목 Making Sense of ASP.NET Paths  를 참조하십시오.

다음 코드는 ErrorLogPageFactory HTTP 처리기 팩토리 클래스에 있는 더 흥미로운 코드를 보여 줍니다.

public class ErrorLogPageFactory : IHttpHandlerFactory 
{
public virtual IHttpHandler
GetHandler(HttpContext context,
string requestType, string url, string pathTranslated)
{
string resource =
context.Request.PathInfo.Length == 0 ? string.Empty
: context.Request.PathInfo.Substring(1);
switch (resource.ToLower(CultureInfo.InvariantCulture))
{
case "detail" : return new ErrorDetailPage();
case "html" : return new ErrorHtmlPage();
case "rss" : return new ErrorRssHandler();
default : return new ErrorLogPage();
}
}
}

위에서 알 수 있듯이 ErrorLogPageFactory 클래스의 GetHandler() 메서드는 요청의 PathInfo에 기초하여 HTTP 처리기 인스턴스를 반환합니다. PathInforss인 경우 ErrorRssHandler HTTP 처리기의 인스턴스가 반환되며 이 인스턴스는 로그를 RSS 필드로 렌더링합니다. PathInfodetail인 경우 ErrorDetailPage HTTP 처리기의 인스턴스가 반환되며 이 인스턴스는 특정 예외에 대한 정보를 표시합니다.

ASP.NET 웹 응용 프로그램의 설정에서 ErrorLogPageFactory HTTP 처리기 팩토리에 매핑할 경로를 지정해야 합니다(예: ErrorLog.aspx). 예외 로그의 RSS 피드를 보려면 http://www.example.com/ErrorLog.aspx/rss를 방문하십시오.

ELMAH의 다양한 HTTP 처리기 클래스(ErrorDetailPage, ErrorHtmlPage, ErrorRssHandler, ErrorLogPage 등)는 다른 태그를 렌더링합니다. 예를 들어 ErrorRssHandler HTTP 처리기는 15개의 최신 오류를 반복하여 이 정보를 RSS 형식으로 표시하기 위한 적절한 XML 태그를 내보냅니다. 다른 모든 HTTP 처리기는 모든 ASP.NET 코드 숨김 클래스가 파생되는 System.Web.UI.Page 클래스에서 직접 또는 간접적으로 파생됩니다. 이러한 페이지 관련 HTTP 처리기는 기록된 예외의 페이징 가능한 목록을 표시하는 HTML 인터페이스를 만들기 위해 Page 클래스의 Render()OnLoad() 메서드를 무시합니다. 이러한 페이지의 스크린샷인 그림 1, 2 및 3을 다시 참조하십시오.

참고   Error 클래스가 ServerVariables, QueryString, FormCookie 컬렉션을 저장하지만 ServerVariables 컬렉션만 예외의 세부 정보에 표시됩니다. 이는 QueryString 매개 변수와 쿠키를 각각 ServerVariableQUERY_STRINGHTTP_COOKIE 매개 변수를 통해 볼 수 있기 때문입니다. Form 컬렉션은 생략되는데, 이는 대부분의 진단에서 거의 도움이 되지 않는 수십 KB의 뷰 상태 정보가 잠재적으로 이 컬렉션에 포함될 수 있기 때문입니다. 물론 원할 경우에는 HTTP 처리기 세부 정보를 간단하게 수정하여 이 정보를 포함할 수 있습니다.

이제 ELMAH의 세 가지 하위 시스템을 검토했으므로 ELMAH를 기존 ASP.NET 웹 응용 프로그램에 추가하는 방법을 살펴보겠습니다. 특히 ELMAH는 HTTP 처리기와 모듈이 제공하는 구성 요소화의 이점으로 인해 임의의 사이트에 매우 간단하게 추가할 수 있습니다.

ASP.NET 웹 응용 프로그램에 ELMAH 추가

ELMAH를 ASP.NET 웹 응용 프로그램에 추가하는 것은 매우 간단하며 다음 두 단계로 구성됩니다.

  • 웹 응용 프로그램에 ELMAH 어셈블리 추가
  • ELMAH의 HTTP 모듈과 HTTP 처리기를 사용하도록 웹 응용 프로그램 구성

어셈블리를 웹 응용 프로그램의 /bin 디렉터리에 복사하고 Web.config 파일을 통해 ELMAH의 설정을 구성하여 ELMAH를 웹 서버의 특정 웹 응용 프로그램에 적

Posted by tornado
|