ASP.NET Core의 오류 처리 살펴보기

등록일시: 2017-06-14 08:00,  수정일시: 2017-10-21 13:35
조회수: 5,206
이 문서는 ASP.NET Core 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.
본문에서는 ASP.NET Core 응용 프로그램에서 예외가 발생했을 때 예외를 처리하는 방법을 살펴봅니다.

ASP.NET Core 응용 프로그램에서 오류가 발생할 경우, 본문에서 설명하는 다양한 방법으로 오류를 처리할 수 있습니다.

예제 코드 살펴보기 및 다운로드

개발자 예외 페이지

개발 환경에서 예외가 발생했을 때, 자세한 예외 정보를 제공해주는 오류 페이지를 표시하도록 응용 프로그램을 구성하려면, 먼저 Microsoft.AspNetCore.Diagnostics NuGet 패키지를 설치한 다음, Startup 클래스의 Configure 메서드에 다음과 같이 코드를 추가합니다:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole();
    env.EnvironmentName = EnvironmentName.Production;

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/error");
    }

이때, app.UseMvc 확장 메서드 같은, 예외를 처리하고자 하는 미들웨어에 대한 모든 확장 메서드보다 UseDeveloperExceptionPage 메서드를 먼저 호출해야 합니다.

경고

응용 프로그램이 개발 환경에서 실행될 때만 개발자 예외 페이지를 사용하도록 구성하시기 바랍니다. 응용 프로그램이 운영 환경에서 실행될 때조차 공개적으로 상세한 예외 정보를 노출하고 싶지는 않을 것입니다. 다양한 환경에서 작업하는 방법에 대해서 더 자세히 알아보시기 바랍니다.

개발자 예외 페이지를 확인해보려면, 예제 응용 프로그램의 환경을 Development로 설정하고 실행한 다음, 응용 프로그램의 기본 URL에 ?throw=true를 추가하면 됩니다. 개발자 예외 페이지는 예외 및 요청에 관한 정보가 담긴 몇 가지 탭을 제공합니다. 먼저 첫 번째 탭에는 스택 추적 (Stack Trace) 정보가 담겨 있습니다.

그리고 두 번째 탭에는 쿼리 문자열 매개 변수가 존재할 경우 표시됩니다.

이번 요청에는 쿠키가 존재하지 않지만, 존재할 경우에는 Cookies 탭에 표시됩니다. 그리고 마지막 탭에서는 전달된 헤더를 확인할 수 있습니다.

사용자 지정 예외 처리 페이지 구성하기

응용 프로그램이 Development 환경에서 실행되지 않을 때는 예외 처리기 페이지를 구성해서 활용하는 것이 좋습니다.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole();
    env.EnvironmentName = EnvironmentName.Production;

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/error");
    }

이때 MVC 응용 프로그램에서 HttpGet 같은 HTTP 메서드 어트리뷰트를 이용해서 명시적으로 오류 처리기 액션 메서드를 지정하면 안됩니다. 명시적으로 동사를 지정하면 일부 요청이 메서드에 도달하지 못할 수도 있습니다.

[Route("/Error")]
public IActionResult Index()
{
    // Handle error here
}

상태 코드 페이지 구성하기

기본적으로 응용 프로그램은 500 (내부 서버 오류) 또는 404 (찾을 수 없음) 같은 HTTP 상태 코드에 대한 자세한 상태 코드 페이지를 제공하지 않습니다. 그러나 Configure 메서드에 다음과 같은 코드를 추가하면 StatusCodePagesMiddleware를 구성할 수 있습니다:

app.UseStatusCodePages();

이 미들웨어는 기본적으로 404 같은 일반적인 상태 코드에 대한 단순한 텍스트 전용 처리기를 추가합니다:

몇 가지 다른 확장 메서드도 지원됩니다. 그중 한 버전은 람다 식을 전달받고, 또 다른 버전은 콘텐츠 형식 및 서식 문자열을 전달받습니다.

app.UseStatusCodePages(async context =>
{
    context.HttpContext.Response.ContentType = "text/plain";
    await context.HttpContext.Response.WriteAsync(
        "Status code page, status code: " + 
        context.HttpContext.Response.StatusCode);
});
app.UseStatusCodePages("text/plain", "Status code page, status code: {0}");

또한 재지정 확장 메서드도 제공됩니다. 한 메서드는 클라이언트에 302 상태 코드를 전송하고, 다른 메서드는 본래의 상태 코드를 클라이언트에 반환하지만 URL 재지정 처리기도 실행합니다.

app.UseStatusCodePagesWithRedirects("/error/{0}");
app.UseStatusCodePagesWithReExecute("/error/{0}");

특정 요청에 대해 상태 코드 페이지를 비활성시키고 싶다면, 다음과 같이 처리할 수 있습니다:

var statusCodePagesFeature = context.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null)
{
    statusCodePagesFeature.Enabled = false;
}

예외 처리 코드

예외 처리 페이지의 코드도 예외를 던질 수 있습니다. 따라서 운영 환경에서 사용하는 오류 페이지는 순수하게 정적인 콘텐츠로 구성하는 것이 좋습니다.

또한, 일단 응답 헤더를 전송하고 나면 응답의 상태 코드를 변경할 수 없으며, 어떠한 예외 페이지나 처리기도 실행할 수 없다는 점을 인지하고 있어야 합니다. 해당 응답은 완료되거나 연결을 중단해야 합니다.

서버 예외 처리

응용 프로그램의 예외 처리 로직뿐만 아니라, 응용 프로그램을 호스팅하는 서버에서도 예외 처리를 일부 수행합니다. 서버는 헤더가 전송되기 전에 예외를 잡으면 본문 없이 500 내부 서버 오류 응답을 전송합니다. 반면 헤더가 전송된 이후에 예외를 잡으면 연결을 닫습니다. 응용 프로그램이 처리하지 않는 요청은 서버에 의해서 처리되며, 발생하는 모든 예외는 서버의 예외 처리 로직에 따라 처리됩니다. 응용 프로그램에 구성된 사용자 지정 오류 페이지나 예외 처리 미들웨어 또는 필터는 이 동작에 영향을 미치지 않습니다.

Startup 예외 처리

응용 프로그램 구동 중 발생하는 예외는 호스팅 계층에서만 처리가 가능합니다. 응용 프로그램 시작 중에 발생하는 예외는 서버의 동작에 영향을 줄 수 있습니다. 예를 들어서, KestrelServerOptions.UseHttps를 호출하기 전에 예외가 발생하면, 호스팅 계층에서 예외를 잡고, 서버를 시작하고, 비 SSL 포트를 통해서 오류 페이지를 표시합니다. 반면 해당 라인이 실행된 후에 예외가 발생하면 대신 HTTPS를 통해 오류 페이지를 제공합니다.

captureStartupErrorsdetailedErrors 키를 이용하면 시작 중에 발생한 오류에 대한 응답으로 호스트가 동작하는 방식을 구성할 수 있습니다.

ASP.NET MVC 오류 처리

MVC 응용 프로그램에서는 예외 필터 구성 및 모델 유효성 검사와 같은 추가적인 오류 처리 옵션을 사용할 수 있습니다.

예외 필터

MVC 응용 프로그램에서는 전역으로, 또는 컨트롤러나 액션 별로 예외 필터를 구성할 수 있습니다. 이런 필터들은 컨트롤러 액션이나 다른 필터를 실행하는 동안 발생하는 처리되지 않은 예외를 처리하며, 그 외의 경우에는 호출되지 않습니다. 필터 문서에서 예외 필터에 관해서 더 자세히 살펴보시기 바랍니다.

예외 필터는 MVC 액션에서 발생하는 예외를 처리하는 용도로는 적합하지만 오류 처리 미들웨어만큼 유연하지는 않습니다. 따라서 일반적인 상황에서는 미들웨어를 이용해서 예외를 처리하고, MVC 액션에 따라서 오류 처리를 다르게 해야하는 경우에만 필터를 사용하십시오.

모델 상태 오류 처리

모델 유효성 검사는 각 컨트롤러 액션이 호출되기 전에 발생하며, ModelState.IsValid 속성을 검사해서 적절히 대응하는 것은 액션 메서드의 역할입니다.

일부 응용 프로그램은 표준 규칙에 따라서 모델 유효성 검사 오류를 처리하는데, 이 경우 정책을 구현하기에 적절한 장소 중 하나가 바로 필터입니다. 이때 유효하지 않은 모델 상태에서 액션이 동작하는 방식을 테스트하는 것이 좋습니다. 이에 관해서는 컨트롤러 로직 테스트하기 문서를 참고하시기 바랍니다.