ASP.NET Core에서 앱 시작App startup in ASP.NET Core

작성자: Rick Anderson, Tom Dykstra, Luke LathamSteve SmithBy Rick Anderson, Tom Dykstra, Luke Latham, and Steve Smith

Startup 클래스는 서비스와 응용 프로그램의 요청 파이프라인을 구성합니다.The Startup class configures services and the app's request pipeline.

시작 클래스The Startup class

ASP.NET Core 앱은 규칙에 따라 Startup으로 이름이 지정된 Startup 클래스를 사용합니다.ASP.NET Core apps use a Startup class, which is named Startup by convention. Startup 클래스는:The Startup class:

  • 선택적으로 앱의 서비스를 구성하는 ConfigureServices 메서드를 포함합니다.Optionally includes a ConfigureServices method to configure the app's services. 서비스는 앱 기능을 제공하는 재사용 가능한 구성 요소입니다.A service is a reusable component that provides app functionality. 서비스는 ConfigureServices에서 등록되며 DI(종속성 주입) 또는 ApplicationServices를 통해 앱 전체에서 사용됩니다.Services are registered in ConfigureServices and consumed across the app via dependency injection (DI) or ApplicationServices.
  • 앱의 요청 처리 파이프라인을 만드는 Configure 메서드가 포함되어 있습니다.Includes a Configure method to create the app's request processing pipeline.

ConfigureServicesConfigure는 앱 시작 시 ASP.NET Core 런타임에 의해 호출됩니다.ConfigureServices and Configure are called by the ASP.NET Core runtime when the app starts:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}

앞의 샘플은 Razor Pages에 해당하며 MVC 버전도 비슷합니다.The preceding sample is for Razor Pages; the MVC version is similar.

public class Startup
{
    // Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        ...
    }

    // Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app)
    {
        ...
    }
}

앱의 호스트가 빌드될 때 Startup 클래스가 지정됩니다.The Startup class is specified when the app's host is built. Startup 클래스는 일반적으로 호스트 작성기에서 WebHostBuilderExtensions.UseStartup<TStartup> 메서드를 호출하여 지정됩니다.The Startup class is typically specified by calling the WebHostBuilderExtensions.UseStartup<TStartup> method on the host builder:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}
public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

호스트는 Startup 클래스 생성자에 사용할 수 있는 서비스를 제공합니다.The host provides services that are available to the Startup class constructor. 앱은 ConfigureServices를 통해 추가 서비스를 추가합니다.The app adds additional services via ConfigureServices. 그러면 호스트 및 앱 서비스 모두를 Configure 및 앱 전체에서 사용할 수 있습니다.Both the host and app services are available in Configure and throughout the app.

제네릭 호스트(IHostBuilder)를 사용할 경우 다음 서비스 유형만 Startup 생성자에 삽입할 수 있습니다.Only the following service types can be injected into the Startup constructor when using the Generic Host (IHostBuilder):

public class Startup
{
    private readonly IWebHostEnvironment _env;

    public Startup(IConfiguration configuration, IWebHostEnvironment env)
    {
        Configuration = configuration;
        _env = env;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        if (_env.IsDevelopment())
        {
        }
        else
        {
        }
    }
}

Configure 메서드가 호출될 때까지 대부분의 서비스를 사용할 수 없습니다.Most services are not available until the Configure method is called.

호스트는 Startup 클래스 생성자에 사용할 수 있는 서비스를 제공합니다.The host provides services that are available to the Startup class constructor. 앱은 ConfigureServices를 통해 추가 서비스를 추가합니다.The app adds additional services via ConfigureServices. 그러면 호스트 및 앱 서비스 모두를 Configure 및 앱 전체에서 사용할 수 있습니다.Both the host and app services are then available in Configure and throughout the app.

Startup 클래스에 대한 종속성 주입의 일반적인 용도는 다음을 삽입하는 것입니다.A common use of dependency injection into the Startup class is to inject:

public class Startup
{
    private readonly IHostingEnvironment _env;
    private readonly IConfiguration _config;
    private readonly ILoggerFactory _loggerFactory;

    public Startup(IHostingEnvironment env, IConfiguration config, 
        ILoggerFactory loggerFactory)
    {
        _env = env;
        _config = config;
        _loggerFactory = loggerFactory;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        var logger = _loggerFactory.CreateLogger<Startup>();

        if (_env.IsDevelopment())
        {
            // Development service configuration

            logger.LogInformation("Development environment");
        }
        else
        {
            // Non-development service configuration

            logger.LogInformation("Environment: {EnvironmentName}", _env.EnvironmentName);
        }

        // Configuration is available during startup.
        // Examples:
        //   _config["key"]
        //   _config["subsection:suboption1"]
    }
}

Configure 메서드가 호출될 때까지 대부분의 서비스를 사용할 수 없습니다.Most services are not available until the Configure method is called.

여러 StartupMultiple Startup

앱에서 다양한 환경(예: StartupDevelopment)에 대해 별도의 Startup 클래스를 정의하면 런타임에 적절한 Startup 클래스가 선택됩니다.When the app defines separate Startup classes for different environments (for example, StartupDevelopment), the appropriate Startup class is selected at runtime. 이름 접미사가 현재 환경과 일치하는 클래스에 우선 순위가 부여됩니다.The class whose name suffix matches the current environment is prioritized. 앱이 개발 환경에서 실행되고 Startup 클래스 및 StartupDevelopment 클래스 모두를 포함하는 경우 StartupDevelopment 클래스가 사용됩니다.If the app is run in the Development environment and includes both a Startup class and a StartupDevelopment class, the StartupDevelopment class is used. 자세한 내용은 여러 환경 사용을 참조하세요.For more information, see Use multiple environments.

호스트에 대한 자세한 내용은 호스트를 참조하세요.See The host for more information on the host. 시작하는 동안 오류를 처리하는 방법은 시작 예외 처리를 참조하세요.For information on handling errors during startup, see Startup exception handling.

ConfigureServices 메서드The ConfigureServices method

ConfigureServices 메서드는 다음과 같습니다.The ConfigureServices method is:

  • 선택 사항입니다.Optional.
  • Configure 메서드 전에 호스트에 의해 호출되어 앱의 서비스를 구성합니다.Called by the host before the Configure method to configure the app's services.
  • 여기서 구성 옵션이 규칙에 의해 설정됩니다.Where configuration options are set by convention.

호스트는 Startup 메서드가 호출되기 전에 일부 서비스를 구성할 수 있습니다.The host may configure some services before Startup methods are called. 자세한 내용은 호스트를 참조하세요.For more information, see The host.

실질적인 설정이 필요한 기능의 경우 IServiceCollectionAdd{Service} 확장 메서드가 있습니다.For features that require substantial setup, there are Add{Service} extension methods on IServiceCollection. 예를 들어 AddDbContext, AddDefaultIdentity, AddEntityFrameworkStores 및 AddRazorPages가 있습니다.For example, AddDbContext, AddDefaultIdentity, AddEntityFrameworkStores, and AddRazorPages:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>(
            options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddRazorPages();
    }
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>()
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();


    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
}

서비스 컨테이너에 서비스를 추가하면 앱 내 및 Configure 메서드에서 사용할 수 있습니다.Adding services to the service container makes them available within the app and in the Configure method. 서비스는 종속성 주입 또는 ApplicationServices를 통해 해결됩니다.The services are resolved via dependency injection or from ApplicationServices.

SetCompatibilityVersion에 대한 자세한 내용은 SetCompatibilityVersion을 참조하세요.See SetCompatibilityVersion for more information on SetCompatibilityVersion.

Configure 메서드The Configure method

Configure 메서드는 앱이 HTTP 요청에 응답하는 방식을 지정하는 데 사용됩니다.The Configure method is used to specify how the app responds to HTTP requests. 요청 파이프라인은 미들웨어 구성 요소를 IApplicationBuilder 인스턴스에 추가하여 구성됩니다.The request pipeline is configured by adding middleware components to an IApplicationBuilder instance. IApplicationBuilderConfigure 메서드에 사용할 수 있지만 서비스 컨테이너에 등록되지 않습니다.IApplicationBuilder is available to the Configure method, but it isn't registered in the service container. 호스팅이 IApplicationBuilder를 만들고 Configure에 직접 전달합니다.Hosting creates an IApplicationBuilder and passes it directly to Configure.

ASP.NET Core 템플릿은 다음을 지원하는 파이프라인을 구성합니다.The ASP.NET Core templates configure the pipeline with support for:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
        });
    }
}

앞의 샘플은 Razor Pages에 해당하며 MVC 버전도 비슷합니다.The preceding sample is for Razor Pages; the MVC version is similar.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseMvc();
}

Use 확장 메서드는 요청 파이프라인에 하나 이상의 미들웨어 구성 요소를 추가합니다.Each Use extension method adds one or more middleware components to the request pipeline. 예를 들어 UseStaticFiles정적 파일을 제공하도록 미들웨어를 구성합니다.For instance, UseStaticFiles configures middleware to serve static files.

요청 파이프라인의 각 미들웨어 구성 요소는 파이프라인의 다음 구성 요소를 호출하거나 적절한 경우 체인을 단락(short-circuiting)하는 일을 담당합니다.Each middleware component in the request pipeline is responsible for invoking the next component in the pipeline or short-circuiting the chain, if appropriate.

IWebHostEnvironment, ILoggerFactory 같은 추가 서비스 또는 ConfigureServices에 정의된 항목은 Configure 메서드 시그니처에서 지정할 수 있습니다.Additional services, such as IWebHostEnvironment, ILoggerFactory, or anything defined in ConfigureServices, can be specified in the Configure method signature. 이 서비스를 사용할 수 있는 경우 삽입됩니다.These services are injected if they're available.

IHostingEnvironmentILoggerFactory 같은 추가 서비스 또는 ConfigureServices에 정의된 항목은 Configure 메서드 시그니처에서 지정할 수 있습니다.Additional services, such as IHostingEnvironment and ILoggerFactory, or anything defined in ConfigureServices, can be specified in the Configure method signature. 이 서비스를 사용할 수 있는 경우 삽입됩니다.These services are injected if they're available.

IApplicationBuilder를 사용하는 방법 및 미들웨어 처리 순서에 대한 자세한 내용은 ASP.NET Core 미들웨어 기본 사항를 참조하세요.For more information on how to use IApplicationBuilder and the order of middleware processing, see ASP.NET Core 미들웨어 기본 사항.

Startup을 사용하지 않고 서비스 구성Configure services without Startup

Startup 클래스를 사용하지 않고 서비스 및 요청 처리 파이프라인을 구성하려면 호스트 작성기에서 ConfigureServicesConfigure 편의성 메서드를 호출합니다.To configure services and the request processing pipeline without using a Startup class, call ConfigureServices and Configure convenience methods on the host builder. ConfigureServices에 대한 여러 호출은 서로 추가합니다.Multiple calls to ConfigureServices append to one another. 여러 Configure 메서드 호출이 있는 경우 마지막 Configure 호출이 사용됩니다.If multiple Configure method calls exist, the last Configure call is used.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.ConfigureServices(services =>
                {
                    services.AddControllersWithViews();
                })
                .Configure(app =>
                {
                    var loggerFactory = app.ApplicationServices
                        .GetRequiredService<ILoggerFactory>();
                    var logger = loggerFactory.CreateLogger<Program>();
                    var env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>();
                    var config = app.ApplicationServices.GetRequiredService<IConfiguration>();

                    logger.LogInformation("Logged in Configure");

                    if (env.IsDevelopment())
                    {
                        app.UseDeveloperExceptionPage();
                    }
                    else
                    {
                        app.UseExceptionHandler("/Home/Error");
                        app.UseHsts();
                    }

                    var configValue = config["MyConfigKey"];
                });
            });
        });
}
public class Program
{
    public static IHostingEnvironment HostingEnvironment { get; set; }
    public static IConfiguration Configuration { get; set; }

    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
            })
            .ConfigureServices(services =>
            {
                ...
            })
            .Configure(app =>
            {
                var loggerFactory = app.ApplicationServices
                    .GetRequiredService<ILoggerFactory>();
                var logger = loggerFactory.CreateLogger<Program>();
                var env = app.ApplicationServices.GetRequiredService<IHostingEnvironment>();
                var config = app.ApplicationServices.GetRequiredService<IConfiguration>();

                logger.LogInformation("Logged in Configure");

                if (env.IsDevelopment())
                {
                    ...
                }
                else
                {
                    ...
                }

                var configValue = config["subsection:suboption1"];

                ...
            });
}

시작 필터를 이용한 Startup 확장Extend Startup with startup filters

IStartupFilter는 다음 용도로 사용합니다.Use IStartupFilter:

  • Use{Middleware}를 명시적으로 호출하지 않고 앱의 Configure 미들웨어 파이프라인의 시작 또는 끝 부분에서 미들웨어를 구성합니다.To configure middleware at the beginning or end of an app's Configure middleware pipeline without an explicit call to Use{Middleware}. IStartupFilter는 ASP.NET Core에서 앱 작성자가 명시적으로 기본 미들웨어를 등록할 필요 없이 파이프라인의 시작 부분에 기본값을 추가하는 데 사용됩니다.IStartupFilter is used by ASP.NET Core to add defaults to the beginning of the pipeline without having to make the app author explicitly register the default middleware. IStartupFilter는 앱 작성자를 대신하여 다른 구성 요소 호출 Use{Middleware}를 허용합니다.IStartupFilter allows a different component call Use{Middleware} on behalf of the app author.
  • Configure 메서드의 파이프라인을 만듭니다.To create a pipeline of Configure methods. IStartupFilter.Configure는 라이브러리에서 추가된 미들웨어 이전 또는 이후에 실행할 미들웨어를 설정할 수 있습니다.IStartupFilter.Configure can set a middleware to run before or after middleware added by libraries.

IStartupFilterAction<IApplicationBuilder>를 받고 반환하는 Configure를 구현합니다.IStartupFilter implements Configure, which receives and returns an Action<IApplicationBuilder>. IApplicationBuilder는 앱의 요청 파이프라인을 구성하는 클래스를 정의합니다.An IApplicationBuilder defines a class to configure an app's request pipeline. 자세한 내용은 IApplicationBuilder로 미들웨어 파이프라인 만들기를 참조하세요.For more information, see Create a middleware pipeline with IApplicationBuilder.

IStartupFilter는 요청 파이프라인에서 하나 이상의 미들웨어를 추가할 수 있습니다.Each IStartupFilter can add one or more middlewares in the request pipeline. 필터는 서비스 컨테이너에 추가된 순서대로 호출됩니다.The filters are invoked in the order they were added to the service container. 필터는 다음 필터에 컨트롤을 전달하기 전이나 후에 미들웨어를 추가할 수 있으므로 앱 파이프라인의 시작 또는 끝에 추가합니다.Filters may add middleware before or after passing control to the next filter, thus they append to the beginning or end of the app pipeline.

다음 예제에서는 IStartupFilter를 사용하여 미들웨어를 등록하는 방법을 보여줍니다.The following example demonstrates how to register a middleware with IStartupFilter. RequestSetOptionsMiddleware 미들웨어는 쿼리 문자열 매개 변수에서 옵션 값을 설정합니다.The RequestSetOptionsMiddleware middleware sets an options value from a query string parameter:

public class RequestSetOptionsMiddleware
{
    private readonly RequestDelegate _next;

    public RequestSetOptionsMiddleware( RequestDelegate next )
    {
        _next = next;
    }

    // Test with https://localhost:5001/Privacy/?option=Hello
    public async Task Invoke(HttpContext httpContext)
    {
        var option = httpContext.Request.Query["option"];

        if (!string.IsNullOrWhiteSpace(option))
        {
            httpContext.Items["option"] = WebUtility.HtmlEncode(option);
        }

        await _next(httpContext);
    }
}

RequestSetOptionsMiddlewareRequestSetOptionsStartupFilter 클래스에서 구성됩니다.The RequestSetOptionsMiddleware is configured in the RequestSetOptionsStartupFilter class:

public class RequestSetOptionsStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        return builder =>
        {
            builder.UseMiddleware<RequestSetOptionsMiddleware>();
            next(builder);
        };
    }
}
public class RequestSetOptionsMiddleware
{
    private readonly RequestDelegate _next;
    private IOptions<AppOptions> _injectedOptions;

    public RequestSetOptionsMiddleware(
        RequestDelegate next, IOptions<AppOptions> injectedOptions)
    {
        _next = next;
        _injectedOptions = injectedOptions;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        Console.WriteLine("RequestSetOptionsMiddleware.Invoke");

        var option = httpContext.Request.Query["option"];

        if (!string.IsNullOrWhiteSpace(option))
        {
            _injectedOptions.Value.Option = WebUtility.HtmlEncode(option);
        }

        await _next(httpContext);
    }
}

RequestSetOptionsMiddlewareRequestSetOptionsStartupFilter 클래스에서 구성됩니다.The RequestSetOptionsMiddleware is configured in the RequestSetOptionsStartupFilter class:

public class RequestSetOptionsStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        return builder =>
        {
            builder.UseMiddleware<RequestSetOptionsMiddleware>();
            next(builder);
        };
    }
}

IStartupFilterConfigureServices의 서비스 컨테이너에 등록됩니다.The IStartupFilter is registered in the service container in ConfigureServices.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
           .ConfigureAppConfiguration((hostingContext, config) =>
           {
           })
         .ConfigureWebHostDefaults(webBuilder =>
         {
             webBuilder.UseStartup<Startup>();
         })
        .ConfigureServices(services =>
        {
            services.AddTransient<IStartupFilter,
                      RequestSetOptionsStartupFilter>();
        });
}
WebHost.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddTransient<IStartupFilter, 
            RequestSetOptionsStartupFilter>();
    })
    .UseStartup<Startup>()
    .Build();

option에 대한 쿼리 문자열 매개 변수가 제공되는 경우 미들웨어는 ASP.NET Core 미들웨어가 응답을 렌더링하기 전에 값 할당을 처리합니다.When a query string parameter for option is provided, the middleware processes the value assignment before the ASP.NET Core middleware renders the response.

미들웨어 실행 순서는 IStartupFilter 등록 순서로 설정됩니다.Middleware execution order is set by the order of IStartupFilter registrations:

  • 여러 IStartupFilter 구현은 동일한 개체와 상호 작용할 수 있습니다.Multiple IStartupFilter implementations may interact with the same objects. 순서 지정이 중요한 경우 해당 미들웨어가 실행해야 하는 순서와 일치하도록 해당 IStartupFilter 서비스 등록의 순서를 지정합니다.If ordering is important, order their IStartupFilter service registrations to match the order that their middlewares should run.

  • 라이브러리는 IStartupFilter로 등록된 다른 앱 미들웨어 전이나 후에 실행하는 하나 이상의 IStartupFilter 구현으로 미들웨어를 추가할 수 있습니다.Libraries may add middleware with one or more IStartupFilter implementations that run before or after other app middleware registered with IStartupFilter. 라이브러리의 IStartupFilter에 의해 추가되는 미들웨어 전에 IStartupFilter 미들웨어를 호출하려면 다음을 수행합니다.To invoke an IStartupFilter middleware before a middleware added by a library's IStartupFilter:

    • 라이브러리가 서비스 컨테이너에 추가되기 전에 서비스 등록의 위치를 지정합니다.Position the service registration before the library is added to the service container.
    • 나중에 호출하려면 라이브러리가 추가된 후에 서비스 등록의 위치를 지정합니다.To invoke afterward, position the service registration after the library is added.

시작 시 외부 어셈블리로부터 구성 추가Add configuration at startup from an external assembly

IHostingStartup 구현은 시작 시 앱의 Startup 클래스 외부에 있는 외부 어셈블리에서 앱에 향상된 기능을 추가할 수 있습니다.An IHostingStartup implementation allows adding enhancements to an app at startup from an external assembly outside of the app's Startup class. 자세한 내용은 ASP.NET Core에서 호스팅 시작 어셈블리 사용을 참조하세요.For more information, see ASP.NET Core에서 호스팅 시작 어셈블리 사용.

추가 자료Additional resources