Computer >> 컴퓨터 >  >> 프로그래밍 >> C#

C# ASP.NET Core에서 IApplicationBuilder.Use()와 Run()의 차이점 완벽 정리

ASP.NET Core 애플리케이션에서는 Startup 클래스의 Configure 메서드에서 IApplicationBuilder 인스턴스를 사용해 미들웨어를 구성할 수 있습니다. 이때 가장 많이 사용되는 두 가지 확장 메서드가 바로 Run()Use()입니다.

Run() 메서드란?

Run()IApplicationBuilder 인스턴스의 확장 메서드로, 애플리케이션 요청 파이프라인에 터미널(Terminal) 미들웨어를 추가합니다. 터미널 미들웨어란 파이프라인의 끝을 의미하며, 이 미들웨어가 실행된 후에는 다음 미들웨어로 제어가 넘어가지 않습니다.

Run 메서드는 IApplicationBuilder의 확장 메서드로, RequestDelegate 타입의 매개변수를 하나 받습니다.

Run 메서드 시그니처

public static void Run(this IApplicationBuilder app, RequestDelegate handler)

RequestDelegate 시그니처

public delegate Task RequestDelegate(HttpContext context);

예제

public class Startup{
    public Startup(){
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env,
    ILoggerFactory loggerFactory){
        // 여기서 IApplicationBuilder로 미들웨어를 구성합니다.
        app.Run(async (context) =>{
            await context.Response.WriteAsync("Hello World!");
        });
        // 설명을 위해 나머지 코드는 생략했습니다..
    }
}

위 예제의 미들웨어 함수가 비동기(async)가 아니라면, 실행이 완료될 때까지 스레드가 블로킹됩니다. 따라서 성능과 확장성을 높이려면 반드시 asyncawait 키워드를 사용해 비동기 방식으로 작성하는 것이 좋습니다.

public class Startup{
    public Startup(){
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env){
        app.Run(MyMiddleware);
    }
    private async Task MyMiddleware(HttpContext context){
        await context.Response.WriteAsync("Hello World! ");
    }
}

Run()으로 여러 미들웨어 구성하기

Run()은 터미널 미들웨어를 등록하기 때문에, 아래 코드처럼 Run()을 여러 번 호출하면 항상 첫 번째 Run만 실행되고 두 번째 Run은 절대 도달하지 않습니다.

public void Configure(IApplicationBuilder app, IHostingEnvironment env){
    app.Run(async (context) =>{
        await context.Response.WriteAsync("1st Middleware");
    });
    // 아래 코드는 절대 실행되지 않습니다
    app.Run(async (context) =>{
        await context.Response.WriteAsync(" 2nd Middleware");
    });
}

Use() 메서드란?

여러 개의 미들웨어를 순차적으로 구성하려면 Use() 확장 메서드를 사용해야 합니다. Use()Run()과 유사하지만, 다음 매개변수(next)를 포함하고 있어 이를 호출하면 파이프라인상의 다음 미들웨어로 제어를 넘길 수 있다는 점이 큰 차이입니다.

public void Configure(IApplicationBuilder app, IHostingEnvironment env){
    app.Use(async (context, next) =>{
        await context.Response.WriteAsync("1st Middleware!");
        await next();
    });
    app.Run(async (context) =>{
        await context.Response.WriteAsync("2nd Middleware");
    });
}

정리

  • Run(): 파이프라인을 종료하는 터미널 미들웨어를 추가하며, 이후 미들웨어는 실행되지 않습니다.
  • Use(): next 델리게이트를 통해 다음 미들웨어로 요청을 전달할 수 있어, 여러 미들웨어를 연결하는 데 적합합니다.

따라서 단순히 요청을 처리하고 종료하는 경우에는 Run()을, 요청 처리 후 다음 단계로 흐름을 계속 이어가야 하는 경우에는 Use()를 사용하는 것이 올바른 설계 방식입니다.