ASP.NET 오류 처리

작성 자: 에릭 레이탄

Wingtip Toys 샘플 프로젝트 다운로드(C#) 또는 전자책 다운로드(PDF)

이 자습서 시리즈에서는 ASP.NET 4.5 및 웹용 Microsoft Visual Studio Express 2013을 사용하여 ASP.NET Web Forms 애플리케이션을 빌드하는 기본 사항을 설명합니다. C# 소스 코드가 포함된 Visual Studio 2013 프로젝트는 이 자습서 시리즈와 함께 사용할 수 있습니다.

이 자습서에서는 오류 처리 및 오류 로깅을 포함하도록 Wingtip Toys 샘플 애플리케이션을 수정합니다. 오류 처리를 통해 애플리케이션은 오류를 정상적으로 처리하고 그에 따라 오류 메시지를 표시할 수 있습니다. 오류 로깅을 사용하면 발생한 오류를 찾아 수정할 수 있습니다. 이 자습서는 이전 자습서 "URL 라우팅"을 기반으로 하며 Wingtip Toys 자습서 시리즈의 일부입니다.

학습할 내용:

  • 애플리케이션의 구성에 전역 오류 처리를 추가하는 방법입니다.
  • 애플리케이션, 페이지 및 코드 수준에서 오류 처리를 추가하는 방법입니다.
  • 나중에 검토할 수 있도록 오류를 기록하는 방법입니다.
  • 보안을 손상시키지 않는 오류 메시지를 표시하는 방법입니다.
  • ELMAH(오류 로깅 모듈 및 처리기) 오류 로깅을 구현하는 방법입니다.

개요

ASP.NET 애플리케이션은 일관된 방식으로 실행 중에 발생하는 오류를 처리할 수 있어야 합니다. ASP.NET CLR(공용 언어 런타임)을 사용하여 애플리케이션에 오류를 균일한 방식으로 알리는 방법을 제공합니다. 오류가 발생하면 예외가 발생합니다. 예외는 애플리케이션에서 발생하는 오류, 조건 또는 예기치 않은 동작입니다.

.NET Framework에서 예외는 System.Exception 클래스에서 상속되는 객체입니다. 문제가 발생한 코드 영역에서 예외가 throw됩니다. 예외는 애플리케이션이 예외를 처리하는 코드를 제공하는 위치에 호출 스택까지 전달됩니다. 애플리케이션이 예외를 처리하지 않으면 브라우저에서 오류 세부 정보를 표시해야 합니다.

권장되는 방법으로, 코드 수준에서 Try/Catch/Finally 블록 내에서 오류를 처리하세요. 사용자가 발생하는 컨텍스트에서 문제를 해결할 수 있도록 이러한 블록을 배치해 봅니다. 오류 처리 블록이 오류가 발생한 위치와 너무 멀리 떨어져 있으면 사용자에게 문제를 해결하는 데 필요한 정보를 제공하기가 더 어려워집니다.

Exception 클래스

Exception 클래스는 예외가 상속하는 기본 클래스입니다. 대부분의 예외 개체는 SystemException 클래스, IndexOutOfRangeException 클래스, ArgumentNullException 클래스와 같은 Exception 클래스의 파생된 클래스의 인스턴스입니다. Exception 클래스에는 발생한 오류에 대한 특정 정보를 제공하는 StackTrace 속성, InnerException 속성, 그리고 Message 속성이 있습니다.

예외 상속 계층 구조

런타임에는 SystemException 클래스로부터 파생되며, 런타임이 예외를 만났을 때 던지는 기본 예외 집합이 있습니다. IndexOutOfRangeException 클래스 및 ArgumentNullException 클래스와 같은 대부분의 클래스는 Exception 클래스를 상속받으며 추가 멤버를 구현하지 않습니다. 따라서 예외에 대한 가장 중요한 정보는 예외 계층 구조, 예외 이름 및 예외에 포함된 정보를 찾을 수 있습니다.

예외 처리 계층 구조

ASP.NET Web Forms 애플리케이션에서는 특정 처리 계층 구조에 따라 예외를 처리할 수 있습니다. 예외는 다음 수준에서 처리할 수 있습니다.

  • 애플리케이션 수준
  • 페이지 수준
  • 코드 수준

애플리케이션이 예외를 처리할 때 Exception 클래스에서 상속된 예외에 대한 추가 정보를 검색하여 사용자에게 표시할 수 있습니다. 애플리케이션, 페이지 및 코드 수준 외에도 HTTP 모듈 수준에서 IIS 사용자 지정 처리기를 사용하여 예외를 처리할 수도 있습니다.

애플리케이션 수준 오류 처리

애플리케이션의 구성을 수정하거나 애플리케이션의 Application_Error 파일에 처리기를 추가하여 애플리케이션 수준에서 기본 오류를 처리할 수 있습니다.

customErrors 파일에 섹션을 추가하여 기본 오류 및 HTTP 오류를 처리할 수 있습니다. 이 섹션에서는 customErrors 오류가 발생할 때 사용자에게 리디렉션되는 기본 페이지를 지정할 수 있습니다. 또한 특정 상태 코드 오류에 대한 개별 페이지를 지정할 수 있습니다.

<configuration>
  <system.web>
    <customErrors mode="On" defaultRedirect="ErrorPage.aspx?handler=customErrors%20section%20-%20Web.config">
      <error statusCode="404" redirect="ErrorPage.aspx?msg=404&amp;handler=customErrors%20section%20-%20Web.config"/>
    </customErrors>
  </system.web>
</configuration>

아쉽게도 구성을 사용하여 사용자를 다른 페이지로 리디렉션하는 경우 발생한 오류에 대한 세부 정보가 없습니다.

그러나 Application_Error 파일의 처리기에 코드를 추가하여 애플리케이션의 어디에서나 발생하는 오류를 트래핑할 수 있습니다.

void Application_Error(object sender, EventArgs e)
{
    Exception exc = Server.GetLastError();

    if (exc is HttpUnhandledException)
    {
        // Pass the error on to the error page.
        Server.Transfer("ErrorPage.aspx?handler=Application_Error%20-%20Global.asax", true);
    }
}

페이지 수준 오류 이벤트 처리

페이지 수준 처리기는 오류가 발생한 페이지로 사용자를 반환하지만 컨트롤 인스턴스가 유지 관리되지 않으므로 페이지에 더 이상 아무 것도 없습니다. 애플리케이션 사용자에게 오류 세부 정보를 제공하려면 오류 세부 정보를 페이지에 구체적으로 작성해야 합니다.

일반적으로 페이지 수준 오류 처리기를 사용하여 처리되지 않은 오류를 기록하거나 유용한 정보를 표시할 수 있는 페이지로 사용자를 데려다 줍니다.

이 코드 예제에서는 ASP.NET 웹 페이지에서 Error 이벤트에 대한 처리기를 보여 드립니다. 페이지의 try/catch 블록 내에서 아직 처리되지 않은 모든 예외를 이 처리기가 catch합니다.

private void Page_Error(object sender, EventArgs e)
{
    Exception exc = Server.GetLastError();

    // Handle specific exception.
    if (exc is HttpUnhandledException)
    {
        ErrorMsgTextBox.Text = "An error occurred on this page. Please verify your " +                  
        "information to resolve the issue."
    }
    // Clear the error from the server.
    Server.ClearError();
}

오류를 처리한 후에는 Server 개체(ClearError클래스)의 메서드를 호출 HttpServerUtility 하여 오류를 지워야 합니다. 그렇지 않으면 이전에 발생한 오류가 표시됩니다.

코드 수준 오류 처리

try-catch 문은 try 블록과 다른 예외에 대한 처리기를 지정하는 하나 이상의 catch 절로 구성됩니다. 예외가 throw되면 CLR(공용 언어 런타임)은 이 예외를 처리하는 catch 문을 찾습니다. 현재 실행 중인 메서드에 catch 블록이 없는 경우 CLR은 현재 메서드를 호출한 메서드를 조회하고 호출 스택을 위로 켭니다. catch 블록이 없으면 CLR은 처리되지 않은 예외 메시지를 사용자에게 표시하고 프로그램 실행을 중지합니다.

다음 코드 예제에서는 오류를 처리하는 일반적인 방법을 try/catch/finally 보여줍니다.

try
{
    file.ReadBlock(buffer, index, buffer.Length);
}
catch (FileNotFoundException e)
{
    Server.Transfer("NoFileErrorPage.aspx", true);
}
catch (System.IO.IOException e)
{
    Server.Transfer("IOErrorPage.aspx", true);
}

finally
{
    if (file != null)
    {
        file.Close();
    }
}

위의 코드에서 try 블록에는 가능한 예외에 대해 보호해야 하는 코드가 포함되어 있습니다. 예외가 throw되거나 블록이 성공적으로 완료될 때까지 블록이 실행됩니다. FileNotFoundException 예외 또는 예외가 IOException 발생하면 실행이 다른 페이지로 전송됩니다. 그런 다음, 오류가 발생했는지 여부에 관계없이 최종 블록에 포함된 코드가 실행됩니다.

오류 로깅 지원 추가

Wingtip Toys 샘플 애플리케이션에 오류 처리를 추가하기 전에 ExceptionUtility 폴더에 클래스를 추가하여 오류 로깅 지원을 추가합니다. 이렇게 하면 애플리케이션에서 오류를 처리할 때마다 오류 세부 정보가 오류 로그 파일에 추가됩니다.

  1. 논리 폴더를 마우스 오른쪽 단추로 클릭한 다음 ,새> 추가를 선택합니다.
    새 항목 추가 대화 상자가 표시됩니다.

  2. 왼쪽에서 Visual C# ->Code 템플릿 그룹을 선택합니다. 그런 다음 중간 목록에서 클래스를 선택하고 이름을 ExceptionUtility.cs.

  3. 추가를 선택합니다. 새 클래스 파일이 표시됩니다.

  4. 기존 코드를 다음으로 바꿉니다.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.IO;
    
    namespace WingtipToys.Logic
    {
      // Create our own utility for exceptions
      public sealed class ExceptionUtility
      {
        // All methods are static, so this can be private
        private ExceptionUtility()
        { }
    
        // Log an Exception
        public static void LogException(Exception exc, string source)
        {
          // Include logic for logging exceptions
          // Get the absolute path to the log file
          string logFile = "~/App_Data/ErrorLog.txt";
          logFile = HttpContext.Current.Server.MapPath(logFile);
    
          // Open the log file for append and write the log
          StreamWriter sw = new StreamWriter(logFile, true);
          sw.WriteLine("********** {0} **********", DateTime.Now);
          if (exc.InnerException != null)
          {
            sw.Write("Inner Exception Type: ");
            sw.WriteLine(exc.InnerException.GetType().ToString());
            sw.Write("Inner Exception: ");
            sw.WriteLine(exc.InnerException.Message);
            sw.Write("Inner Source: ");
            sw.WriteLine(exc.InnerException.Source);
            if (exc.InnerException.StackTrace != null)
            {
              sw.WriteLine("Inner Stack Trace: ");
              sw.WriteLine(exc.InnerException.StackTrace);
            }
          }
          sw.Write("Exception Type: ");
          sw.WriteLine(exc.GetType().ToString());
          sw.WriteLine("Exception: " + exc.Message);
          sw.WriteLine("Source: " + source);
          sw.WriteLine("Stack Trace: ");
          if (exc.StackTrace != null)
          {
            sw.WriteLine(exc.StackTrace);
            sw.WriteLine();
          }
          sw.Close();
        }
      }
    }
    

예외가 발생하면 메서드를 호출하여 예외 로그 파일에 예외를 LogException 쓸 수 있습니다. 이 메서드는 예외 개체와 예외 원본에 대한 세부 정보가 포함된 문자열이라는 두 개의 매개 변수를 사용합니다. 예외 로그는 App_Data 폴더의 ErrorLog.txt 파일에 기록됩니다.

오류 페이지 추가

Wingtip Toys 샘플 애플리케이션에서는 오류를 표시하는 데 한 페이지가 사용됩니다. 오류 페이지는 사이트의 사용자에게 보안 오류 메시지를 표시하도록 설계되었습니다. 그러나 사용자가 코드가 있는 컴퓨터에서 로컬로 제공되는 HTTP 요청을 만드는 개발자인 경우 오류 페이지에 추가 오류 세부 정보가 표시됩니다.

  1. 솔루션 탐색기에서 프로젝트 이름(Wingtip Toys)을 마우스 오른쪽 단추로 클릭하고 새 항목>를 선택합니다.
    새 항목 추가 대화 상자가 표시됩니다.

  2. 왼쪽에서 Visual C# ->Web 템플릿 그룹을 선택합니다. 가운데 목록에서 마스터 페이지가 있는 웹 양식을 선택하고 이름을 ErrorPage.aspx.

  3. 추가를 클릭합니다.

  4. Site.Master 파일을 마스터 페이지로 선택한 다음 확인을 선택합니다.

  5. 기존 태그를 다음으로 바꿉다.

    <%@ Page Title="" Language="C#" AutoEventWireup="true" MasterPageFile="~/Site.Master"  CodeBehind="ErrorPage.aspx.cs" Inherits="WingtipToys.ErrorPage" %>
    <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
        <h2>Error:</h2>
        <p></p>
        <asp:Label ID="FriendlyErrorMsg" runat="server" Text="Label" Font-Size="Large" style="color: red"></asp:Label>
    
        <asp:Panel ID="DetailedErrorPanel" runat="server" Visible="false">
            <p>&nbsp;</p>
            <h4>Detailed Error:</h4>
            <p>
                <asp:Label ID="ErrorDetailedMsg" runat="server" Font-Size="Small" /><br />
            </p>
    
            <h4>Error Handler:</h4>
            <p>
                <asp:Label ID="ErrorHandler" runat="server" Font-Size="Small" /><br />
            </p>
    
            <h4>Detailed Error Message:</h4>
            <p>
                <asp:Label ID="InnerMessage" runat="server" Font-Size="Small" /><br />
            </p>
            <p>
                <asp:Label ID="InnerTrace" runat="server"  />
            </p>
        </asp:Panel>
    </asp:Content>
    
  6. 다음과 같이 표시되도록 코드 숨김(ErrorPage.aspx.cs)의 기존 코드를 바꿉니다.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using WingtipToys.Logic;
    
    namespace WingtipToys
    {
      public partial class ErrorPage : System.Web.UI.Page
      {
        protected void Page_Load(object sender, EventArgs e)
        {
          // Create safe error messages.
          string generalErrorMsg = "A problem has occurred on this web site. Please try again. " +
              "If this error continues, please contact support.";
          string httpErrorMsg = "An HTTP error occurred. Page Not found. Please try again.";
          string unhandledErrorMsg = "The error was unhandled by application code.";
    
          // Display safe error message.
          FriendlyErrorMsg.Text = generalErrorMsg;
    
          // Determine where error was handled.
          string errorHandler = Request.QueryString["handler"];
          if (errorHandler == null)
          {
            errorHandler = "Error Page";
          }
    
          // Get the last error from the server.
          Exception ex = Server.GetLastError();
    
          // Get the error number passed as a querystring value.
          string errorMsg = Request.QueryString["msg"];
          if (errorMsg == "404")
          {
            ex = new HttpException(404, httpErrorMsg, ex);
            FriendlyErrorMsg.Text = ex.Message;
          }
    
          // If the exception no longer exists, create a generic exception.
          if (ex == null)
          {
            ex = new Exception(unhandledErrorMsg);
          }
    
          // Show error details to only you (developer). LOCAL ACCESS ONLY.
          if (Request.IsLocal)
          {
            // Detailed Error Message.
            ErrorDetailedMsg.Text = ex.Message;
    
            // Show where the error was handled.
            ErrorHandler.Text = errorHandler;
    
            // Show local access details.
            DetailedErrorPanel.Visible = true;
    
            if (ex.InnerException != null)
            {
              InnerMessage.Text = ex.GetType().ToString() + "<br/>" +
                  ex.InnerException.Message;
              InnerTrace.Text = ex.InnerException.StackTrace;
            }
            else
            {
              InnerMessage.Text = ex.GetType().ToString();
              if (ex.StackTrace != null)
              {
                InnerTrace.Text = ex.StackTrace.ToString().TrimStart();
              }
            }
          }
    
          // Log the exception.
          ExceptionUtility.LogException(ex, errorHandler);
    
          // Clear the error from the server.
          Server.ClearError();
        }
      }
    }
    

오류 페이지가 표시 Page_Load 되면 이벤트 처리기가 실행됩니다. Page_Load 처리기에서 오류가 처음 처리된 위치가 결정됩니다. 그런 다음, 발생한 마지막 오류는 서버 개체의 메서드를 GetLastError 호출하여 결정됩니다. 예외가 더 이상 없으면 제네릭 예외가 만들어집니다. 그런 다음 HTTP 요청이 로컬로 이루어진 경우 모든 오류 세부 정보가 표시됩니다. 이 경우 웹 애플리케이션을 실행하는 로컬 컴퓨터만 이러한 오류 세부 정보를 볼 수 있습니다. 오류 정보가 표시되면 오류가 로그 파일에 추가되고 서버에서 오류가 지워집니다.

애플리케이션에 대해 처리되지 않은 오류 메시지 표시

customErrors 파일에 섹션을 추가 하면 애플리케이션 전체에서 발생하는 간단한 오류를 신속하게 처리할 수 있습니다. 상태 코드 값(예: 404 - 파일을 찾을 수 없음)에 따라 오류를 처리하는 방법을 지정할 수도 있습니다.

구성 업데이트

customErrors 파일에 섹션을 추가하여 구성을 업데이트합니다.

  1. 솔루션 탐색기에서 Wingtip Toys 샘플 애플리케이션의 루트에서 Web.config 파일을 찾아 엽니다.

  2. customErrors 섹션을 <system.web> 노드 내의 Web.config 파일에 다음과 같이 추가합니다.

    <configuration>
      <system.web>
        <customErrors mode="On" defaultRedirect="ErrorPage.aspx?handler=customErrors%20section%20-%20Web.config">
          <error statusCode="404" redirect="ErrorPage.aspx?msg=404&amp;handler=customErrors%20section%20-%20Web.config"/>
        </customErrors>
      </system.web>
    </configuration>
    
  3. Web.config 파일을 저장합니다.

섹션은 customErrors "On"으로 설정된 모드를 지정합니다. 또한 애플리케이션에 defaultRedirect오류가 발생할 때 탐색할 페이지를 알려주는 를 지정합니다. 또한 페이지를 찾을 수 없을 때 404 오류를 처리하는 방법을 지정하는 특정 오류 요소를 추가했습니다. 이 자습서의 뒷부분에서는 애플리케이션 수준에서 오류의 세부 정보를 캡처하는 추가 오류 처리를 추가합니다.

애플리케이션 실행하기

이제 애플리케이션을 실행하여 업데이트된 경로를 볼 수 있습니다.

  1. F5 키를 눌러 Wingtip Toys 샘플 애플리케이션을 실행합니다.
    브라우저가 열리고 Default.aspx 페이지가 표시됩니다.

  2. 브라우저에 다음 URL 주소를 입력합니다(반드시 사용자 의 포트 번호를 사용해야 합니다.).
    https://localhost:44300/NoPage.aspx

  3. 브라우저에 표시되는 ErrorPage.aspx 검토합니다.

    ASP.NET 오류 처리 - 페이지를 찾을 수 없음 오류

존재하지 않는 NoPage.aspx 페이지를 요청하면 추가 세부 정보를 사용할 수 있는 경우 오류 페이지에 간단한 오류 메시지와 자세한 오류 정보가 표시됩니다. 그러나 사용자가 원격 위치에서 존재하지 않는 페이지를 요청한 경우 오류 페이지에는 오류 메시지만 빨간색으로 표시됩니다.

테스트용 예외 포함

오류가 발생할 때 애플리케이션이 어떻게 작동하는지 확인하려면 ASP.NET 의도적으로 오류 조건을 만들 수 있습니다. Wingtip Toys 샘플 애플리케이션에서는 기본 페이지가 로드될 때 테스트 예외를 throw하여 어떤 일이 발생하는지 확인합니다.

  1. Visual Studio에서 Default.aspx 페이지의 코드 비하인드 파일을 엽니다.
    Default.aspx.cs 코드 숨김 페이지가 표시됩니다.

  2. Page_Load 처리기에서 처리기가 다음과 같이 표시되도록 코드를 추가합니다.

    protected void Page_Load(object sender, EventArgs e)
    {
        throw new InvalidOperationException("An InvalidOperationException " +
        "occurred in the Page_Load handler on the Default.aspx page.");
    }
    

다양한 유형의 예외를 만들 수 있습니다. 위의 코드에서는 Default.aspx 페이지가 로드될 때 InvalidOperationException를 생성합니다.

애플리케이션 실행하기

애플리케이션을 실행하여 애플리케이션에서 예외를 처리하는 방법을 확인할 수 있습니다.

  1. Ctrl+F5를 눌러 Wingtip Toys 샘플 애플리케이션을 실행합니다.
    애플리케이션이 InvalidOperationException을 throw합니다.

    메모

    Visual Studio에서 오류의 원본을 보려면 코드에 침입하지 않고 페이지를 표시하려면 Ctrl+F5 를 눌러야 합니다.

  2. 브라우저에 표시되는 ErrorPage.aspx 검토합니다.

    ASP.NET 오류 처리 - 오류 페이지

오류 세부 정보에서 볼 수 있듯이 예외는 customError 파일의 섹션에 의해 트래핑되었습니다.

Application-Level 오류 처리 추가

예외에 대한 정보가 거의 없는 customErrors 파일의 섹션을 사용하여 예외를 트래핑하는 대신 애플리케이션 수준에서 오류를 트래핑하고 오류 세부 정보를 검색할 수 있습니다.

  1. 솔루션 탐색기에서 Global.asax.cs 파일을 찾아 엽니다.

  2. 다음과 같이 표시되도록 Application_Error 처리기를 추가합니다.

    void Application_Error(object sender, EventArgs e)
    {
      // Code that runs when an unhandled error occurs.
    
      // Get last error from the server
      Exception exc = Server.GetLastError();
    
      if (exc is HttpUnhandledException)
      {
        if (exc.InnerException != null)
        {
          exc = new Exception(exc.InnerException.Message);
          Server.Transfer("ErrorPage.aspx?handler=Application_Error%20-%20Global.asax",
              true);
        }
      }
    }
    

애플리케이션 Application_Error 에서 오류가 발생하면 처리기가 호출됩니다. 이 처리기에서 마지막 예외가 검색되고 검토됩니다. 예외가 처리되지 않았고 예외에 내부 예외 세부 정보(즉, InnerException null이 아님)가 포함된 경우 애플리케이션은 예외 세부 정보가 표시되는 오류 페이지로 실행을 전송합니다.

애플리케이션 실행하기

애플리케이션 수준에서 예외를 처리하여 제공된 추가 오류 세부 정보를 보려면 애플리케이션을 실행할 수 있습니다.

  1. Ctrl+F5를 눌러 Wingtip Toys 샘플 애플리케이션을 실행합니다.
    애플리케이션이 InvalidOperationException 을 던집니다.

  2. 브라우저에 표시되는 ErrorPage.aspx 검토합니다.

    ASP.NET 오류 처리 - 애플리케이션 수준 오류

Page-Level 오류 처리 추가

페이지 지시문의 @PageErrorPage 특성을 추가하거나 페이지의 코드 숨김에 Page_Error 이벤트 처리기를 추가하여 페이지에 페이지 수준 오류를 처리할 수 있습니다. 이 섹션에서는 Page_Error 페이지로 전송하는 이벤트 처리기를 추가 합니다.

  1. 솔루션 탐색기에서 Default.aspx.cs 파일을 찾아 엽니다.

  2. Page_Error 코드-비하인드가 다음과 같이 나타나도록 핸들러를 추가합니다.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    namespace WingtipToys
    {
      public partial class _Default : Page
      {
        protected void Page_Load(object sender, EventArgs e)
        {
          throw new InvalidOperationException("An InvalidOperationException " +
          "occurred in the Page_Load handler on the Default.aspx page.");
        }
    
        private void Page_Error(object sender, EventArgs e)
        {
          // Get last error from the server.
          Exception exc = Server.GetLastError();
    
          // Handle specific exception.
          if (exc is InvalidOperationException)
          {
            // Pass the error on to the error page.
            Server.Transfer("ErrorPage.aspx?handler=Page_Error%20-%20Default.aspx",
                true);
          }
        }
      }
    }
    

페이지에서 Page_Error 오류가 발생하면 이벤트 처리기가 호출됩니다. 이 처리기에서 마지막 예외가 검색되고 검토됩니다. InvalidOperationException 이 경우 Page_Error 이벤트 처리기는 예외 세부 정보가 표시되는 오류 페이지로 실행을 전송합니다.

애플리케이션 실행하기

이제 애플리케이션을 실행하여 업데이트된 경로를 볼 수 있습니다.

  1. Ctrl+F5를 눌러 Wingtip Toys 샘플 애플리케이션을 실행합니다.
    애플리케이션이 InvalidOperationException를 던집니다.

  2. 브라우저에 표시되는 ErrorPage.aspx 검토합니다.

    ASP.NET 오류 처리 - 페이지 수준 오류

  3. 브라우저 창을 닫습니다.

테스트에 사용되는 예외 제거

이 자습서에서 이전에 추가한 예외를 발생시키지 않고 Wingtip Toys 샘플 애플리케이션이 정상적으로 작동하도록 하려면, 예외를 제거하십시오.

  1. Default.aspx 페이지의 코드-비하인드를 엽니다.

  2. 다음과 같이 처리기가 나타나도록 Page_Load 처리기에서 예외를 발생시키는 코드를 제거합니다.

    protected void Page_Load(object sender, EventArgs e)
    {
    
    }
    

코드 수준 오류 로깅 추가

이 자습서의 앞부분에서 설명한 것처럼 try/catch 문을 추가하여 코드 섹션을 실행하고 발생하는 첫 번째 오류를 처리할 수 있습니다. 이 예제에서는 오류 세부 정보만 오류 로그 파일에 기록하여 나중에 오류를 검토할 수 있도록 합니다.

  1. 솔루션 탐색기의논리 폴더에서 PayPalFunctions.cs 파일을 찾아 엽니다.

  2. 코드가 HttpCall 다음과 같이 표시되도록 메서드를 업데이트합니다.

    public string HttpCall(string NvpRequest)
    {
      string url = pEndPointURL;
    
      string strPost = NvpRequest + "&" + buildCredentialsNVPString();
      strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode(BNCode);
    
      HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
      objRequest.Timeout = Timeout;
      objRequest.Method = "POST";
      objRequest.ContentLength = strPost.Length;
    
      try
      {
        using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
        {
          myWriter.Write(strPost);
        }
      }
      catch (Exception e)
      {
        // Log the exception.
        WingtipToys.Logic.ExceptionUtility.LogException(e, "HttpCall in PayPalFunction.cs");
      }
    
      //Retrieve the Response returned from the NVP API call to PayPal.
      HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
      string result;
      using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
      {
        result = sr.ReadToEnd();
      }
    
      return result;
    }
    

위의 코드는 클래스에 LogException 포함된 메서드를 호출합니다 ExceptionUtility . 이 자습서의 앞부분에서 논리 폴더에 ExceptionUtility.cs 클래스 파일을 추가했습니다. 이 메서드는 LogException 두 개의 매개 변수를 사용합니다. 첫 번째 매개 변수는 예외 개체입니다. 두 번째 매개 변수는 오류의 원인을 인식하는 데 사용되는 문자열입니다.

오류 로깅 정보 검사

앞에서 설명한 대로 오류 로그를 사용하여 먼저 수정해야 하는 애플리케이션의 오류를 확인할 수 있습니다. 물론 오류 로그에 갇혀 기록된 오류만 기록됩니다.

  1. 솔루션 탐색기에서 App_Data 폴더에서ErrorLog.txt 파일을 찾아 엽니다.
    ErrorLog.txt 파일을 보려면 솔루션 탐색기 위쪽에서 "모든 파일 표시" 옵션 또는 "새로 고침" 옵션을 선택해야 할 수 있습니다.

  2. Visual Studio에 표시되는 오류 로그를 검토합니다.

    ASP.NET 오류 처리 - ErrorLog.txt

안전한 오류 메시지

애플리케이션에서 오류 메시지를 표시 때 악의적인 사용자가 애플리케이션을 공격하는 데 도움이 될 수 있는 정보를 제공하지 않아야 합니다. 예를 들어 애플리케이션이 데이터베이스에 쓰기를 시도하는 데 실패한 경우 사용 중인 사용자 이름을 포함하는 오류 메시지를 표시해서는 안 됩니다. 이러한 이유로 일반 오류 메시지가 빨간색으로 사용자에게 표시됩니다. 모든 추가 오류 세부 정보는 로컬 컴퓨터의 개발자에게만 표시됩니다.

ELMAH 사용

ELMAH(오류 로깅 모듈 및 처리기)는 nuGet 패키지로 ASP.NET 애플리케이션에 연결하는 오류 로깅 기능입니다. ELMAH는 다음과 같은 기능을 제공합니다.

  • 처리되지 않은 예외의 로깅입니다.
  • 다시 코딩된 처리되지 않은 예외의 전체 로그를 볼 수 있는 웹 페이지입니다.
  • 기록된 각 예외의 전체 세부 정보를 볼 수 있는 웹 페이지입니다.
  • 발생한 각 오류에 대한 이메일 알림입니다.
  • 로그의 마지막 15개 오류에 대한 RSS 피드입니다.

ELMAH로 작업하려면 먼저 설치해야 합니다. NuGet 패키지 설치 관리자를 쉽게 사용할 수 있습니다. 이 자습서 시리즈의 앞부분에서 설명한 것처럼 NuGet은 Visual Studio에서 오픈 소스 라이브러리 및 도구를 쉽게 설치하고 업데이트할 수 있는 Visual Studio 확장입니다.

  1. Visual Studio 내의 도구 메뉴에서 NuGet 패키지 관리자>솔루션용 NuGet 패키지 관리를 선택합니다.

    ASP.NET 오류 처리 - 솔루션용 NuGet 패키지 관리

  2. NuGet 패키지 관리 대화 상자가 Visual Studio 내에 표시됩니다.

  3. NuGet 패키지 관리 대화 상자에서 왼쪽에서 온라인을 확장한 다음, nuget.org 선택합니다. 그런 다음, 온라인으로 사용 가능한 패키지 목록에서 ELMAH 패키지를 찾아 설치합니다.

    ASP.NET 오류 처리 - ELMA NuGet 패키지

  4. 패키지를 다운로드하려면 인터넷에 연결되어 있어야 합니다.

  5. 프로젝트 선택 대화 상자에서 WingtipToys 선택 영역이 선택되어 있는지 확인한 다음 확인을 클릭합니다.

    ASP.NET 오류 처리 - 프로젝트 선택 대화 상자

  6. 필요한 경우 NuGet 패키지 관리 대화 상자에서 기를 클릭합니다.

  7. Visual Studio에서 열려 있는 파일을 다시 로드하도록 요청하는 경우 "모두 예"를 선택합니다.

  8. ELMAH 패키지는 프로젝트의 루트에 있는 Web.config 파일에 자체 항목을 추가합니다. Visual Studio에서 수정된 Web.config 파일을 다시 로드할지 묻는 메시지가 표시되면 [예]를 클릭합니다.

ELMAH는 이제 발생하는 처리되지 않은 오류를 저장할 준비가 되었습니다.

ELMAH 로그 보기

ELMAH 로그를 보는 것은 쉽지만 먼저 ELMAH 로그에 기록될 처리되지 않은 예외를 만듭니다.

  1. Ctrl+F5를 눌러 Wingtip Toys 샘플 애플리케이션을 실행합니다.

  2. 처리되지 않은 예외를 ELMAH 로그에 쓰려면 브라우저에서 다음 URL(포트 번호 사용)로 이동합니다.
    https://localhost:44300/NoPage.aspx 오류 페이지가 표시됩니다.

  3. ELMAH 로그를 표시하려면 브라우저에서 다음 URL(포트 번호 사용)로 이동합니다.
    https://localhost:44300/elmah.axd

    ASP.NET 오류 처리 - ELMAH 오류 로그

요약

이 자습서에서는 애플리케이션 수준, 페이지 수준 및 코드 수준에서 오류를 처리하는 방법을 알아보았습니다. 또한 나중에 검토할 수 있도록 처리된 오류와 처리되지 않은 오류를 기록하는 방법도 알아보았습니다. NuGet을 사용하여 애플리케이션에 예외 로깅 및 알림을 제공하기 위해 ELMAH 유틸리티를 추가했습니다. 또한 안전한 오류 메시지의 중요성에 대해 알아보았습니다.

자습서 시리즈 결론

함께 따라 주셔서 감사합니다. 이 자습서 집합이 ASP.NET Web Forms에 익숙해지는 데 도움이 되기를 바랍니다. ASP.NET 4.5 및 Visual Studio 2013에서 사용할 수 있는 Web Forms 기능에 대한 자세한 내용은 ASP.NET 및 Web Tools for Visual Studio 2013 릴리스 정보를 참조하세요. 또한 다음 단계 섹션에 언급된 자습서를 꼭 확인하시고, 무료 Azure 평가판을 반드시 사용해 보세요.

감사합니다 - 에릭

다음 단계

Microsoft Azure에 웹 애플리케이션을 배포하는 방법에 대한 자세한 내용은 Azure 웹 사이트에 멤버 자격, OAuth 및 SQL Database를 사용하여 보안 ASP.NET Web Forms 앱 배포를 참조하세요.

무료 평가판

Microsoft Azure - 평가판
Microsoft Azure에 웹 사이트를 게시하면 시간, 유지 관리 및 비용이 절약됩니다. Azure에 웹앱을 배포하는 빠른 프로세스입니다. 웹앱을 유지 관리하고 모니터링해야 하는 경우 Azure는 다양한 도구와 서비스를 제공합니다. Azure에서 데이터, 트래픽, ID, 백업, 메시징, 미디어 및 성능을 관리합니다. 그리고 이 모든 것은 매우 비용 효율적인 접근 방식으로 제공됩니다.

추가 리소스

ASP.NET 상태 모니터링을 사용하여 오류 세부 정보 로깅
Elmah

감사의 말

이 자습서 시리즈의 콘텐츠에 크게 기여한 다음 사람들에게 감사드립니다.

커뮤니티 기여