참고
이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 10 버전을 참조하세요.
경고
이 버전의 ASP.NET Core는 더 이상 지원되지 않습니다. 자세한 내용은 .NET 및 .NET Core 지원 정책을 참조 하세요. 현재 릴리스는 이 문서의 .NET 10 버전을 참조하세요.
미들웨어는 요청 및 응답을 처리하는 앱 파이프라인으로 어셈블리되는 소프트웨어입니다. 각 미들웨어:
- 파이프라인의 다음 미들웨어에 요청을 전달할지 여부를 선택합니다.
- 파이프라인의 다음 미들웨어 전후에 작업을 수행할 수 있습니다.
요청 대리자는 요청 파이프라인을 빌드하는 데 사용됩니다. 요청 대리자는 각 HTTP 요청을 처리합니다.
Map, Use 및 Run 확장 메서드를 사용하여 요청 대리자를 구성합니다. 개별 요청 대리자를 익명 메서드(인라인 미들웨어라고 함)로 지정하거나 재사용 가능한 클래스에서 정의할 수 있습니다. 이러한 인라인 익명 메서드 또는 재사용 가능한 클래스를 미들웨어 또는 미들웨어 구성 요소라고 합니다. 요청 파이프라인의 각 미들웨어는 파이프라인에서 다음 미들웨어를 호출하거나 파이프라인을 단락하는 작업을 담당합니다. 미들웨어가 단락(short-circuit)되는 경우 미들웨어에서 더는 요청을 처리하지 못하도록 하기 때문에 이를 터미널 미들웨어라고 합니다.
추가 미들웨어 샘플을 사용하여 ASP.NET Core 요청 파이프라인과 ASP.NET 4.x 간의 차이점에 대한 자세한 내용은 HTTP 모듈을 ASP.NET Core 미들웨어로 마이그레이션을 참조하세요.
앱 유형별 미들웨어 역할
서버 쪽 Blazor, Razor 페이지 및 MVC는 미들웨어를 사용하여 서버에서 브라우저 요청을 처리합니다. 이 문서의 지침은 이러한 유형의 앱에 적용됩니다.
독립 실행형 Blazor WebAssembly 앱은 클라이언트에서 전적으로 실행되며 미들웨어 파이프라인으로 요청을 처리하지 않습니다. 이 문서의 지침은 독립 실행형 Blazor WebAssembly 앱에는 적용되지 않습니다.
미들웨어 코드 분석
품질을 위해 앱 코드를 검사하는 ASP.NET Core 컴파일러 플랫폼 분석기에 대한 자세한 내용은 ASP.NET Core 앱의 진단 코드 분석을 참조하세요.
WebApplication으로 미들웨어 파이프라인 만들기
ASP.NET Core 요청 파이프라인은 하나씩 차례로 호출되는 요청 대리자 시퀀스로 구성됩니다. 다음 다이어그램은 그 개념을 보여줍니다. 실행 스레드는 검은색 화살표를 따릅니다.
각 대리자는 다음 대리자 전과 후에 작업을 수행할 수 있습니다. 예외 처리 대리자는 파이프라인의 이후 단계에서 발생하는 예외를 잡을 수 있도록 파이프라인의 초기에 호출되어야 합니다.
참고
이 섹션의 코드 예제를 사용하여 로컬로 실험하려면 ASP.NET Core 빈 프로젝트 템플릿을 사용하여 ASP.NET Core 앱을 만듭니다. .NET CLI를 사용하는 경우 템플릿의 짧은 이름은 (web)입니다 dotnet new web .
가장 간단한 ASP.NET Core 앱은 요청 파이프라인 없이 요청을 처리하기 위해 단일 터미널 미들웨어를 익명 함수 요청 대리자로 설정하기 위해 호출 Run 합니다.
다음 예제에서
- 호출 RunExtensions.Run 은 모든 요청에 대해 호출되고 응답에 "Hello world!"를 씁니다.
- 코드 블록의 끝에 있는 WebApplication.Run 호출은 앱을 실행하고 호스트가 종료될 때까지 호출 스레드를 차단합니다.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Run();
시작 URL에서 브라우저에서 앱에 액세스할 때 응답:
Hello world!
Use를 사용하여 여러 요청 대리자를 연결합니다.
next 매개 변수는 파이프라인의 다음 대리자를 나타냅니다.
next 대리자 앞과 뒤에서 일반적으로 작업을 수행할 수 있습니다.
아래 예제에서는 다음을 보여줍니다.
- 두 개의 Use 호출, 각각 콘솔에 기록:
- 응답(
context.Response, HttpResponse)에 쓸 수 있는 작업을 수행할 수 있는 위치입니다. - 매개 변수가 호출된 후
next응답에 쓰지 않는 작업을 수행할 수 있는 위치입니다.
- 응답(
- 응답에 "RunExtensions.Run"를 쓰는 Hello world! 호출이 있는 터미널 요청 대리자입니다.
- 최종 Use 호출로, Run 터미널 요청 대리자 뒤에 위치하여 실행되지 않습니다.
- 앱을 실행하고 호스트가 종료될 때까지 호출 스레드를 차단하는 코드 블록의 끝에 대한 호출 WebApplication.Run 입니다.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
Console.WriteLine("Work that can write to the response. (1)");
await next.Invoke(context);
Console.WriteLine("Work that doesn't write to the response. (1)");
});
app.Use(async (context, next) =>
{
Console.WriteLine("Work that can write to the response. (2)");
await next.Invoke(context);
Console.WriteLine("Work that doesn't write to the response. (2)");
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Use(async (context, next) =>
{
Console.WriteLine("This statement isn't reached. (3)");
await next.Invoke(context);
Console.WriteLine("This statement isn't reached. (3)");
});
app.Run();
앱이 실행되면 앱의 콘솔 창에서 다음을 수행합니다.
응답에 작성할 수 있는 작업입니다. (1)
응답에 작성할 수 있는 작업입니다. (2)
응답에 쓰지 않는 작업입니다. (2)
응답에 쓰지 않는 작업입니다. (1)
요청 파이프라인의 단락은 불필요한 작업을 방지하므로 바람직한 경우가 많습니다. 예를 들어 정적 파일 미들웨어는 정적 파일에 대한 요청을 처리하고 나머지 파이프라인을 단락시켜 터미널 미들웨어 역할을 할 수 있습니다. 터미널 미들웨어 처리 전에 파이프라인에 추가된 미들웨어는 여전히 next.Invoke 명령문 이후의 코드를 처리합니다. 파이프라인을 종료하는 것이 목표이므로 호출 next.Invoke 할 계획이 없는 경우 확장 메서드를 Run 호출하는 대신 대리자를 Use 사용합니다.
응답이 클라이언트에 전송되는 동안 또는 이후에는 호출 next.Invoke 하지 마세요.
HttpResponse 시작되면 변경 내용으로 인해 예외가 발생합니다. 예를 들어 헤더 또는 응답 상태 코드를 설정 하면 응답이 시작된 후 예외가 발생합니다. 호출 next 후 응답 본문에 쓰는 방법은 다음과 같습니다.
- 지정된 응답의 콘텐츠 길이(
Content-Length헤더 값)보다 더 많은 바이트를 응답에 쓰는 것과 같은 프로토콜 위반을 발생시킵니다. - CSS 파일에 HTML 바닥글을 쓰는 등 본문 형식이 손상되었습니다.
응답이 시작되었는지 확인하려면 의 값을 HasStarted확인합니다.
자세한 내용은 라우팅 후 단락 회로 미들웨어를 참조하세요.
Run 대리자
대리자는 Run 매개 변수를 next 받지 않습니다. 첫 번째 Run 대리자는 항상 파이프라인을 종료합니다.
Run 는 규칙이기도 하며 일부 미들웨어는 파이프라인의 끝에서 실행되는 메서드를 노출 Run 할 수 있습니다.
Use 대리자 이후의 Run 대리자 또는 Run 대리자는 호출되지 않습니다.
미들웨어 파이프라인 분기
Map 확장은 요청 처리 파이프라인을 분기하는 규칙으로 사용됩니다. Map은 지정된 요청 경로의 일치를 기반으로 요청 파이프라인을 분기합니다. 요청 경로가 지정된 경로로 시작되면 분기가 실행됩니다.
다음 예제에서는 HandleMap1이(가) /map1에 대한 요청에 호출되며, HandleMap2이(가) /map2에 대한 요청에 호출됩니다.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/map1", HandleMap1);
app.Map("/map2", HandleMap2);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from the non-Map delegate!");
});
app.Run();
private static void HandleMap1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map 1");
});
}
private static void HandleMap2(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map 2");
});
}
다음 표에서는 이전 코드를 사용하는 요청 및 응답을 보여 줍니다.
| 요청 | 응답 |
|---|---|
/ |
Hello from the non-Map delegate. |
/map1 |
Map 1 |
/map2 |
Map 2 |
/map3 |
Hello from the non-Map delegate. |
Map이 사용되는 경우 일치하는 경로 세그먼트는 HttpRequest.Path에서 제거되고 각 요청에 대해 HttpRequest.PathBase에 추가됩니다.
Map 는 여러 세그먼트를 한 번에 일치시킬 수 있습니다.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/map1/segment1", HandleMultipleSegments);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from the non-Map delegate.");
});
app.Run();
private static void HandleMultipleSegments(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Processing '/map1/segment1'");
});
}
다음 표에서는 이전 코드를 사용하는 요청 및 응답을 보여 줍니다.
| 요청 | 응답 |
|---|---|
/ |
Hello from the non-Map delegate. |
/map1/segment1 |
Processing '/map1/segment1' |
Map 는 중첩을 지원합니다.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/level1", level1App => {
level1App.Map("/level2a", level2AApp => {
level2AApp.Run(async context =>
{
await context.Response.WriteAsync("Processing '/level1/level2a'");
});
});
level1App.Map("/level2b", level2BApp => {
level2BApp.Run(async context =>
{
await context.Response.WriteAsync("Processing '/level1/level2b'");
});
});
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from the non-Map delegate!");
});
app.Run();
다음 표에서는 이전 코드를 사용하는 요청 및 응답을 보여 줍니다.
| 요청 | 응답 |
|---|---|
/ |
Hello from the non-Map delegate. |
/level1/level2a |
Processing '/level1/level2a' |
/level1/level2b |
Processing '/level1/level2b' |
MapWhen은 지정된 조건자의 결과를 기반으로 요청 파이프라인을 분기합니다.
Func<HttpContext, bool> 형식의 조건자는 파이프라인의 새 분기에 요청을 매핑하는 데 사용될 수 있습니다. 다음 예제에서는 조건자를 사용하여 "branch"라는 쿼리 문자열 변수가 있는지 검색합니다.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapWhen(context => context.Request.Query.ContainsKey("branch"), HandleBranch);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from the non-Map delegate.");
});
app.Run();
private static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
var branchVer = context.Request.Query["branch"];
await context.Response.WriteAsync($"Branch used = '{branchVer}'");
});
}
다음 표에서는 이전 코드를 사용하는 요청 및 응답을 보여 줍니다.
| 요청 | 응답 |
|---|---|
/ |
Hello from the non-Map delegate. |
/?branch=main |
Branch used = 'main' |
UseWhen 는 지정된 조건자의 결과에 따라 요청 파이프라인을 분기할 수 있습니다. 달리 MapWhen분기는 터미널 미들웨어를 포함하지 않는 경우 주 파이프라인에 다시 가입됩니다.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
appBuilder => HandleBranchAndRejoin(appBuilder));
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from the non-Map delegate.");
});
app.Run();
void HandleBranchAndRejoin(IApplicationBuilder app)
{
var logger = app.ApplicationServices.GetRequiredService<ILogger<Program>>();
app.Use(async (context, next) =>
{
var branchVer = context.Request.Query["branch"];
logger.LogInformation("Branch used = {branchVer}", branchVer.ToString());
Console.WriteLine("Work that can write to the response.");
await next.Invoke(context);
Console.WriteLine("Work that doesn't write to the response.");
});
}
앞의 예제에서는 모든 요청에 대해 "Hello from the non-Map delegate."의 응답이 기록됩니다. 요청에 "branch"라는 쿼리 문자열 변수가 포함된 경우 주 파이프라인이 다시 참가하기 전에 해당 값이 기록됩니다.
IApplicationBuilder으로 미들웨어 파이프라인 만들기
ASP.NET Core 요청 파이프라인은 하나씩 차례로 호출되는 요청 대리자 시퀀스로 구성됩니다. 다음 다이어그램은 그 개념을 보여줍니다. 실행 스레드는 검은색 화살표를 따릅니다.
각 대리자는 다음 대리자 전과 후에 작업을 수행할 수 있습니다. 예외 처리 대리자는 파이프라인의 이후 단계에서 발생하는 예외를 잡을 수 있도록 파이프라인의 초기에 호출되어야 합니다.
가장 간단한 가능한 ASP.NET Core 앱은 모든 요청을 처리하는 단일 요청 대리자를 설정합니다. 이 경우 실제 요청 파이프라인은 포함되지 않습니다. 대신, 단일 익명 함수가 모든 HTTP 요청에 대한 응답에 호출됩니다.
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Hello, World!");
});
}
}
Use를 사용하여 여러 요청 대리자를 연결합니다.
next 매개 변수는 파이프라인의 다음 대리자를 나타냅니다.
next 매개 변수를 호출하지 않고 파이프라인을 단락(short-circuit)할 수 있습니다. 다음 예제의 설명처럼, 일반적으로 다음 대리자 전과 후 모두에서 작업을 수행할 수 있습니다.
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
대리자가 다음 대리자에게 요청을 전달하지 않을 때 이를 요청 파이프라인을 단락 처리(short-circuiting)하는 것이라고 합니다. 단락(short-circuiting)은 불필요한 작업을 방지하기 때문에 종종 바람직합니다. 예를 들어 정적 파일 미들웨어는 정적 파일에 대한 요청을 처리하고 나머지 파이프라인을 단락시켜 터미널 미들웨어 역할을 할 수 있습니다. 추가 처리를 종료하는 미들웨어 전에 파이프라인에 추가된 미들웨어는 next.Invoke 문 이후의 코드를 계속 처리합니다. 그러나 이미 전송된 응답에 쓰려고 시도하는 것에 대한 다음 경고를 참조하세요.
경고
클라이언트에 응답을 전송한 후에 next.Invoke를 호출하지 마십시오. 응답이 시작된 후 HttpResponse로 변경하면 예외를 던집니다. 예를 들면 헤더 및 상태 코드를 설정하면 예외가 발생합니다.
next를 호출한 후 응답 본문에 작성할 경우:
- 프로토콜 위반이 발생할 수 있습니다. 예를 들어, 명시된
Content-Length보다 긴 내용이 작성될 수 있습니다. - 본문 형식을 손상시킬 수 있습니다. 예를 들어, CSS 파일에 HTML 바닥글을 작성할 수 있습니다.
HasStarted는 헤더가 이미 전송됐는지 또는 본문이 이미 작성됐는지 여부를 나타내는 유용한 힌트를 제공해줍니다.
Run 대리자는 next 매개 변수를 받지 않습니다. 첫 번째 Run 대리자는 항상 터미널이며 파이프라인을 종료합니다.
Run이 규칙입니다. 일부 미들웨어 구성 요소는 파이프라인의 끝에서 실행되는 Run[Middleware] 메서드를 노출할 수 있습니다.
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
위 예제에서 Run 대리자는 응답에 "Hello from 2nd delegate."를 쓴 다음 파이프라인을 종료합니다.
Use 대리자 뒤에 추가된 다른 Run 또는 Run 대리자는 호출되지 않습니다.
미들웨어 파이프라인 분기
Map 확장자는 파이프라인 분기의 관례로 사용됩니다.
Map은 지정된 요청 경로의 일치를 기반으로 요청 파이프라인을 분기합니다. 요청 경로가 지정된 경로로 시작되면 분기가 실행됩니다.
public class Startup
{
private static void HandleMapTest1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
private static void HandleMapTest2(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 2");
});
}
public void Configure(IApplicationBuilder app)
{
app.Map("/map1", HandleMapTest1);
app.Map("/map2", HandleMapTest2);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
}
}
다음 표는 앞의 코드를 사용하여 http://localhost:1234의 요청 및 응답을 보여줍니다.
| 요청 | 응답 |
|---|---|
| localhost:1234 | 비맵(delegate)에서 인사드립니다. |
| localhost:1234/map1 | 지도 테스트 1 |
| localhost:1234/map2 | 지도 테스트 2 |
| localhost:1234/map3 | 비맵(delegate)에서 인사드립니다. |
Map이 사용되는 경우 일치하는 경로 세그먼트는 HttpRequest.Path에서 제거되고 각 요청에 대해 HttpRequest.PathBase에 추가됩니다.
Map은 중첩을 지원합니다. 예를 들면 다음과 같습니다.
app.Map("/level1", level1App => {
level1App.Map("/level2a", level2AApp => {
// "/level1/level2a" processing
});
level1App.Map("/level2b", level2BApp => {
// "/level1/level2b" processing
});
});
Map은 여러 세그먼트를 한 번에 일치시킬 수도 있습니다.
public class Startup
{
private static void HandleMultiSeg(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map multiple segments.");
});
}
public void Configure(IApplicationBuilder app)
{
app.Map("/map1/seg1", HandleMultiSeg);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
}
}
MapWhen은 지정된 조건자의 결과를 기반으로 요청 파이프라인을 분기합니다. 형식 Func<HttpContext, bool> 의 조건자를 사용하여 파이프라인의 새 분기에 요청을 매핑할 수 있습니다. 다음 예제에서 조건자는 쿼리 문자열 변수 branch의 존재를 검색합니다.
public class Startup
{
private static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
var branchVer = context.Request.Query["branch"];
await context.Response.WriteAsync($"Branch used = {branchVer}");
});
}
public void Configure(IApplicationBuilder app)
{
app.MapWhen(context => context.Request.Query.ContainsKey("branch"),
HandleBranch);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
}
}
다음 표는 앞의 코드를 사용하여 http://localhost:1234의 요청 및 응답을 보여줍니다.
| 요청 | 응답 |
|---|---|
| localhost:1234 | 비맵(delegate)에서 인사드립니다. |
| localhost:1234/?branch=main | 사용한 브랜치 = main |
UseWhen도 지정된 조건자의 결과를 기준으로 요청 파이프라인을 분기합니다.
MapWhen과 달리, 이 분기는 조기 종료가 발생하지 않거나 터미널 미들웨어를 포함하지 않는 경우 기본 파이프라인에 다시 합쳐집니다.
public class Startup
{
private void HandleBranchAndRejoin(IApplicationBuilder app, ILogger<Startup> logger)
{
app.Use(async (context, next) =>
{
var branchVer = context.Request.Query["branch"];
logger.LogInformation("Branch used = {branchVer}", branchVer.ToString());
// Do work that doesn't write to the Response.
await next();
// Do other work that doesn't write to the Response.
});
}
public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
{
app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
appBuilder => HandleBranchAndRejoin(appBuilder, logger));
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from main pipeline.");
});
}
}
위의 예제에서 "Hello from main pipeline." 응답은 모든 요청에 대해 기록됩니다. 요청에 쿼리 문자열 변수 branch가 포함되어 있으면, 기본 파이프라인이 다시 연결되기 전에 변수 값이 기록됩니다.
WebApplication에 의해 자동으로 추가된 미들웨어
WebApplication는 특정 조건에 따라 ASP.NET Core 앱에 다음 미들웨어를 자동으로 추가합니다.
-
UseDeveloperExceptionPage가HostingEnvironment일 때"Development"가 먼저 추가됩니다. - 사용자 코드가 아직
UseRouting를 호출하지 않은 경우 및 구성된 엔드포인트가 있는 경우(예:UseRouting),app.MapGet가 두 번째로 추가됩니다. -
UseEndpoints는 엔드포인트가 구성된 경우 미들웨어 파이프라인의 끝에 추가됩니다. -
UseAuthentication은 사용자 코드가 아직UseRouting를 호출하지 않았고 서비스 공급자에서UseAuthentication를 검색할 수 있는 경우IAuthenticationSchemeProvider바로 뒤에 추가됩니다.IAuthenticationSchemeProvider은AddAuthentication를 사용할 때 기본적으로 추가되고IServiceProviderIsService를 사용하여 서비스가 검색됩니다. -
UseAuthorization는 사용자 코드가 아직 호출UseAuthorization되지 않았고 서비스 공급자에서 검색할 수 있는 경우IAuthorizationHandlerProvider다음에 추가됩니다.IAuthorizationHandlerProvider은AddAuthorization를 사용할 때 기본적으로 추가되고IServiceProviderIsService를 사용하여 서비스가 검색됩니다. - 사용자 구성 미들웨어 및 엔드포인트는
UseRouting및UseEndpoints사이에 추가됩니다.
다음 코드는 앱에 추가되는 자동 미들웨어가 생성하는 것입니다.
if (isDevelopment)
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
if (isAuthenticationConfigured)
{
app.UseAuthentication();
}
if (isAuthorizationConfigured)
{
app.UseAuthorization();
}
// user middleware/endpoints
app.CustomMiddleware(...);
app.MapGet("/", () => "hello world");
// end user middleware/endpoints
app.UseEndpoints(e => {});
경우에 따라 앱에 대한 기본 미들웨어 구성이 올바르지 않으며 수정이 필요합니다. 예를 들어, UseCors은 UseAuthentication 및 UseAuthorization 전에 호출되어야 합니다. 앱은 UseAuthentication가 호출될 경우 UseAuthorization와 UseCors를 호출해야 합니다.
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
경로 일치가 발생하기 전에 미들웨어를 실행해야 하는 경우, UseRouting를 호출해야 하며 UseRouting에 대한 호출 전에 미들웨어를 배치해야 합니다.
UseEndpoints 는 앞에서 설명한 대로 자동으로 추가되므로 이 경우에는 필요하지 않습니다.
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// other middleware and endpoints
터미널 미들웨어를 추가하는 경우:
- 미들웨어는
UseEndpoints다음에 추가해야 합니다. - 터미널 미들웨어를 올바른 위치에 배치할 수 있도록 앱은
UseRouting및UseEndpoints를 호출해야 합니다.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
터미널 미들웨어는 요청을 처리하는 엔드포인트가 없는 경우 실행되는 미들웨어입니다.
WebApplication은 특정 조건에 따라 ASP.NET Core 앱에 다음 미들웨어를 자동으로 추가합니다.
HostingEnvironment가 있는 경우 UseDeveloperExceptionPage가 먼저 추가됩니다
"Development".사용자 코드가 아직 호출 되지 않았고 엔드포인트가 구성된 경우
UseRouting이 두 번째로 추가됩니다. 예를 들면 다음과 같습니다app.MapGet.엔드포인트가 구성된 경우 미들웨어 파이프라인의 끝에 UseEndpoints가 추가됩니다.
사용자 코드가 아직 을 호출하지 않았고, 서비스 공급자에서
UseRouting를 감지할 수 있는 경우, 이는 즉시UseAuthentication뒤에 추가됩니다.IAuthenticationSchemeProvider는 AddAuthentication을 사용할 때 기본적으로 추가되며, 서비스는 IServiceProviderIsService를 사용하여 검색됩니다.사용자 코드가 아직 호출 되지 않은 경우 및 서비스 공급자에서
UseAuthorization를 검색할 수 있는 경우 UseAuthorization이 다음에 추가됩니다.IAuthorizationHandlerProvider는 AddAuthorization을 사용할 때 기본적으로 추가되며,IServiceProviderIsService를 사용하여 서비스를 탐지합니다.사용자 구성 미들웨어 및 엔드포인트는
UseRouting및UseEndpoints사이에 추가됩니다.
다음 코드는 앱에 추가되는 자동 미들웨어가 생성하는 것입니다.
if (isDevelopment)
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
if (isAuthenticationConfigured)
{
app.UseAuthentication();
}
if (isAuthorizationConfigured)
{
app.UseAuthorization();
}
// User middleware/endpoints
app.CustomMiddleware(...);
app.MapGet("/", () => "hello world");
// End user middleware/endpoints
app.UseEndpoints(e => {});
경우에 따라 앱에 대한 기본 미들웨어 구성이 올바르지 않으며 수정이 필요합니다. 예를 들어, UseCors은 UseAuthentication 및 UseAuthorization 전에 호출되어야 합니다. 앱은 UseAuthentication가 호출될 경우 UseAuthorization와 UseCors를 호출해야 합니다.
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
경로 일치가 발생하기 전에 미들웨어를 UseRouting 실행해야 하는 경우 호출해야 하며 미들웨어를 호출 UseRouting하기 전에 배치해야 합니다.
UseEndpoints 는 앞에서 설명한 대로 자동으로 추가되므로 이 경우에 필요하지 않습니다.
app.Use((context, next) =>
{
return next(context);
});
app.UseRouting();
// Other middleware and endpoints
터미널 미들웨어를 추가하는 경우:
미들웨어는
UseEndpoints다음에 추가해야 합니다.앱이
UseRouting및UseEndpoints을 호출해야만 터미널 미들웨어를 올바른 위치에 배치할 수 있습니다.
app.UseRouting();
app.MapGet("/", () => "hello world");
app.UseEndpoints(e => {});
app.Run(context =>
{
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
터미널 미들웨어는 요청을 처리하는 엔드포인트가 없는 경우 실행되는 미들웨어입니다.
최소 API의 위조 방지 미들웨어에 대한 자세한 내용은
미들웨어 순서
미들웨어가 앱의 Program 파일에 나타나는 순서는 응답에 대한 역순으로 요청에 대해 미들웨어가 호출되는 순서를 정의합니다.
미들웨어 순서와 요청 처리 시나리오에 사용자 지정 미들웨어를 추가하는 기능을 완전히 제어할 수 있습니다. 미들웨어 순서는 보안, 성능 및 기능에 매우 중요할 수 있습니다.
다음 예제에서는 일반적인 앱 시나리오에 대한 미들웨어 순서를 보여 줍니다. 각 미들웨어 확장 메서드는 WebApplicationBuilder 네임스페이스를 통해 Microsoft.AspNetCore.Builder에 노출됩니다.
- 예외 및 오류 처리
- 앱이 환경에서 실행되는 경우
Development:- 개발자 예외 페이지 미들웨어(UseDeveloperExceptionPage)는 앱 런타임 오류를 보고합니다.
- 데이터베이스 오류 페이지 미들웨어(UseDatabaseErrorPage)는 데이터베이스 런타임 오류를 보고합니다.
- 앱이 환경에서 실행되는 경우
Production:- 예외 처리기 미들웨어(UseExceptionHandler)는 뒤따르는 미들웨어에서 발생한 예외를 포착합니다.
- HSTS(HTTP Strict Transport Security) 프로토콜 미들웨어(UseHsts)는 헤더를
Strict-Transport-Security추가합니다.
- 앱이 환경에서 실행되는 경우
- HTTPS 리디렉션 미들웨어(UseHttpsRedirection)는 HTTP 요청을 HTTPS로 리디렉션합니다.
- 정적 파일 미들웨어(필요한 경우 UseStaticFiles)는 정적 파일을 반환하고 추가 요청 처리를 중단합니다.
- Cookie 정책 미들웨어(UseCookiePolicy)는 앱을 EU GDPR(일반 데이터 보호 규정)에 따릅니다.
- 요청을 라우팅하도록 미들웨어(UseRouting)를 라우팅합니다.
- 인증 미들웨어(UseAuthentication)는 보안 리소스에 대한 액세스가 허용되기 전에 사용자를 인증하려고 시도합니다.
- 권한 부여 미들웨어(UseAuthorization)는 사용자에게 보안 리소스에 액세스할 수 있는 권한을 부여합니다.
- 위조 방지 미들웨어(UseAntiforgery)는 파이프라인에 위조 방지 미들웨어를 추가합니다. UseAntiforgery은 UseAuthentication 및 UseAuthorization 호출 뒤에 배치되어야 합니다.
- 세션 미들웨어(Razor Pages 및 MVC만 UseSession해당)는 세션 상태를 설정하고 유지 관리합니다. 앱이 세션 상태를 사용하는 경우 정책 미들웨어 후 cookie 및 Pages/MVC 미들웨어 전에 Razor 세션 미들웨어를 호출합니다.
- 엔드포인트 라우팅 미들웨어
- MapRazorComponents 요청 파이프라인에 구성 요소 엔드포인트를 추가합니다. Razor
- MapRazorPages 페이지 엔드포인트를 요청 파이프라인에 추가하려면 Razor을 사용합니다.
- MapControllerRoute - 요청 파이프라인에 컨트롤러 엔드포인트를 추가합니다.
일반적인 Blazor Web App 미들웨어 파이프라인:
app.UseWebAssemblyDebugging(); // Development environment with client-side rendering
app.UseMigrationsEndPoint(); // Development environment with ASP.NET Core Identity
app.UseExceptionHandler("/Error", createScopeForErrors: true); // Non-Development environment
app.UseHsts(); // Non-Development environment with HTTPS protocol
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
app.UseHttpsRedirection(); // With HTTPS protocol
app.UseAntiforgery();
app.MapStaticAssets();
app.MapRazorComponents<App>(); // With additional extension methods for render modes
app.MapAdditionalIdentityEndpoints(); // With ASP.NET Core Identity
app.Run();
일반적인 Razor 페이지/MVC 미들웨어 파이프라인:
app.UseMigrationsEndPoint(); // Development environment with ASP.NET Core Identity
app.UseExceptionHandler("/Error"); // Non-Development environment
app.UseHsts(); // Non-Development environment with HTTPS protocol
app.UseHttpsRedirection(); // With HTTPS protocol
// app.UseCookiePolicy();
app.UseRouting(); // If not called, runs at the beginning of the pipeline by default
// app.UseRateLimiter();
// app.UseRequestLocalization();
// app.UseCors();
// app.UseAuthentication(); // Called internally for ASP.NET Core Identity
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.MapStaticAssets();
app.MapControllerRoute(...); // For MVC controllers
app.MapRazorPages(); // For Razor Pages pages
app.MapControllers(); // With authentication in a Razor Pages app
app.Run();
위의 코드에서
- CORS 미들웨어(UseCors), 인증 미들웨어(UseAuthentication) 및 권한 부여 미들웨어()는UseAuthorization 표시된 순서대로 표시되어야 합니다.
- 캐시된 응답을 포함하여 모든 요청에 CORS 헤더를 추가하려면 응답 캐싱 미들웨어() 앞에 CORS 미들웨어(UseCorsUseResponseCaching)가 나타나야 합니다. 자세한 내용은 UseCORS가 UseResponseCaching보다 앞서야 하는지는 명확하지 않습니다 (
dotnet/aspnetcore#23218). - 요청 지역화 미들웨어(UseRequestLocalization)는 요청 문화권을 확인할 수 있는 미들웨어 앞에 나타나야 합니다(예: 정적 파일 미들웨어)UseStaticFiles.
- 속도 제한 미들웨어(UseRateLimiter)는 엔드포인트별 API를 사용하는 속도 제한 미들웨어(UseRouting)를 라우팅한 후 호출해야 합니다. 예를 들어
[EnableRateLimiting]특성을 사용하는 경우, 속도 제한 미들웨어는 라우팅 미들웨어 뒤에 호출되어야 합니다. 글로벌 리미터만 호출하는 경우 미들웨어를 라우팅하기 전에 속도 제한 미들웨어를 호출할 수 있습니다.
일부 시나리오의 경우 미들웨어는 다른 순서를 갖습니다. 예를 들어 캐싱 및 압축 순서는 앱의 사양에 따라 달라집니다. 다음 순서로 압축된 응답을 캐싱하여 CPU 사용량을 줄일 수 있지만 앱은 Gzip 또는 Brotli와 같은 다양한 압축 알고리즘을 사용하여 리소스의 여러 표현을 캐싱할 수 있습니다.
app.UseResponseCaching();
app.UseResponseCompression();
정적 자산은 일반적으로 파이프라인 초기에 제공되므로 앱이 성능을 향상시키기 위해 요청 처리를 단락시킬 수 있습니다.
인증은 인증되지 않은 요청을 그냥 넘어가지 않습니다. 인증 미들웨어가 요청을 인증하더라도 권한 부여는 프레임워크가 Razor에서 Blazor Web App 구성 요소를, Razor Pages 앱에서 페이지를, 또는 MVC 앱에서 컨트롤러와 작업을 선택한 후에 이루어집니다.
다음 다이어그램은 ASP.NET Core MVC 및 Razor Pages 앱의 전체 요청 처리 파이프라인을 보여 줍니다. 일반적인 앱에서 기존 미들웨어의 순서가 지정되는 방식과 사용자 지정 미들웨어가 추가되는 위치를 볼 수 있습니다. 사용자는 원하는 대로 기존 미들웨어의 순서를 바꾸거나 시나리오의 필요에 따라 새 사용자 지정 미들웨어를 주입할 수 있습니다.
앞에 나온 다이어그램의 엔드포인트 미들웨어는 해당 앱 형식(MVC 또는 Razor Pages)에 따라 필터 파이프라인을 실행합니다.
앞의 다이어그램은 정적 파일 다음에 나오는 라우팅 미들웨어를 보여줍니다. 이 순서는 명시적으로 앱을 호출하여 프로젝트 템플릿이 작동하는 방식입니다 . UseRouting.
app.UseRouting을 호출하지 않으면 라우팅 미들웨어는 기본적으로 파이프라인의 시작 부분에서 실행됩니다. 자세한 내용은 라우팅을 참조하세요.
파일에 미들웨어 구성 요소를 Program.cs 추가하는 순서는 요청에 따라 미들웨어 구성 요소가 호출되는 순서와 응답의 역순을 정의합니다. 순서는 보안, 성능 및 기능에 중요합니다.
다음 강조 표시된 코드는 Program.cs 일반적인 권장 순서로 보안 관련 미들웨어 구성 요소를 추가합니다.
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMiddleware.Data;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRateLimiter();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.MapRazorPages();
app.MapDefaultControllerRoute();
app.Run();
위의 코드에서
- 개별 사용자 계정으로 새 웹 앱을 만들면 주석 처리된 미들웨어가 추가되지 않습니다.
- 모든 미들웨어가 정확한 순서로 표시되는 것은 아닙니다. 예:
-
UseCors,UseAuthentication,UseAuthorization은 표시된 순서로 표시되어야 합니다. - 현재
UseCors는UseResponseCaching보다 먼저 표시되어야 합니다. 이 요구 사항은 GitHub 이슈 dotnet/aspnetcore #23218에 설명되어 있습니다. -
UseRequestLocalization는 요청 문화권을 확인할 수 있는 미들웨어 앞에 나타나야 합니다. 예를 들면app.UseStaticFiles()과 같은 경우입니다. -
UseRateLimiter 후에
UseRouting를 호출해야 속도 제한 엔드포인트 특정 API를 사용할 수 있습니다. 예를 들어,[EnableRateLimiting]특성을 사용하는 경우UseRateLimiter다음에UseRouting를 호출해야 합니다. 전역 리미터UseRateLimiter만 호출하는 경우 이전에UseRouting호출할 수 있습니다.
-
일부 시나리오의 경우 미들웨어는 다른 순서를 갖습니다. 예를 들어 캐싱 및 압축 순서는 시나리오마다 다르며 유효한 순서가 여러 개 있습니다. 예시:
app.UseResponseCaching();
app.UseResponseCompression();
위의 코드를 사용하면 압축된 응답을 캐싱하여 CPU 사용량을 줄일 수 있지만 Gzip 또는 Brotli와 같은 다른 압축 알고리즘을 사용하여 리소스의 여러 표현을 캐싱할 수 있습니다.
다음 순서는 정적 파일을 결합하여 압축된 정적 파일 캐싱을 허용합니다.
app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();
다음 Program.cs 코드는 일반적인 앱 시나리오에 대한 미들웨어 구성 요소를 추가합니다.
- 예외 및 오류 처리
- 앱이 환경에서 실행되는 경우
Development:- 개발자 예외 페이지 미들웨어(UseDeveloperExceptionPage)는 앱 런타임 오류를 보고합니다.
- 데이터베이스 오류 페이지 미들웨어(UseDatabaseErrorPage)는 데이터베이스 런타임 오류를 보고합니다.
- 앱이 환경에서 실행되는 경우
Production:- 예외 처리기 미들웨어(UseExceptionHandler)는 뒤따르는 미들웨어에서 발생한 예외를 포착합니다.
- HSTS(HTTP Strict Transport Security) 프로토콜 미들웨어(UseHsts)는 헤더를
Strict-Transport-Security추가합니다.
- 앱이 환경에서 실행되는 경우
- HTTPS 리디렉션 미들웨어(UseHttpsRedirection)는 HTTP 요청을 HTTPS로 리디렉션합니다.
- 정적 파일 미들웨어(UseStaticFiles)는 정적 파일을 반환하고 후속 요청 처리를 중단합니다.
- Cookie 정책 미들웨어(UseCookiePolicy)는 앱을 EU GDPR(일반 데이터 보호 규정) 규정을 준수합니다.
- 요청을 라우팅하도록 미들웨어(UseRouting)를 라우팅합니다.
- 인증 미들웨어(UseAuthentication)는 보안 리소스에 대한 액세스가 허용되기 전에 사용자를 인증하려고 시도합니다.
- 권한 부여 미들웨어(UseAuthorization)는 사용자에게 보안 리소스에 액세스할 수 있는 권한을 부여합니다.
- 세션 미들웨어(UseSession)는 세션 상태를 설정하고 유지 관리합니다. 앱이 세션 상태를 사용하는 경우 정책 미들웨어 후 cookie 및 MVC 미들웨어 전에 세션 미들웨어를 호출합니다.
- UseEndpoints와 함께 사용하는 엔드포인트 라우팅 미들웨어(MapRazorPages)로 Razor Pages 엔드포인트를 요청 파이프라인에 추가합니다.
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();
앞의 예제 코드에서 각 미들웨어 확장 메서드는 WebApplicationBuilder 네임스페이스를 통해 Microsoft.AspNetCore.Builder에 표시됩니다.
UseExceptionHandler는 파이프라인에 처음으로 추가된 미들웨어 구성 요소입니다. 따라서 예외 처리기 미들웨어는 이후 호출에서 발생하는 모든 예외를 catch합니다.
정적 파일 미들웨어는 파이프라인 초기에 호출되므로 나머지 구성 요소를 거치지 않고 요청 및 단락을 처리할 수 있습니다. 정적 파일 미들웨어는 권한 부여 검사를 제공하지 않습니다 . wwwroot 아래에 있는 파일을 포함하여 정적 파일 미들웨어에서 제공하는 모든 파일을 공개적으로 사용할 수 있습니다. 정적 파일을 보호하는 방법은 ASP.NET Core 앱에서 정적 파일 제공을 참조하세요.
요청이 정적 파일 미들웨어에서 처리되지 않으면 인증을 수행하는 인증 미들웨어(UseAuthentication)에 전달됩니다. 인증은 인증되지 않은 요청을 그냥 넘어가지 않습니다. 인증 미들웨어는 요청을 인증하지만 MVC가 특정 Razor 페이지 또는 MVC 컨트롤러 및 작업을 선택한 후에만 권한 부여(및 거부)가 발생합니다.
다음 예제에서는 정적 파일에 대한 요청이 응답 압축 미들웨어 전에 정적 파일 미들웨어에 의해 처리되는 미들웨어 순서를 보여 줍니다. 정적 파일은 이 미들웨어 순서를 사용하여 압축되지 않습니다. Razor Pages 응답을 압축할 수 있습니다.
// Static files aren't compressed by static file middleware.
app.UseStaticFiles();
app.UseRouting();
app.UseResponseCompression();
app.MapRazorPages();
다음 다이어그램은 ASP.NET Core MVC 및 Razor Pages 앱의 전체 요청 처리 파이프라인을 보여 줍니다. 일반적인 앱에서 기존 미들웨어의 순서가 지정되는 방식과 사용자 지정 미들웨어가 추가되는 위치를 볼 수 있습니다. 사용자는 원하는 대로 기존 미들웨어의 순서를 바꾸거나 시나리오의 필요에 따라 새 사용자 지정 미들웨어를 주입할 수 있습니다.
앞에 나온 다이어그램의 엔드포인트 미들웨어는 해당 앱 형식(MVC 또는 Razor Pages)에 따라 필터 파이프라인을 실행합니다.
앞의 다이어그램은 정적 파일 다음에 나오는 라우팅 미들웨어를 보여줍니다. 이 순서는 명시적으로 앱을 호출하여 프로젝트 템플릿이 작동하는 방식입니다 . UseRouting.
app.UseRouting을 호출하지 않으면 라우팅 미들웨어는 기본적으로 파이프라인의 시작 부분에서 실행됩니다. 자세한 내용은 라우팅을 참조하세요.
파일에 미들웨어 구성 요소를 Program.cs 추가하는 순서는 요청에 따라 미들웨어 구성 요소가 호출되는 순서와 응답의 역순을 정의합니다. 순서는 보안, 성능 및 기능에 중요합니다.
다음 강조 표시된 코드는 Program.cs 일반적인 권장 순서로 보안 관련 미들웨어 구성 요소를 추가합니다.
using IndividualAccountsExample.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
// 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.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.MapRazorPages();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
위의 코드에서
- 개별 사용자 계정으로 새 웹 앱을 만들면 주석 처리된 미들웨어가 추가되지 않습니다.
- 모든 미들웨어가 정확한 순서로 표시되는 것은 아닙니다. 예:
-
UseCors,UseAuthentication,UseAuthorization은 표시된 순서로 표시되어야 합니다. - 현재
UseCors는UseResponseCaching보다 먼저 표시되어야 합니다. 이 요구 사항은 GitHub 이슈 dotnet/aspnetcore #23218에 설명되어 있습니다. -
UseRequestLocalization은 요청 문화권(예:app.UseMvcWithDefaultRoute())을 확인할 수 있는 모든 미들웨어보다 먼저 표시되어야 합니다.
-
일부 시나리오의 경우 미들웨어는 다른 순서를 갖습니다. 예를 들어 캐싱 및 압축 순서는 시나리오마다 다르며 유효한 순서가 여러 개 있습니다. 예시:
app.UseResponseCaching();
app.UseResponseCompression();
위의 코드를 사용하면 압축된 응답을 캐싱하여 CPU 사용량을 줄일 수 있지만 Gzip 또는 Brotli와 같은 다른 압축 알고리즘을 사용하여 리소스의 여러 표현을 캐싱할 수 있습니다.
다음 순서는 정적 파일을 결합하여 압축된 정적 파일 캐싱을 허용합니다.
app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();
다음 Program.cs 코드는 일반적인 앱 시나리오에 대한 미들웨어 구성 요소를 추가합니다.
- 예외 및 오류 처리
- 앱이 환경에서 실행되는 경우
Development:- 개발자 예외 페이지 미들웨어(UseDeveloperExceptionPage)는 앱 런타임 오류를 보고합니다.
- 데이터베이스 오류 페이지 미들웨어(UseDatabaseErrorPage)는 데이터베이스 런타임 오류를 보고합니다.
- 앱이 환경에서 실행되는 경우
Production:- 예외 처리기 미들웨어(UseExceptionHandler)는 뒤따르는 미들웨어에서 발생한 예외를 포착합니다.
- HSTS(HTTP Strict Transport Security) 프로토콜 미들웨어(UseHsts)는 헤더를
Strict-Transport-Security추가합니다.
- 앱이 환경에서 실행되는 경우
- HTTPS 리디렉션 미들웨어(UseHttpsRedirection)는 HTTP 요청을 HTTPS로 리디렉션합니다.
- 정적 파일 미들웨어(UseStaticFiles)는 정적 파일을 반환하고 후속 요청 처리를 중단합니다.
- Cookie 정책 미들웨어(UseCookiePolicy)는 앱을 EU GDPR(일반 데이터 보호 규정) 규정을 준수합니다.
- 요청을 라우팅하도록 미들웨어(UseRouting)를 라우팅합니다.
- 인증 미들웨어(UseAuthentication)는 보안 리소스에 대한 액세스가 허용되기 전에 사용자를 인증하려고 시도합니다.
- 권한 부여 미들웨어(UseAuthorization)는 사용자에게 보안 리소스에 액세스할 수 있는 권한을 부여합니다.
- 세션 미들웨어(UseSession)는 세션 상태를 설정하고 유지 관리합니다. 앱이 세션 상태를 사용하는 경우 정책 미들웨어 후 cookie 및 MVC 미들웨어 전에 세션 미들웨어를 호출합니다.
- UseEndpoints와 함께 사용하는 엔드포인트 라우팅 미들웨어(MapRazorPages)로 Razor Pages 엔드포인트를 요청 파이프라인에 추가합니다.
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();
앞의 예제 코드에서 각 미들웨어 확장 메서드는 WebApplicationBuilder 네임스페이스를 통해 Microsoft.AspNetCore.Builder에 표시됩니다.
UseExceptionHandler는 파이프라인에 처음으로 추가된 미들웨어 구성 요소입니다. 따라서 예외 처리기 미들웨어는 이후 호출에서 발생하는 모든 예외를 catch합니다.
정적 파일 미들웨어는 파이프라인 초기에 호출되므로 나머지 구성 요소를 거치지 않고 요청 및 단락을 처리할 수 있습니다. 정적 파일 미들웨어는 권한 부여 검사를 제공하지 않습니다 . wwwroot 아래에 있는 파일을 포함하여 정적 파일 미들웨어에서 제공하는 모든 파일을 공개적으로 사용할 수 있습니다. 정적 파일을 보호하는 방법은 ASP.NET Core 앱에서 정적 파일 제공을 참조하세요.
요청이 정적 파일 미들웨어에서 처리되지 않으면 인증을 수행하는 인증 미들웨어(UseAuthentication)에 전달됩니다. 인증은 인증되지 않은 요청을 그냥 넘어가지 않습니다. 인증 미들웨어는 요청을 인증하지만 MVC가 특정 Razor 페이지 또는 MVC 컨트롤러 및 작업을 선택한 후에만 권한 부여(및 거부)가 발생합니다.
다음 예제에서는 정적 파일에 대한 요청이 응답 압축 미들웨어 전에 정적 파일 미들웨어에 의해 처리되는 미들웨어 순서를 보여 줍니다. 정적 파일은 이 미들웨어 순서를 사용하여 압축되지 않습니다. Razor Pages 응답을 압축할 수 있습니다.
// Static files aren't compressed by static file middleware.
app.UseStaticFiles();
app.UseRouting();
app.UseResponseCompression();
app.MapRazorPages();
다음 다이어그램은 ASP.NET Core MVC 및 Razor Pages 앱의 전체 요청 처리 파이프라인을 보여 줍니다. 일반적인 앱에서 기존 미들웨어의 순서가 지정되는 방식과 사용자 지정 미들웨어가 추가되는 위치를 볼 수 있습니다. 사용자는 원하는 대로 기존 미들웨어의 순서를 바꾸거나 시나리오의 필요에 따라 새 사용자 지정 미들웨어를 주입할 수 있습니다.
앞에 나온 다이어그램의 엔드포인트 미들웨어는 해당 앱 형식(MVC 또는 Razor Pages)에 따라 필터 파이프라인을 실행합니다.
미들웨어 구성 요소가 Startup.Configure 메서드에 추가되는 순서는 요청에서 미들웨어 구성 요소가 호출되는 순서와 응답에 대한 역순서를 정의합니다. 순서는 보안, 성능 및 기능에 중요합니다.
다음 Startup.Configure 메서드는 보안 관련 미들웨어 구성 요소를 일반적인 권장 순서에 따라 추가합니다.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
위의 코드에서
- 개별 사용자 계정으로 새 웹 앱을 만들면 주석 처리된 미들웨어가 추가되지 않습니다.
- 모든 미들웨어가 정확한 순서로 표시되는 것은 아닙니다. 예:
일부 시나리오의 경우 미들웨어는 다른 순서를 갖습니다. 예를 들어 캐싱 및 압축 순서는 시나리오마다 다르며 유효한 순서가 여러 개 있습니다. 예시:
app.UseResponseCaching();
app.UseResponseCompression();
위의 코드를 사용하면 압축된 응답을 캐싱하여 CPU를 저장할 수 있지만 Gzip 또는 Brotli와 같은 다른 압축 알고리즘을 사용하여 리소스의 여러 표현을 캐싱할 수도 있습니다.
다음 순서는 정적 파일을 결합하여 압축된 정적 파일 캐싱을 허용합니다.
app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();
다음 Startup.Configure 메서드는 공통 앱 시나리오를 위한 미들웨어 구성 요소를 추가합니다.
- 예외 및 오류 처리
- 앱이 환경에서 실행되는 경우
Development:- 개발자 예외 페이지 미들웨어(UseDeveloperExceptionPage)는 앱 런타임 오류를 보고합니다.
- 데이터베이스 오류 페이지 미들웨어는 데이터베이스 런타임 오류를 보고합니다.
- 앱이 환경에서 실행되는 경우
Production:- 예외 처리기 미들웨어(UseExceptionHandler)는 뒤따르는 미들웨어에서 발생한 예외를 포착합니다.
- HSTS(HTTP Strict Transport Security) 프로토콜 미들웨어(UseHsts)는 헤더를
Strict-Transport-Security추가합니다.
- 앱이 환경에서 실행되는 경우
- HTTPS 리디렉션 미들웨어(UseHttpsRedirection)는 HTTP 요청을 HTTPS로 리디렉션합니다.
- 정적 파일 미들웨어(UseStaticFiles)는 정적 파일을 반환하고 후속 요청 처리를 중단합니다.
- Cookie 정책 미들웨어(UseCookiePolicy)는 앱을 EU GDPR(일반 데이터 보호 규정) 규정을 준수합니다.
- 요청을 라우팅하도록 미들웨어(UseRouting)를 라우팅합니다.
- 인증 미들웨어(UseAuthentication)는 보안 리소스에 대한 액세스가 허용되기 전에 사용자를 인증하려고 시도합니다.
- 권한 부여 미들웨어(UseAuthorization)는 사용자에게 보안 리소스에 액세스할 수 있는 권한을 부여합니다.
- 세션 미들웨어(UseSession)는 세션 상태를 설정하고 유지 관리합니다. 앱이 세션 상태를 사용하는 경우 정책 미들웨어 후 cookie 및 MVC 미들웨어 전에 세션 미들웨어를 호출합니다.
- UseEndpoints와 함께 사용하는 엔드포인트 라우팅 미들웨어(MapRazorPages)로 Razor Pages 엔드포인트를 요청 파이프라인에 추가합니다.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
앞의 예제 코드에서 각 미들웨어 확장 메서드는 IApplicationBuilder 네임스페이스를 통해 Microsoft.AspNetCore.Builder에 표시됩니다.
UseExceptionHandler는 파이프라인에 처음으로 추가된 미들웨어 구성 요소입니다. 따라서 예외 처리기 미들웨어는 이후 호출에서 발생하는 모든 예외를 catch합니다.
정적 파일 미들웨어는 파이프라인 초기에 호출되므로 나머지 구성 요소를 거치지 않고 요청 및 단락을 처리할 수 있습니다. 정적 파일 미들웨어는 권한 부여 검사를 제공하지 않습니다 . wwwroot 아래에 있는 파일을 포함하여 정적 파일 미들웨어에서 제공하는 모든 파일을 공개적으로 사용할 수 있습니다. 정적 파일을 보호하는 방법은 ASP.NET Core 앱에서 정적 파일 제공을 참조하세요.
요청이 정적 파일 미들웨어에서 처리되지 않으면 인증을 수행하는 인증 미들웨어(UseAuthentication)에 전달됩니다. 인증은 인증되지 않은 요청을 그냥 넘어가지 않습니다. 인증 미들웨어는 요청을 인증하지만 MVC가 특정 Razor 페이지 또는 MVC 컨트롤러 및 작업을 선택한 후에만 권한 부여(및 거부)가 발생합니다.
다음 예제에서는 정적 파일에 대한 요청이 응답 압축 미들웨어 전에 정적 파일 미들웨어에 의해 처리되는 미들웨어 순서를 보여 줍니다. 정적 파일은 이 미들웨어 순서를 사용하여 압축되지 않습니다. Razor Pages 응답을 압축할 수 있습니다.
public void Configure(IApplicationBuilder app)
{
// Static files aren't compressed by static file middleware.
app.UseStaticFiles();
app.UseRouting();
app.UseResponseCompression();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
SPA(단일 페이지 애플리케이션)의 경우 SPA 미들웨어 UseSpaStaticFiles는 일반적으로 미들웨어 파이프라인에서 마지막으로 나옵니다. SPA 미들웨어가 마지막으로 나오는 이유는 다음과 같습니다.
- 다른 모든 미들웨어가 일치하는 요청에 먼저 응답할 수 있도록 합니다.
- 서버 앱에서 인식하지 못하는 모든 경로에 대해 클라이언트 쪽 라우팅이 있는 SPA가 실행되도록 허용합니다.
단일 페이지 애플리케이션에 대한 자세한 내용은 React 및 Angular 프로젝트 템플릿 관련 가이드를 참조하세요.
UseCors 및 UseStaticFiles 순서
순서 지정 및 자세한 내용은 UseCors.UseStaticFiles
전달된 헤더 미들웨어 순서
전달된 헤더 정보를 사용하는 미들웨어가 처리에 헤더 값을 사용할 수 있도록 다른 미들웨어 앞에 전달된 헤더 미들웨어를 실행합니다. 진단 및 오류 처리 미들웨어 후 전달된 헤더 미들웨어를 실행하려면 전달된 헤더 미들웨어 순서를 참조하세요.
기본 제공 미들웨어
ASP.NET Core 최신 릴리스에는 다음 미들웨어가 포함되어 있습니다.
UI 스택 열에는 미들웨어가 사용되는 일반적인 UI 스택이 표시됩니다. [All, Blazor Web App (BWA), Razor Pages and MVC(RP/MVC)].
주문 열은 요청 처리 파이프라인의 미들웨어 배치 및 미들웨어가 요청 처리를 중지할 수 있는 조건에 대한 정보를 제공합니다. 미들웨어가 요청 처리 파이프라인을 단락(short-circuit)하고 후속 미들웨어가 더는 요청을 처리하지 못하도록 하는 경우 이를 터미널 미들웨어라고 합니다. 쇼트서킷에 대한 자세한 내용은 WebApplication를 사용하여 미들웨어 파이프라인 만들기 섹션을 참조하세요.
| 미들웨어 | 설명 | UI 스택 | 순서 |
|---|---|---|---|
| 위조 방지 | 요청 위조 방지 지원을 제공합니다. | All | 인증 및 권한 부여 후, 엔드포인트 전에. |
| 인증 | 인증 지원을 제공합니다. | All | 이전 HttpContext.User 은 필수입니다. OAuth 콜백에 대한 터미널. |
| 승인 | 권한 부여 지원을 제공합니다. | All | 인증 미들웨어 직후. |
| Cookie 정책 | 개인 정보 저장과 관련한 사용자의 동의를 추적하고 cookie 필드(예: secure 및 SameSite)에 대해 최소한의 표준을 적용합니다. |
All | 쿠키를 발행하는 미들웨어가 실행되기 전에. 예: 인증, 세션, MVC(TempData). |
| CORS | 원본 간 리소스 공유를 구성합니다. | All | CORS를 사용하는 미들웨어 이전
UseCors은 UseResponseCaching 전에 사용해야 합니다. 자세한 내용은 UseCORS가 UseResponseCaching보다 앞서야 하는지는 명확하지 않습니다 (dotnet/aspnetcore #23218). |
| 개발자 예외 페이지 | 환경에서만 사용하기 위한 오류 정보가 포함된 Development 페이지를 생성합니다. |
All | 오류를 생성하는 미들웨어 이전. 프로젝트 템플릿은 환경이 Development일 때 이 미들웨어를 파이프라인의 첫 번째 미들웨어로 자동으로 등록합니다. |
| 진단 | 개발자 예외 페이지, 예외 처리, 상태 코드 페이지 및 새 앱에 대한 기본 웹 페이지를 제공하는 몇 가지 개별 미들웨어. | All | 오류를 생성하는 미들웨어 이전. 예외가 발생하거나 새 앱의 기본 웹 페이지를 처리하는 터미널입니다. |
| 전달된 헤더 | 프록시된 헤더를 현재 요청에 전달합니다. | All | 업데이트된 필드를 소모하는 미들웨어 이전에. 예: 체계, 호스트, 클라이언트 IP, 메서드. |
| 상태 확인 | ASP.NET Core 앱 및 그 종속성(데이터베이스 가용성 등)의 상태를 검사합니다. | All | 요청이 상태 검사 엔드포인트와 일치하는 경우 종료됩니다. |
| 헤더 전파 | 들어오는 요청에서 나가는 HTTP 클라이언트 요청으로 HTTP 헤더를 전파합니다. | ||
| All | |||
| HTTP 로깅 | HTTP 요청 및 응답을 로그합니다. | All | 미들웨어 파이프라인의 시작 부분에서. |
| HTTP 메서드 재정의 | 들어오는 POST 요청이 메서드를 재정의하도록 허용합니다. | All | 미들웨어가 업데이트된 메서드를 사용하기 전에. |
| HTTPS 리디렉션 | 모든 HTTP 요청을 HTTPS로 리디렉션합니다. | All | URL을 사용하는 미들웨어 이전. |
| HSTS(HTTP 엄격한 전송 보안) | 특별한 응답 헤더를 추가하는 보안 향상 미들웨어입니다. | All | 응답을 보내기 전과 요청을 수정하는 미들웨어 이후. 예: 전달된 헤더, URL 재작성. |
| MVC | MVC 및 Razor Pages를 사용하여 요청을 처리합니다. | RP/MVC | 요청이 경로와 일치하는 경우 터미널입니다. |
| OWIN | OWIN 기반 앱, 서버 및 미들웨어와 상호 운용됩니다. | RP/MVC | OWIN 미들웨어가 요청을 완전히 처리하는 경우 터미널입니다. |
| 출력 캐싱 | 구성에 따라 응답 캐싱을 지원합니다. | RP/MVC | 캐싱이 필요한 미들웨어 이전. UseRouting, UseCors, UseAuthentication및 UseAuthorization 앞에 UseOutputCache와야 합니다. |
| 응답 캐싱 | 응답 캐시에 대한 지원을 제공합니다. 이 미들웨어를 사용하려면 클라이언트 참여가 필요합니다. 전체 서버 제어에 출력 캐싱을 사용합니다. | RP/MVC | 캐싱이 필요한 미들웨어 이전. UseCors는 UseResponseCaching 앞에 와야 합니다. 응답 캐싱은 일반적으로 페이지와 같은 Razor UI 앱에 도움이 되지 않습니다. 브라우저는 일반적으로 캐싱을 방지하는 요청 헤더를 설정하기 때문입니다. 출력 캐싱은 UI 앱의 이점을 제공합니다. |
| 요청 압축 해제 | 요청의 압축 해제를 지원합니다. | All | 요청 본문을 읽은 미들웨어 이전. |
| 응답 압축 | 응답 압축에 대한 지원을 제공합니다. | All | 압축이 필요한 미들웨어 이전. |
| 요청 지역화 | 지역화 지원을 제공합니다. | All | 지역화 전 중요한 미들웨어. RouteDataRequestCultureProvider를 사용할 때는 라우팅 미들웨어 뒤에 위치해야 합니다. |
| 요청 시간 제한 | 요청 시간 제한, 전역 및 엔드포인트당 구성을 지원합니다. | All | UseRequestTimeouts 는 반드시 UseExceptionHandler, UseDeveloperExceptionPage, 그리고 UseRouting 다음에 와야 합니다. |
| 엔드포인트 라우팅. | 요청 경로를 정의하고 제한합니다. | All | 경로 매칭을 위한 터미널. |
| 스파 | SPA(단일 페이지 애플리케이션)의 기본 페이지를 반환하여 미들웨어 체인에서 이 시점의 모든 요청을 처리합니다. | All | 파이프라인에서 늦게 표시되므로 MVC 작업과 같은 정적 파일을 제공하기 위한 다른 미들웨어가 우선합니다. |
| 세션 | 사용자 세션 관리에 대한 지원을 제공합니다. | RP/MVC | 세션이 필요한 미들웨어들 이전. |
| 정적 파일 | 정적 파일 및 디렉터리 검색 처리에 대한 지원을 제공합니다. | All | 요청이 파일과 일치하는 경우 터미널입니다. |
| URL 재작성 | URL 재작성 및 요청 리디렉션에 대한 지원을 제공합니다. | All | URL을 사용하는 미들웨어 이전. |
| W3C 로깅 | W3C 확장 로그 파일 형식으로 서버 액세스 로그를 생성합니다. | All | 미들웨어 파이프라인의 시작 부분에서. |
| Blazor WebAssembly 디버깅 | Chromium 개발자 도구에서 클라이언트 측 렌더링(CSR)을 사용하는 Blazor Web App를 디버깅합니다. | BWA | 미들웨어 파이프라인의 시작 부분에서. |
| WebSocket | WebSocket 프로토콜을 활성화합니다. | All | 미들웨어가 WebSocket 요청을 수락하기 전에. |
추가 리소스
ASP.NET Core