미들웨어 이해
웹 애플리케이션의 목적은 HTTP 요청을 수신하고 응답하는 것입니다. 요청이 수신되면 서버는 적절한 응답을 생성합니다. ASP.NET Core는 모두 이 요청/응답 주기와 관련이 있습니다.
ASP.NET Core 앱이 HTTP 요청을 받으면 일련의 구성 요소를 거쳐 응답을 생성합니다. 이러한 구성 요소를 미들웨어라고 합니다. 미들웨어는 요청이 이동하는 파이프라인으로 생각할 수 있으며, 각 미들웨어 계층은 파이프라인의 다음 계층 전과 후에 코드를 실행할 수 있습니다.
미들웨어 및 대리자
미들웨어는 HttpContext 개체를 가져와 Task를 반환하는 대리자로 구현됩니다.
HttpContext 개체는 현재 요청과 응답을 나타냅니다. 대리자는 요청과 응답을 처리하는 함수입니다.
예를 들어, 다음 코드를 고려하세요.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Run();
위의 코드에서
-
WebApplication.CreateBuilder(args)는 새WebApplicationBuilder개체를 만듭니다. -
builder.Build()는 새WebApplication개체를 만듭니다. - 첫 번째
app.Run()은HttpContext개체를 가져와Task를 반환하는 대리자를 정의합니다. 대리자는 응답에 "Hello world!"를 씁니다. - 두 번째
app.Run()이 앱을 시작합니다.
앱이 HTTP 요청을 받으면 대리자가 호출됩니다. 위임자는 응답에 "Hello world!"를 쓰고 요청을 완료합니다.
미들웨어 연결
대부분의 앱에는 순서대로 실행되는 여러 개의 미들웨어 구성 요소가 있습니다. 파이프라인에 미들웨어 구성 요소를 추가하는 순서는 중요합니다. 구성 요소는 추가된 순서대로 실행됩니다.
터미널 및 터미널이 아닌 미들웨어
각 미들웨어는 터미널 미들웨어 또는 터미널이 아닌 미들웨어로 생각할 수 있습니다. 터미널이 아닌 미들웨어는 요청을 처리한 후 파이프라인의 다음 미들웨어를 호출합니다. 터미널 미들웨어는 파이프라인의 마지막 미들웨어이며, 다음에 호출할 미들웨어가 없습니다.
app.Use()로 추가된 대리자는 터미널 미들웨어 또는 터미널이 아닌 미들웨어가 될 수 있습니다. 이러한 대리자는 매개 변수로 HttpContext 개체와 RequestDelegate 개체를 예상합니다. 일반적으로 대리자에는 await next.Invoke();가 포함됩니다. 이렇게 하면 제어권이 파이프라인의 다음 미들웨어로 넘어갑니다. 해당 줄 앞의 코드는 다음 미들웨어보다 먼저 실행되고, 해당 줄 뒤의 코드는 다음 미들웨어보다 먼저 실행됩니다.
app.Use()로 추가된 대리자는 응답이 클라이언트로 전송되기 전에 요청에 대한 작업을 수행할 두 가지 기회를 가져옵니다. 한 번은 터미널 미들웨어에서 응답이 생성되기 전에, 그리고 한 번은 터미널 미들웨어에서 응답이 생성된 후에 가져옵니다.
app.Run()으로 추가된 대리자는 항상 터미널 미들웨어입니다. 이러한 대리자는 파이프라인의 다음 미들웨어를 호출하지 않습니다. 이는 실행되는 마지막 미들웨어 구성 요소이며, 매개 변수로 HttpContext 개체만 예상합니다.
app.Run()은 터미널 미들웨어를 추가하는 바로 가기입니다.
다음 예시를 참조하세요.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Hello from middleware 1. Passing to the next middleware!\r\n");
// Call the next middleware in the pipeline
await next.Invoke();
await context.Response.WriteAsync("Hello from middleware 1 again!\r\n");
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from middleware 2!\r\n");
});
app.Run();
위의 코드에서
-
app.Use()는 다음을 수행하는 미들웨어 구성 요소를 정의합니다.- 응답에 "Hello from middleware 1. Passing to the next middleware!"를 씁니다.
- 파이프라인의 다음 미들웨어 구성 요소에 요청을 전달하고
await next.Invoke()로 완료될 때까지 기다립니다. - 파이프라인의 다음 구성 요소가 완료되면 "Hello from middleware 1 again!"라고 씁니다.
- 첫 번째
app.Run()은 응답에 "Hello from middleware 2!"를 쓰는 미들웨어 구성 요소를 정의합니다. - 두 번째
app.Run()이 앱을 시작합니다.
런타임에 웹 브라우저가 이 앱에 요청을 보내면 미들웨어 구성 요소는 파이프라인에 추가된 순서대로 실행됩니다. 앱은 다음과 같은 응답을 반환합니다.
Hello from middleware 1. Passing to the next middleware!
Hello from middleware 2!
Hello from middleware 1 again!
기본 제공 미들웨어
ASP.NET Core는 앱에 일반적인 기능을 추가하는 데 사용할 수 있는 일련의 기본 제공 미들웨어 구성 요소를 제공합니다. 명시적으로 추가된 미들웨어 구성 요소 외에도 일부 미들웨어는 기본적으로 암묵적으로 추가됩니다. 예를 들어, WebApplication.CreateBuilder()는 개발자 예외 페이지 라우팅 미들웨어를 추가하고, 관련 서비스가 구성된 경우 인증 및 권한 부여 미들웨어를 조건부로 추가하고, 엔드포인트 라우팅 미들웨어를 추가하는 WebApplicationBuilder를 반환합니다.
예를 들어, 다음 Program.cs 파일을 고려해 보세요.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAntiforgery();
app.MapStaticAssets();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();
위의 코드에서
-
app.UseExceptionHandler()는 예외를 catch하고 오류 페이지를 반환하는 미들웨어 구성 요소를 추가합니다. -
app.UseHsts()는 Strict-Transport-Security 헤더를 설정하는 미들웨어 구성 요소를 추가합니다. -
app.UseHttpsRedirection()은 HTTP 요청을 HTTPS로 리디렉션하는 미들웨어 구성 요소를 추가합니다. -
app.UseAntiforgery()는 CSRF(교차 사이트 요청 위조) 공격을 방지하는 미들웨어 구성 요소를 추가합니다. -
app.MapStaticAssets()및app.MapRazorComponents<App>()은 엔드포인트에 대한 경로를 매핑하고, 이후 엔드포인트 라우팅 미들웨어에서 이를 처리합니다. 엔드포인트 라우팅 미들웨어는WebApplicationBuilder에 의해 암묵적으로 추가됩니다.
앱 형식과 요구 사항에 따라 앱에서 사용할 수 있는 기본 제공 미들웨어 구성 요소가 훨씬 더 많습니다. 전체 목록은 설명서를 확인합니다.
팁
이 컨텍스트에서 Use로 시작하는 메서드는 일반적으로 미들웨어를 매핑하는 데 사용됩니다.
Map으로 시작하는 메서드는 일반적으로 엔드포인트를 매핑하는 데 사용됩니다.
Important
파이프라인에 미들웨어 구성 요소를 추가하는 순서는 중요합니다. 특정 미들웨어 구성 요소는 제대로 작동하려면 다른 구성 요소보다 먼저 실행되어야 합니다. 각 미들웨어 구성 요소에 대한 설명서를 확인하여 올바른 순서를 결정합니다.