다음을 통해 공유


MVC 또는 Razor Pages와 ASP.NET Core Razor 구성 요소 통합

참고 항목

이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 9 버전을 참조 하세요.

Warning

이 버전의 ASP.NET Core는 더 이상 지원되지 않습니다. 자세한 내용은 .NET 및 .NET Core 지원 정책을 참조 하세요. 현재 릴리스는 이 문서의 .NET 9 버전을 참조 하세요.

Important

이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.

현재 릴리스는 이 문서의 .NET 9 버전을 참조 하세요.

Razor 구성 요소를 Pages 또는 MVC 앱에 Razor 통합할 수 있습니다. 페이지나 뷰를 렌더링할 때 구성 요소를 동시에 미리 렌더링할 수 있습니다.

Important

ASP.NET Core 릴리스의 프레임워크 변경으로 인해 이 문서의 다양한 지침 집합이 제공되었습니다. 이 문서의 지침을 사용하기 전에 이 문서의 맨 위에 있는 문서 버전 선택기가 앱에 사용하려는 ASP.NET Core 버전과 일치하는지 확인합니다.

미리 렌더링은 검색 엔진이 페이지 순위를 계산하는 데 사용할 수 있는 초기 HTTP 응답에 대한 콘텐츠를 렌더링하여 SEO(검색 엔진 최적화)를 향상시킬 수 있습니다.

프로젝트를 구성한 후 프로젝트 요구 사항에 따라 다음 섹션의 지침을 따릅니다.

구성

다음 지침을 사용하여 구성 요소를 기존 Razor Pages 또는 MVC 앱의 페이지 또는 뷰에 통합 Razor 합니다.

  1. 다음 콘텐츠를 사용하여 프로젝트 루트 폴더에 가져오기 파일을 추가합니다. {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 변경합니다.

    _Imports.razor:

    @using System.Net.Http
    @using Microsoft.AspNetCore.Authorization
    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.Forms
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.AspNetCore.Components.Web
    @using Microsoft.AspNetCore.Components.Web.Virtualization
    @using Microsoft.JSInterop
    @using {APP NAMESPACE}
    
  2. 프로젝트의 레이아웃 파일(Razor Pages 앱의 Pages/Shared/_Layout.cshtml 또는 MVC 앱의 Views/Shared/_Layout.cshtml)에서

    • <head> 요소에 다음 <base> 태그 및 HeadOutlet 구성 요소 태그 도우미를 추가합니다.

      <base href="~/" />
      <component type="typeof(Microsoft.AspNetCore.Components.Web.HeadOutlet)" 
          render-mode="ServerPrerendered" />
      

      위의 예제에서 href 값(‘앱 기본 경로’)은 앱이 루트 URL 경로(/)에 있는 것으로 가정합니다. 앱이 하위 애플리케이션인 경우, ASP.NET Core Blazor 호스트 및 배포 문서의 앱 기본 경로 섹션에 설명된 지침을 따르세요.

      HeadOutlet 구성 요소는 Razor 구성 요소에서 설정한 페이지 제목(PageTitle 구성 요소) 및 기타 헤드 요소(HeadContent 구성 요소)에 대한 헤드(<head>) 콘텐츠를 렌더링하는 데 사용됩니다. 자세한 내용은 ASP.NET Core Blazor 앱의 헤드 콘텐츠 제어를 참조하세요.

    • Scripts 렌더링 섹션(@await RenderSectionAsync(...)) 바로 앞에 blazor.server.js 스크립트의 <script> 태그를 추가합니다.

      <script src="_framework/blazor.server.js"></script>
      

      프레임워크는 앱에 blazor.server.js 스크립트를 추가합니다. 앱에 blazor.server.js 스크립트 파일을 수동으로 추가할 필요는 없습니다.

    참고 항목

    일반적으로 레이아웃은 _ViewStart.cshtml 파일을 통해 로드됩니다.

  3. 서비스가 등록된 Program.cs에 Blazor Server 서비스를 등록합니다.

    builder.Services.AddServerSideBlazor();
    
  4. Blazor 허브 엔드포인트를 경로가 매핑되는 Program.cs의 엔드포인트에 추가합니다. MapRazorPages(Razor Pages) 또는 MapControllerRoute(MVC)에 대한 호출 뒤에 다음 라인을 배치합니다.

    app.MapBlazorHub();
    
  5. 페이지 또는 뷰에 구성 요소를 통합합니다. 예를 들어 프로젝트의 Shared 폴더에 Counter구성 요소를 추가합니다.

    Pages/Shared/Counter.razor(Razor 페이지) 또는 Views/Shared/Counter.razor(MVC):

    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    

    Razor 페이지:

    Razor 페이지 앱의 프로젝트 Index 페이지에서 Counter 구성 요소의 네임스페이스를 추가하고 이 구성 요소를 페이지에 포함합니다. Index 페이지가 로드되면 Counter 구성 요소가 페이지에 미리 렌더링됩니다. 다음 예제에서는 {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 바꿉니다.

    Pages/Index.cshtml:

    @page
    @using {APP NAMESPACE}.Pages.Shared
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }
    
    <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    

    MVC:

    MVC 앱의 프로젝트 Index뷰에서 Counter 구성 요소 네임스페이스를 추가하고 해당 구성 요소를 뷰에 포함합니다. Index 뷰가 로드되면 Counter 구성 요소가 페이지에서 미리 렌더링됩니다. 다음 예제에서는 {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 바꿉니다.

    Views/Home/Index.cshtml:

    @using {APP NAMESPACE}.Views.Shared
    @{
        ViewData["Title"] = "Home Page";
    }
    
    <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    

자세한 내용은 페이지 또는 뷰에서 구성 요소 렌더링 섹션을 참조하세요.

Razor Pages 앱에서 라우팅 가능한 구성 요소 사용

‘이 섹션에서는 사용자 요청에서 직접 라우팅할 수 있는 구성 요소를 추가하는 방법을 설명합니다.’

Razor Pages 앱에서 라우팅 가능한 Razor 구성 요소를 지원하려면 다음을 수행합니다.

  1. 구성 섹션의 지침을 따릅니다.

  2. 다음 콘텐츠를 사용하여 프로젝트 루트에 App 구성 요소를 추가합니다.

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <p role="alert">Sorry, there's nothing at this address.</p>
        </NotFound>
    </Router>
    
  3. 다음 콘텐츠로 _Host 페이지를 프로젝트에 추가합니다. {APP NAMESPACE} 자리 표시자를 앱의 네임스페이스로 바꿉니다.

    Pages/_Host.cshtml:

    @page
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    
    <component type="typeof(App)" render-mode="ServerPrerendered" />
    

    참고 항목

    앞의 예제에서는 HeadOutlet 구성 요소 및 Blazor 스크립트(_framework/blazor.server.js)가 앱의 레이아웃에 의해 렌더링된다고 가정합니다. 자세한 내용은 구성 섹션을 참조하세요.

    RenderModeApp 구성 요소에 대해 다음을 구성합니다.

    • 페이지에 미리 렌더링할지 여부
    • 페이지에 정적 HTML로 렌더링할지 여부 또는 사용자 에이전트에서 Blazor 앱을 부트스트랩하는 데 필요한 정보를 포함할지 여부

    매개 변수 전달과 RenderMode 구성을 포함하여 구성 요소 태그 도우미에 대한 자세한 내용은 ASP.NET Core의 구성 요소 태그 도우미를 참조하세요.

  4. Program.cs 엔드포인트에서 _Host 페이지의 우선 순위가 낮은 경로를 마지막 엔드포인트로 추가합니다.

    app.MapFallbackToPage("/_Host");
    
  5. 라우팅 가능한 구성 요소를 프로젝트에 추가합니다. 다음 예제는 Blazor 프로젝트 템플릿의 Counter 구성 요소를 기반으로 하는 RoutableCounter 구성 요소입니다.

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <PageTitle>Routable Counter</PageTitle>
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  6. 프로젝트를 실행하고 /routable-counter에서 라우팅할 수 있는 RoutableCounter 구성 요소로 이동합니다.

네임스페이스에 대한 자세한 내용은 구성 요소 네임스페이스 섹션을 참조하세요.

MVC 앱에서 라우팅 가능한 구성 요소 사용

‘이 섹션에서는 사용자 요청에서 직접 라우팅할 수 있는 구성 요소를 추가하는 방법을 설명합니다.’

MVC 앱에서 라우팅 가능한 Razor 구성 요소를 지원하려면 다음을 수행합니다.

  1. 구성 섹션의 지침을 따릅니다.

  2. 다음 콘텐츠를 사용하여 프로젝트 루트에 App 구성 요소를 추가합니다.

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <p role="alert">Sorry, there's nothing at this address.</p>
        </NotFound>
    </Router>
    
  3. 다음 콘텐츠를 사용하여 _Host 뷰를 프로젝트에 추가합니다. {APP NAMESPACE} 자리 표시자를 앱의 네임스페이스로 바꿉니다.

    Views/Home/_Host.cshtml:

    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    
    <component type="typeof(App)" render-mode="ServerPrerendered" />
    

    참고 항목

    앞의 예제에서는 HeadOutlet 구성 요소 및 Blazor 스크립트(_framework/blazor.server.js)가 앱의 레이아웃에 의해 렌더링된다고 가정합니다. 자세한 내용은 구성 섹션을 참조하세요.

    RenderModeApp 구성 요소에 대해 다음을 구성합니다.

    • 페이지에 미리 렌더링할지 여부
    • 페이지에 정적 HTML로 렌더링할지 여부 또는 사용자 에이전트에서 Blazor 앱을 부트스트랩하는 데 필요한 정보를 포함할지 여부

    매개 변수 전달과 RenderMode 구성을 포함하여 구성 요소 태그 도우미에 대한 자세한 내용은 ASP.NET Core의 구성 요소 태그 도우미를 참조하세요.

  4. Home 컨트롤러에 작업을 추가합니다.

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Program.cs 엔드포인트에 _Host 보기를 반환하는 컨트롤러 작업에 우선 순위가 낮은 경로를 추가합니다.

    app.MapFallbackToController("Blazor", "Home");
    
  6. MVC 앱에 Pages 폴더를 만들고 라우팅 가능한 구성 요소를 추가합니다. 다음 예제는 Blazor 프로젝트 템플릿의 Counter 구성 요소를 기반으로 하는 RoutableCounter 구성 요소입니다.

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <PageTitle>Routable Counter</PageTitle>
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  7. 프로젝트를 실행하고 /routable-counter에서 라우팅할 수 있는 RoutableCounter 구성 요소로 이동합니다.

네임스페이스에 대한 자세한 내용은 구성 요소 네임스페이스 섹션을 참조하세요.

페이지 또는 뷰에서 구성 요소 렌더링

‘이 섹션에서는 사용자 요청에서 직접 구성 요소를 라우팅할 수 없는 페이지 또는 뷰에 구성 요소를 추가하는 방법을 설명합니다.’

페이지 또는 뷰에서 구성 요소를 렌더링하려면 구성 요소 태그 도우미를 사용합니다.

상태 저장 대화형 구성 요소 렌더링

Razor 페이지 또는 뷰에 상태 저장 대화형 구성 요소를 추가할 수 있습니다.

페이지 또는 뷰를 렌더링하는 경우와 관련해서 다음 사항을 확인합니다.

  • 구성 요소가 페이지 또는 뷰와 함께 미리 렌더링됩니다.
  • 미리 렌더링하는 데 사용된 초기 구성 요소 상태가 손실됩니다.
  • SignalR 연결이 완료되면 새 구성 요소 상태가 생성됩니다.

다음 Razor 페이지는 Counter 구성 요소를 렌더링합니다.

<h1>Razor Page</h1>

<component type="typeof(Counter)" render-mode="ServerPrerendered" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

자세한 내용은 ASP.NET Core 구성 요소 태그 도우미를 참조하세요.

비대화형 구성 요소 렌더링

다음 Razor 페이지에서 Counter 구성 요소는 폼을 통해 지정된 초기 값을 사용하여 정적으로 렌더링됩니다. 구성 요소가 정적으로 렌더링되므로 구성 요소는 대화형이 아닙니다.

<h1>Razor Page</h1>

<form>
    <input type="number" asp-for="InitialValue" />
    <button type="submit">Set initial value</button>
</form>

<component type="typeof(Counter)" render-mode="Static" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

자세한 내용은 ASP.NET Core 구성 요소 태그 도우미를 참조하세요.

구성 요소 네임스페이스

사용자 지정 폴더를 사용하여 프로젝트의 Razor 구성 요소를 저장하는 경우, 폴더를 나타내는 네임스페이스를 페이지/뷰 또는 _ViewImports.cshtml 파일에 추가합니다. 다음 예제에서

  • 구성 요소는 프로젝트의 Components 폴더에 저장됩니다.
  • {APP NAMESPACE} 자리 표시자는 프로젝트의 네임스페이스입니다. Components은 폴더의 이름을 나타냅니다.
@using {APP NAMESPACE}.Components

_ViewImports.cshtml 파일은 Razor Pages 앱의 Pages 폴더 또는 MVC 앱의 Views 폴더에 있습니다.

자세한 내용은 ASP.NET Core Razor 구성 요소를 참조하세요.

미리 렌더링된 상태 유지

미리 렌더링된 상태를 유지하지 않으면 미리 렌더링하는 동안 사용된 상태를 잃게 되며 앱이 완전히 로드되면 다시 만들어야 합니다. 상태가 비동기적으로 설정된 경우 미리 렌더링된 UI가 임시 자리 표시자로 대체된 다음, 완전히 다시 렌더링되면 UI가 깜박일 수 있습니다.

미리 렌더링된 구성 요소의 상태를 유지하려면 지속 구성 요소 상태 태그 도우미(참조 원본)를 사용합니다. 구성 요소를 미리 렌더링하는 앱에서 _Host 페이지의 닫는 </body> 태그 안에 태그 도우미의 태그인 <persist-component-state />를 추가합니다.

참고 항목

.NET 참조 원본의 설명서 링크는 일반적으로 다음 릴리스의 .NET을 위한 현재 개발을 나타내는 리포지토리의 기본 분기를 로드합니다. 특정 릴리스를 위한 태그를 선택하려면 Switch branches or tags(분기 또는 태그 전환) 드롭다운 목록을 사용합니다. 자세한 내용은 ASP.NET Core 소스 코드(dotnet/AspNetCore.Docs #26205)의 버전 태그를 선택하는 방법을 참조하세요.

Pages/_Host.cshtml 앱에 있는 ServerPrerendered 앱의 Blazor 경우Blazor Server:

<body>
    ...

    <persist-component-state />
</body>

PersistentComponentState 서비스를 사용하여 유지할 상태를 결정합니다. PersistentComponentState.RegisterOnPersisting은 앱이 일시 중지되기 전에 구성 요소 상태를 유지하도록 콜백을 등록합니다. 애플리케이션이 다시 시작될 때 상태가 검색됩니다.

다음 예제에서

  • {TYPE} 자리 표시자는 유지할 데이터 형식을 나타냅니다(예: WeatherForecast[]).
  • {TOKEN} 자리 표시자는 상태 식별자 문자열입니다(예: fetchdata).
@implements IDisposable
@inject PersistentComponentState ApplicationState

...

@code {
    private {TYPE} data;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        persistingSubscription = 
            ApplicationState.RegisterOnPersisting(PersistData);

        if (!ApplicationState.TryTakeFromJson<{TYPE}>(
            "{TOKEN}", out var restored))
        {
            data = await ...;
        }
        else
        {
            data = restored!;
        }
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson("{TOKEN}", data);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

다음 예제는 프로젝트 템플릿을 기반으로 Blazor 구성 요소의 FetchData 업데이트된 버전입니다. WeatherForecastPreserveState 구성 요소는 미리 렌더링하는 동안 날씨 예측 상태를 유지한 다음, 상태를 검색하여 구성 요소를 초기화합니다. 구성 요소 상태 유지 태그 도우미는 모든 구성 요소 호출 후 구성 요소 상태를 유지합니다.

Pages/WeatherForecastPreserveState.razor:

@page "/weather-forecast-preserve-state"
@using BlazorSample.Shared
@implements IDisposable
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState

<PageTitle>Weather Forecast</PageTitle>

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        persistingSubscription = 
            ApplicationState.RegisterOnPersisting(PersistForecasts);

        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            "fetchdata", out var restored))
        {
            forecasts = 
                await WeatherForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
        }
        else
        {
            forecasts = restored!;
        }
    }

    private Task PersistForecasts()
    {
        ApplicationState.PersistAsJson("fetchdata", forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

미리 렌더링하는 동안 사용된 것과 동일한 상태로 구성 요소를 초기화하면 비용이 많이 드는 초기화 단계가 한 번만 실행됩니다. 렌더링된 UI도 미리 렌더링된 UI와 일치하므로 브라우저에서 깜박임이 발생하지 않습니다.

지속형 미리 렌더링된 상태는 구성 요소 상태를 복원하는 데 사용되는 클라이언트로 전송됩니다. ASP.NET Core Data Protection 은 데이터가 앱에서 Blazor Server 안전하게 전송되도록 합니다.

미리 렌더링된 상태 크기 및 SignalR 메시지 크기 제한

미리 렌더링된 큰 상태 크기가 '의 SignalR 회로 메시지 크기 제한을 초과Blazor할 수 있으며, 이로 인해 다음과 같은 결과가 발생합니다.

  • Circuit host not initialized. 클라이언트에서 오류가 발생하여 SignalR 회로를 초기화하지 못합니다.
  • 회로가 실패하면 클라이언트의 다시 연결 UI가 나타납니다. 복구는 불가능합니다.

문제를 해결하려면 다음 방법 중 하나를 사용합니다.

  • 미리 렌더링된 상태로 전환할 데이터의 양을 줄입니다.
  • SignalR 메시지 크기 제한을 늘입니다. 경고: 제한을 늘리면 DoS(서비스 거부) 공격의 위험이 증가할 수 있습니다.

추가 Blazor Server 리소스

미리 렌더링은 검색 엔진이 페이지 순위를 계산하는 데 사용할 수 있는 초기 HTTP 응답에 대한 콘텐츠를 렌더링하여 SEO(검색 엔진 최적화)를 향상시킬 수 있습니다.

프로젝트를 구성한 후 프로젝트 요구 사항에 따라 다음 섹션의 지침을 따릅니다.

구성

다음 지침을 사용하여 구성 요소를 기존 Razor Pages 또는 MVC 앱의 페이지 또는 뷰에 통합 Razor 합니다.

Important

페이지의 제목(PageTitle 구성 요소) 및 기타 헤드 요소(HeadContent 구성 요소)와 같은 <head> 콘텐츠를 제어하려면 HeadOutlet 구성 요소에 대해 구성 요소 태그 도우미와 함께 레이아웃 페이지(_Layout.cshtml)를 사용해야 합니다. 자세한 내용은 ASP.NET Core Blazor 앱의 헤드 콘텐츠 제어를 참조하세요.

  1. 프로젝트의 레이아웃 파일에서 다음을 수행합니다.

    • Pages/Shared/_Layout.cshtml(Razor Pages) 또는 Views/Shared/_Layout.cshtml(MVC)의 <head> 요소에 다음 <base> 태그 및 HeadOutlet 구성 요소 태그 도우미를 추가합니다.

      <base href="~/" />
      <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
      

      위의 예제에서 href 값(‘앱 기본 경로’)은 앱이 루트 URL 경로(/)에 있는 것으로 가정합니다. 앱이 하위 애플리케이션인 경우, ASP.NET Core Blazor 호스트 및 배포 문서의 앱 기본 경로 섹션에 설명된 지침을 따르세요.

      HeadOutlet 구성 요소는 Razor 구성 요소에서 설정한 페이지 제목(PageTitle 구성 요소) 및 기타 헤드 요소(HeadContent 구성 요소)에 대한 헤드(<head>) 콘텐츠를 렌더링하는 데 사용됩니다. 자세한 내용은 ASP.NET Core Blazor 앱의 헤드 콘텐츠 제어를 참조하세요.

    • 앱의 레이아웃에 있는 Scripts 렌더링 섹션(@await RenderSectionAsync(...)) 바로 앞에 blazor.server.js 스크립트의 <script> 태그를 추가합니다.

      Pages/Shared/_Layout.cshtml(Razor 페이지) 또는 Views/Shared/_Layout.cshtml(MVC):

      <script src="_framework/blazor.server.js"></script>
      

      프레임워크는 앱에 blazor.server.js 스크립트를 추가합니다. 앱에 blazor.server.js 스크립트 파일을 수동으로 추가할 필요는 없습니다.

  2. 다음 콘텐츠를 사용하여 프로젝트 루트 폴더에 가져오기 파일을 추가합니다. {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 변경합니다.

    _Imports.razor:

    @using System.Net.Http
    @using Microsoft.AspNetCore.Authorization
    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.Forms
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.AspNetCore.Components.Web
    @using Microsoft.AspNetCore.Components.Web.Virtualization
    @using Microsoft.JSInterop
    @using {APP NAMESPACE}
    
  3. 서비스가 등록된 Program.cs에 Blazor Server 서비스를 등록합니다.

    builder.Services.AddServerSideBlazor();
    
  4. Blazor 허브 엔드포인트를 경로가 매핑되는 Program.cs의 엔드포인트에 추가합니다.

    MapRazorPages(Razor Pages) 또는 MapControllerRoute(MVC)에 대한 호출 뒤에 다음 라인을 배치합니다.

    app.MapBlazorHub();
    
  5. 페이지 또는 뷰에 구성 요소를 통합합니다. 예를 들어 프로젝트의 Shared 폴더에 Counter구성 요소를 추가합니다.

    Pages/Shared/Counter.razor(Razor 페이지) 또는 Views/Shared/Counter.razor(MVC):

    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    

    Razor 페이지:

    Razor 페이지 앱의 프로젝트 Index 페이지에서 Counter 구성 요소의 네임스페이스를 추가하고 이 구성 요소를 페이지에 포함합니다. Index 페이지가 로드되면 Counter 구성 요소가 페이지에 미리 렌더링됩니다. 다음 예제에서는 {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 바꿉니다.

    Pages/Index.cshtml:

    @page
    @using {APP NAMESPACE}.Pages.Shared
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }
    
    <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    

    MVC:

    MVC 앱의 프로젝트 Index뷰에서 Counter 구성 요소 네임스페이스를 추가하고 해당 구성 요소를 뷰에 포함합니다. Index 뷰가 로드되면 Counter 구성 요소가 페이지에서 미리 렌더링됩니다. 다음 예제에서는 {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 바꿉니다.

    Views/Home/Index.cshtml:

    @using {APP NAMESPACE}.Views.Shared
    @{
        ViewData["Title"] = "Home Page";
    }
    
    <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    

자세한 내용은 페이지 또는 뷰에서 구성 요소 렌더링 섹션을 참조하세요.

Razor Pages 앱에서 라우팅 가능한 구성 요소 사용

‘이 섹션에서는 사용자 요청에서 직접 라우팅할 수 있는 구성 요소를 추가하는 방법을 설명합니다.’

Razor Pages 앱에서 라우팅 가능한 Razor 구성 요소를 지원하려면 다음을 수행합니다.

  1. 구성 섹션의 지침을 따릅니다.

  2. 다음 콘텐츠를 사용하여 프로젝트 루트에 App 구성 요소를 추가합니다.

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <p role="alert">Sorry, there's nothing at this address.</p>
        </NotFound>
    </Router>
    
  3. 다음 콘텐츠로 _Host 페이지를 프로젝트에 추가합니다.

    Pages/_Host.cshtml:

    @page "/blazor"
    @namespace {APP NAMESPACE}.Pages.Shared
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    @{
        Layout = "_Layout";
    }
    
    <component type="typeof(App)" render-mode="ServerPrerendered" />
    

    이 시나리오에서 구성 요소는 해당 레이아웃에 공유 _Layout.cshtml 파일을 사용합니다.

    Important

    페이지의 제목(PageTitle 구성 요소) 및 기타 헤드 요소(HeadContent 구성 요소)와 같은 <head> 콘텐츠를 제어하려면 HeadOutlet 구성 요소에 대해 구성 요소 태그 도우미와 함께 레이아웃 페이지(_Layout.cshtml)를 사용해야 합니다. 자세한 내용은 ASP.NET Core Blazor 앱의 헤드 콘텐츠 제어를 참조하세요.

    RenderModeApp 구성 요소에 대해 다음을 구성합니다.

    • 페이지에 미리 렌더링할지 여부
    • 페이지에 정적 HTML로 렌더링할지 여부 또는 사용자 에이전트에서 Blazor 앱을 부트스트랩하는 데 필요한 정보를 포함할지 여부

    매개 변수 전달과 RenderMode 구성을 포함하여 구성 요소 태그 도우미에 대한 자세한 내용은 ASP.NET Core의 구성 요소 태그 도우미를 참조하세요.

  4. Program.cs 엔드포인트에서 _Host 페이지의 우선 순위가 낮은 경로를 마지막 엔드포인트로 추가합니다.

    app.MapFallbackToPage("/_Host");
    
  5. 라우팅 가능한 구성 요소를 프로젝트에 추가합니다. 다음 예제는 Blazor 프로젝트 템플릿의 Counter 구성 요소를 기반으로 하는 RoutableCounter 구성 요소입니다.

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <PageTitle>Routable Counter</PageTitle>
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  6. 프로젝트를 실행하고 /routable-counter에서 라우팅할 수 있는 RoutableCounter 구성 요소로 이동합니다.

네임스페이스에 대한 자세한 내용은 구성 요소 네임스페이스 섹션을 참조하세요.

MVC 앱에서 라우팅 가능한 구성 요소 사용

‘이 섹션에서는 사용자 요청에서 직접 라우팅할 수 있는 구성 요소를 추가하는 방법을 설명합니다.’

MVC 앱에서 라우팅 가능한 Razor 구성 요소를 지원하려면 다음을 수행합니다.

  1. 구성 섹션의 지침을 따릅니다.

  2. 다음 콘텐츠를 사용하여 프로젝트 루트에 App 구성 요소를 추가합니다.

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(App).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <p role="alert">Sorry, there's nothing at this address.</p>
        </NotFound>
    </Router>
    
  3. 다음 콘텐츠를 사용하여 _Host 뷰를 프로젝트에 추가합니다.

    Views/Home/_Host.cshtml:

    @namespace {APP NAMESPACE}.Views.Shared
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    @{
        Layout = "_Layout";
    }
    
    <component type="typeof(App)" render-mode="ServerPrerendered" />
    

    구성 요소는 해당 레이아웃에 공유 _Layout.cshtml 파일을 사용합니다.

    Important

    페이지의 제목(PageTitle 구성 요소) 및 기타 헤드 요소(HeadContent 구성 요소)와 같은 <head> 콘텐츠를 제어하려면 HeadOutlet 구성 요소에 대해 구성 요소 태그 도우미와 함께 레이아웃 페이지(_Layout.cshtml)를 사용해야 합니다. 자세한 내용은 ASP.NET Core Blazor 앱의 헤드 콘텐츠 제어를 참조하세요.

    RenderModeApp 구성 요소에 대해 다음을 구성합니다.

    • 페이지에 미리 렌더링할지 여부
    • 페이지에 정적 HTML로 렌더링할지 여부 또는 사용자 에이전트에서 Blazor 앱을 부트스트랩하는 데 필요한 정보를 포함할지 여부

    매개 변수 전달과 RenderMode 구성을 포함하여 구성 요소 태그 도우미에 대한 자세한 내용은 ASP.NET Core의 구성 요소 태그 도우미를 참조하세요.

  4. Home 컨트롤러에 작업을 추가합니다.

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Program.cs 엔드포인트에 _Host 보기를 반환하는 컨트롤러 작업에 우선 순위가 낮은 경로를 추가합니다.

    app.MapFallbackToController("Blazor", "Home");
    
  6. MVC 앱에 Pages 폴더를 만들고 라우팅 가능한 구성 요소를 추가합니다. 다음 예제는 Blazor 프로젝트 템플릿의 Counter 구성 요소를 기반으로 하는 RoutableCounter 구성 요소입니다.

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <PageTitle>Routable Counter</PageTitle>
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  7. 프로젝트를 실행하고 /routable-counter에서 라우팅할 수 있는 RoutableCounter 구성 요소로 이동합니다.

네임스페이스에 대한 자세한 내용은 구성 요소 네임스페이스 섹션을 참조하세요.

페이지 또는 뷰에서 구성 요소 렌더링

‘이 섹션에서는 사용자 요청에서 직접 구성 요소를 라우팅할 수 없는 페이지 또는 뷰에 구성 요소를 추가하는 방법을 설명합니다.’

페이지 또는 뷰에서 구성 요소를 렌더링하려면 구성 요소 태그 도우미를 사용합니다.

상태 저장 대화형 구성 요소 렌더링

Razor 페이지 또는 뷰에 상태 저장 대화형 구성 요소를 추가할 수 있습니다.

페이지 또는 뷰를 렌더링하는 경우와 관련해서 다음 사항을 확인합니다.

  • 구성 요소가 페이지 또는 뷰와 함께 미리 렌더링됩니다.
  • 미리 렌더링하는 데 사용된 초기 구성 요소 상태가 손실됩니다.
  • SignalR 연결이 완료되면 새 구성 요소 상태가 생성됩니다.

다음 Razor 페이지는 Counter 구성 요소를 렌더링합니다.

<h1>Razor Page</h1>

<component type="typeof(Counter)" render-mode="ServerPrerendered" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

자세한 내용은 ASP.NET Core 구성 요소 태그 도우미를 참조하세요.

Important

페이지의 제목(PageTitle 구성 요소) 및 기타 헤드 요소(HeadContent 구성 요소)와 같은 <head> 콘텐츠를 제어하려면 HeadOutlet 구성 요소에 대해 구성 요소 태그 도우미와 함께 레이아웃 페이지(_Layout.cshtml)를 사용해야 합니다. 자세한 내용은 ASP.NET Core Blazor 앱의 헤드 콘텐츠 제어를 참조하세요.

비대화형 구성 요소 렌더링

다음 Razor 페이지에서 Counter 구성 요소는 폼을 통해 지정된 초기 값을 사용하여 정적으로 렌더링됩니다. 구성 요소가 정적으로 렌더링되므로 구성 요소는 대화형이 아닙니다.

<h1>Razor Page</h1>

<form>
    <input type="number" asp-for="InitialValue" />
    <button type="submit">Set initial value</button>
</form>

<component type="typeof(Counter)" render-mode="Static" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

자세한 내용은 ASP.NET Core 구성 요소 태그 도우미를 참조하세요.

Important

페이지의 제목(PageTitle 구성 요소) 및 기타 헤드 요소(HeadContent 구성 요소)와 같은 <head> 콘텐츠를 제어하려면 HeadOutlet 구성 요소에 대해 구성 요소 태그 도우미와 함께 레이아웃 페이지(_Layout.cshtml)를 사용해야 합니다. 자세한 내용은 ASP.NET Core Blazor 앱의 헤드 콘텐츠 제어를 참조하세요.

구성 요소 네임스페이스

사용자 지정 폴더를 사용하여 프로젝트의 Razor 구성 요소를 저장하는 경우, 폴더를 나타내는 네임스페이스를 페이지/뷰 또는 _ViewImports.cshtml 파일에 추가합니다. 다음 예제에서

  • 구성 요소는 프로젝트의 Components 폴더에 저장됩니다.
  • {APP NAMESPACE} 자리 표시자는 프로젝트의 네임스페이스입니다. Components은 폴더의 이름을 나타냅니다.
@using {APP NAMESPACE}.Components

_ViewImports.cshtml 파일은 Razor Pages 앱의 Pages 폴더 또는 MVC 앱의 Views 폴더에 있습니다.

자세한 내용은 ASP.NET Core Razor 구성 요소를 참조하세요.

미리 렌더링된 상태 유지

미리 렌더링된 상태를 유지하지 않으면 미리 렌더링하는 동안 사용된 상태를 잃게 되며 앱이 완전히 로드되면 다시 만들어야 합니다. 상태가 비동기적으로 설정된 경우 미리 렌더링된 UI가 임시 자리 표시자로 대체된 다음, 완전히 다시 렌더링되면 UI가 깜박일 수 있습니다.

이러한 문제를 해결하기 위해 Blazor는 구성 요소 상태 유지 태그 도우미를 사용하여 미리 렌더링된 페이지에서 상태 유지를 지원합니다. 닫는 </body> 태그 안에 태그 도우미 태그인 <persist-component-state />를 추가합니다.

Pages/_Layout.cshtml:

<body>
    ...

    <persist-component-state />
</body>

PersistentComponentState 서비스를 사용하여 유지할 상태를 결정합니다. PersistentComponentState.RegisterOnPersisting은 앱이 일시 중지되기 전에 구성 요소 상태를 유지하도록 콜백을 등록합니다. 애플리케이션이 다시 시작될 때 상태가 검색됩니다.

다음 예제는 프로젝트 템플릿을 기반으로 Blazor 구성 요소의 FetchData 업데이트된 버전입니다. WeatherForecastPreserveState 구성 요소는 미리 렌더링하는 동안 날씨 예측 상태를 유지한 다음, 상태를 검색하여 구성 요소를 초기화합니다. 구성 요소 상태 유지 태그 도우미는 모든 구성 요소 호출 후 구성 요소 상태를 유지합니다.

Pages/WeatherForecastPreserveState.razor:

@page "/weather-forecast-preserve-state"
@implements IDisposable
@using BlazorSample.Shared
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState

<PageTitle>Weather Forecast</PageTitle>

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        persistingSubscription = 
            ApplicationState.RegisterOnPersisting(PersistForecasts);

        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            "fetchdata", out var restored))
        {
            forecasts = 
                await WeatherForecastService.GetForecastAsync(DateTime.Now);
        }
        else
        {
            forecasts = restored!;
        }
    }

    private Task PersistForecasts()
    {
        ApplicationState.PersistAsJson("fetchdata", forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

미리 렌더링하는 동안 사용된 것과 동일한 상태로 구성 요소를 초기화하면 비용이 많이 드는 초기화 단계가 한 번만 실행됩니다. 렌더링된 UI도 미리 렌더링된 UI와 일치하므로 브라우저에서 깜박임이 발생하지 않습니다.

지속형 미리 렌더링된 상태는 구성 요소 상태를 복원하는 데 사용되는 클라이언트로 전송됩니다. ASP.NET Core Data Protection 은 데이터가 앱에서 Blazor Server 안전하게 전송되도록 합니다.

미리 렌더링된 상태 크기 및 SignalR 메시지 크기 제한

미리 렌더링된 큰 상태 크기가 '의 SignalR 회로 메시지 크기 제한을 초과Blazor할 수 있으며, 이로 인해 다음과 같은 결과가 발생합니다.

  • Circuit host not initialized. 클라이언트에서 오류가 발생하여 SignalR 회로를 초기화하지 못합니다.
  • 회로가 실패하면 클라이언트의 다시 연결 UI가 나타납니다. 복구는 불가능합니다.

문제를 해결하려면 다음 방법 중 하나를 사용합니다.

  • 미리 렌더링된 상태로 전환할 데이터의 양을 줄입니다.
  • SignalR 메시지 크기 제한을 늘입니다. 경고: 제한을 늘리면 DoS(서비스 거부) 공격의 위험이 증가할 수 있습니다.

추가 Blazor Server 리소스

미리 렌더링은 검색 엔진이 페이지 순위를 계산하는 데 사용할 수 있는 초기 HTTP 응답에 대한 콘텐츠를 렌더링하여 SEO(검색 엔진 최적화)를 향상시킬 수 있습니다.

프로젝트를 구성한 후 프로젝트 요구 사항에 따라 다음 섹션의 지침을 따릅니다.

구성

기존 Razor Pages 또는 MVC 앱은 구성 요소를 페이지 또는 보기에 통합 Razor 할 수 있습니다.

  1. 프로젝트의 레이아웃 파일에서 다음을 수행합니다.

    • Pages/Shared/_Layout.cshtml(Razor 페이지) 또는 Views/Shared/_Layout.cshtml(MVC)의 <head>요소에 다음 <base>태그를 추가합니다.

      <base href="~/" />
      

      위의 예제에서 href 값(‘앱 기본 경로’)은 앱이 루트 URL 경로(/)에 있는 것으로 가정합니다. 앱이 하위 애플리케이션인 경우, ASP.NET Core Blazor 호스트 및 배포 문서의 앱 기본 경로 섹션에 설명된 지침을 따르세요.

    • Scripts 렌더링 섹션 바로 앞에 blazor.server.js 스크립트의 <script> 태그를 추가합니다.

      Pages/Shared/_Layout.cshtml(Razor 페이지) 또는 Views/Shared/_Layout.cshtml(MVC):

          ...
          <script src="_framework/blazor.server.js"></script>
      
          @await RenderSectionAsync("Scripts", required: false)
      </body>
      

      프레임워크는 앱에 blazor.server.js 스크립트를 추가합니다. 앱에 blazor.server.js 스크립트 파일을 수동으로 추가할 필요는 없습니다.

  2. 다음 콘텐츠를 사용하여 프로젝트 루트 폴더에 가져오기 파일을 추가합니다. {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 변경합니다.

    _Imports.razor:

    @using System.Net.Http
    @using Microsoft.AspNetCore.Authorization
    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.Forms
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.AspNetCore.Components.Web
    @using Microsoft.JSInterop
    @using {APP NAMESPACE}
    
  3. Startup.ConfigureServices에 Blazor Server 서비스를 등록합니다.

    Startup.cs의 경우

    services.AddServerSideBlazor();
    
  4. Startup.Configure의 엔드포인트(app.UseEndpoints)에 Blazor 허브 엔드포인트를 추가합니다.

    Startup.cs:

    endpoints.MapBlazorHub();
    
  5. 페이지 또는 뷰에 구성 요소를 통합합니다. 예를 들어 프로젝트의 Shared 폴더에 Counter구성 요소를 추가합니다.

    Pages/Shared/Counter.razor(Razor 페이지) 또는 Views/Shared/Counter.razor(MVC):

    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    

    Razor 페이지:

    Razor 페이지 앱의 프로젝트 Index 페이지에서 Counter 구성 요소의 네임스페이스를 추가하고 이 구성 요소를 페이지에 포함합니다. Index 페이지가 로드되면 Counter 구성 요소가 페이지에 미리 렌더링됩니다. 다음 예제에서는 {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 바꿉니다.

    Pages/Index.cshtml:

    @page
    @using {APP NAMESPACE}.Pages.Shared
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }
    
    <div>
        <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    </div>
    

    앞의 예제에서 {APP NAMESPACE} 자리 표시자를 앱의 네임스페이스로 바꿉니다.

    MVC:

    MVC 앱의 프로젝트 Index뷰에서 Counter 구성 요소 네임스페이스를 추가하고 해당 구성 요소를 뷰에 포함합니다. Index 뷰가 로드되면 Counter 구성 요소가 페이지에서 미리 렌더링됩니다. 다음 예제에서는 {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 바꿉니다.

    Views/Home/Index.cshtml:

    @using {APP NAMESPACE}.Views.Shared
    @{
        ViewData["Title"] = "Home Page";
    }
    
    <div>
        <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    </div>
    

자세한 내용은 페이지 또는 뷰에서 구성 요소 렌더링 섹션을 참조하세요.

Razor Pages 앱에서 라우팅 가능한 구성 요소 사용

‘이 섹션에서는 사용자 요청에서 직접 라우팅할 수 있는 구성 요소를 추가하는 방법을 설명합니다.’

Razor Pages 앱에서 라우팅 가능한 Razor 구성 요소를 지원하려면 다음을 수행합니다.

  1. 구성 섹션의 지침을 따릅니다.

  2. 다음 콘텐츠를 사용하여 프로젝트 루트에 App 구성 요소를 추가합니다.

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(Program).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <h1>Page not found</h1>
            <p>Sorry, but there's nothing here!</p>
        </NotFound>
    </Router>
    

    참고 항목

    ASP.NET Core 5.0.1 릴리스 및 추가 5.x 릴리스부터 Router 구성 요소에는 @true로 설정된 PreferExactMatches 매개 변수가 포함됩니다. 자세한 내용은 ASP.NET Core 3.1에서 5.0으로 마이그레이션을 참조하세요.

  3. 다음 콘텐츠로 _Host 페이지를 프로젝트에 추가합니다.

    Pages/_Host.cshtml:

    @page "/blazor"
    @{
        Layout = "_Layout";
    }
    
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    

    구성 요소는 해당 레이아웃에 공유 _Layout.cshtml 파일을 사용합니다.

    RenderModeApp 구성 요소에 대해 다음을 구성합니다.

    • 페이지에 미리 렌더링할지 여부
    • 페이지에 정적 HTML로 렌더링할지 여부 또는 사용자 에이전트에서 Blazor 앱을 부트스트랩하는 데 필요한 정보를 포함할지 여부

    매개 변수 전달과 RenderMode 구성을 포함하여 구성 요소 태그 도우미에 대한 자세한 내용은 ASP.NET Core의 구성 요소 태그 도우미를 참조하세요.

  4. Startup.csStartup.Configure 엔드포인트에서 _Host 페이지의 우선 순위가 낮은 경로를 마지막 엔드포인트로 추가합니다.

    endpoints.MapFallbackToPage("/_Host");
    

    다음 예제에서는 일반적인 앱의 엔드포인트 구성에 추가된 줄을 보여줍니다.

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
    });
    
  5. 라우팅 가능한 구성 요소를 프로젝트에 추가합니다.

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  6. 프로젝트를 실행하고 /routable-counter에서 라우팅할 수 있는 RoutableCounter 구성 요소로 이동합니다.

네임스페이스에 대한 자세한 내용은 구성 요소 네임스페이스 섹션을 참조하세요.

MVC 앱에서 라우팅 가능한 구성 요소 사용

‘이 섹션에서는 사용자 요청에서 직접 라우팅할 수 있는 구성 요소를 추가하는 방법을 설명합니다.’

MVC 앱에서 라우팅 가능한 Razor 구성 요소를 지원하려면 다음을 수행합니다.

  1. 구성 섹션의 지침을 따릅니다.

  2. 다음 콘텐츠를 사용하여 프로젝트 루트에 App 구성 요소를 추가합니다.

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(Program).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <h1>Page not found</h1>
            <p>Sorry, but there's nothing here!</p>
        </NotFound>
    </Router>
    

    참고 항목

    ASP.NET Core 5.0.1 릴리스 및 추가 5.x 릴리스부터 Router 구성 요소에는 @true로 설정된 PreferExactMatches 매개 변수가 포함됩니다. 자세한 내용은 ASP.NET Core 3.1에서 5.0으로 마이그레이션을 참조하세요.

  3. 다음 콘텐츠를 사용하여 _Host 뷰를 프로젝트에 추가합니다.

    Views/Home/_Host.cshtml:

    @{
        Layout = "_Layout";
    }
    
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    

    구성 요소는 해당 레이아웃에 공유 _Layout.cshtml 파일을 사용합니다.

    RenderModeApp 구성 요소에 대해 다음을 구성합니다.

    • 페이지에 미리 렌더링할지 여부
    • 페이지에 정적 HTML로 렌더링할지 여부 또는 사용자 에이전트에서 Blazor 앱을 부트스트랩하는 데 필요한 정보를 포함할지 여부

    매개 변수 전달과 RenderMode 구성을 포함하여 구성 요소 태그 도우미에 대한 자세한 내용은 ASP.NET Core의 구성 요소 태그 도우미를 참조하세요.

  4. Home 컨트롤러에 작업을 추가합니다.

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Startup.csStartup.Configure 엔드포인트 구성에 _Host 뷰를 반환하는 컨트롤러 작업의 우선순위가 낮은 경로를 추가합니다.

    endpoints.MapFallbackToController("Blazor", "Home");
    

    다음 예제에서는 일반적인 앱의 엔드포인트 구성에 추가된 줄을 보여줍니다.

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToController("Blazor", "Home");
    });
    
  6. 라우팅 가능한 구성 요소를 프로젝트에 추가합니다.

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  7. 프로젝트를 실행하고 /routable-counter에서 라우팅할 수 있는 RoutableCounter 구성 요소로 이동합니다.

네임스페이스에 대한 자세한 내용은 구성 요소 네임스페이스 섹션을 참조하세요.

페이지 또는 뷰에서 구성 요소 렌더링

‘이 섹션에서는 사용자 요청에서 직접 구성 요소를 라우팅할 수 없는 페이지 또는 뷰에 구성 요소를 추가하는 방법을 설명합니다.’

페이지 또는 뷰에서 구성 요소를 렌더링하려면 구성 요소 태그 도우미를 사용합니다.

상태 저장 대화형 구성 요소 렌더링

Razor 페이지 또는 뷰에 상태 저장 대화형 구성 요소를 추가할 수 있습니다.

페이지 또는 뷰를 렌더링하는 경우와 관련해서 다음 사항을 확인합니다.

  • 구성 요소가 페이지 또는 뷰와 함께 미리 렌더링됩니다.
  • 미리 렌더링하는 데 사용된 초기 구성 요소 상태가 손실됩니다.
  • SignalR 연결이 완료되면 새 구성 요소 상태가 생성됩니다.

다음 Razor 페이지는 Counter 구성 요소를 렌더링합니다.

<h1>My Razor Page</h1>

<component type="typeof(Counter)" render-mode="ServerPrerendered" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

자세한 내용은 ASP.NET Core 구성 요소 태그 도우미를 참조하세요.

비대화형 구성 요소 렌더링

다음 Razor 페이지에서 Counter 구성 요소는 폼을 통해 지정된 초기 값을 사용하여 정적으로 렌더링됩니다. 구성 요소가 정적으로 렌더링되므로 구성 요소는 대화형이 아닙니다.

<h1>My Razor Page</h1>

<form>
    <input type="number" asp-for="InitialValue" />
    <button type="submit">Set initial value</button>
</form>

<component type="typeof(Counter)" render-mode="Static" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

자세한 내용은 ASP.NET Core 구성 요소 태그 도우미를 참조하세요.

구성 요소 네임스페이스

사용자 지정 폴더를 사용하여 프로젝트의 Razor 구성 요소를 저장하는 경우, 폴더를 나타내는 네임스페이스를 페이지/뷰 또는 _ViewImports.cshtml 파일에 추가합니다. 다음 예제에서

  • 구성 요소는 프로젝트의 Components 폴더에 저장됩니다.
  • {APP NAMESPACE} 자리 표시자는 프로젝트의 네임스페이스입니다. Components은 폴더의 이름을 나타냅니다.
@using {APP NAMESPACE}.Components

_ViewImports.cshtml 파일은 Razor Pages 앱의 Pages 폴더 또는 MVC 앱의 Views 폴더에 있습니다.

자세한 내용은 ASP.NET Core Razor 구성 요소를 참조하세요.

미리 렌더링된 상태 크기 및 SignalR 메시지 크기 제한

미리 렌더링된 큰 상태 크기가 '의 SignalR 회로 메시지 크기 제한을 초과Blazor할 수 있으며, 이로 인해 다음과 같은 결과가 발생합니다.

  • Circuit host not initialized. 클라이언트에서 오류가 발생하여 SignalR 회로를 초기화하지 못합니다.
  • 회로가 실패하면 클라이언트의 다시 연결 UI가 나타납니다. 복구는 불가능합니다.

문제를 해결하려면 다음 방법 중 하나를 사용합니다.

  • 미리 렌더링된 상태로 전환할 데이터의 양을 줄입니다.
  • SignalR 메시지 크기 제한을 늘입니다. 경고: 제한을 늘리면 DoS(서비스 거부) 공격의 위험이 증가할 수 있습니다.

추가 Blazor Server 리소스

Razor 구성 요소를 Pages 또는 MVC 앱에 Razor 통합할 수 있습니다. 페이지나 뷰를 렌더링할 때 구성 요소를 동시에 미리 렌더링할 수 있습니다.

미리 렌더링은 검색 엔진이 페이지 순위를 계산하는 데 사용할 수 있는 초기 HTTP 응답에 대한 콘텐츠를 렌더링하여 SEO(검색 엔진 최적화)를 향상시킬 수 있습니다.

프로젝트를 구성한 후 프로젝트 요구 사항에 따라 다음 섹션의 지침을 따릅니다.

구성

기존 Razor Pages 또는 MVC 앱은 구성 요소를 페이지 또는 보기에 통합 Razor 할 수 있습니다.

  1. 프로젝트의 레이아웃 파일에서 다음을 수행합니다.

    • Pages/Shared/_Layout.cshtml(Razor 페이지) 또는 Views/Shared/_Layout.cshtml(MVC)의 <head>요소에 다음 <base>태그를 추가합니다.

      + <base href="~/" />
      

      위의 예제에서 href 값(‘앱 기본 경로’)은 앱이 루트 URL 경로(/)에 있는 것으로 가정합니다. 앱이 하위 애플리케이션인 경우, ASP.NET Core Blazor 호스트 및 배포 문서의 앱 기본 경로 섹션에 설명된 지침을 따르세요.

    • Scripts 렌더링 섹션 바로 앞에 blazor.server.js 스크립트의 <script> 태그를 추가합니다.

      Pages/Shared/_Layout.cshtml(Razor 페이지) 또는 Views/Shared/_Layout.cshtml(MVC):

          ...
          <script src="_framework/blazor.server.js"></script>
      
          @await RenderSectionAsync("Scripts", required: false)
      </body>
      

      프레임워크는 앱에 blazor.server.js 스크립트를 추가합니다. 앱에 blazor.server.js 스크립트 파일을 수동으로 추가할 필요는 없습니다.

  2. 다음 콘텐츠를 사용하여 프로젝트 루트 폴더에 가져오기 파일을 추가합니다. {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 변경합니다.

    _Imports.razor:

    @using System.Net.Http
    @using Microsoft.AspNetCore.Authorization
    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.Forms
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.AspNetCore.Components.Web
    @using Microsoft.JSInterop
    @using {APP NAMESPACE}
    
  3. Startup.ConfigureServices에 Blazor Server 서비스를 등록합니다.

    Startup.cs:

    services.AddServerSideBlazor();
    
  4. Startup.Configure의 엔드포인트(app.UseEndpoints)에 Blazor 허브 엔드포인트를 추가합니다.

    Startup.cs:

    endpoints.MapBlazorHub();
    
  5. 페이지 또는 뷰에 구성 요소를 통합합니다. 예를 들어 프로젝트의 Shared 폴더에 Counter구성 요소를 추가합니다.

    Pages/Shared/Counter.razor(Razor 페이지) 또는 Views/Shared/Counter.razor(MVC):

    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    

    Razor 페이지:

    Razor 페이지 앱의 프로젝트 Index 페이지에서 Counter 구성 요소의 네임스페이스를 추가하고 이 구성 요소를 페이지에 포함합니다. Index 페이지가 로드되면 Counter 구성 요소가 페이지에 미리 렌더링됩니다. 다음 예제에서는 {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 바꿉니다.

    Pages/Index.cshtml:

    @page
    @using {APP NAMESPACE}.Pages.Shared
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }
    
    <div>
        <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    </div>
    

    앞의 예제에서 {APP NAMESPACE} 자리 표시자를 앱의 네임스페이스로 바꿉니다.

    MVC:

    MVC 앱의 프로젝트 Index뷰에서 Counter 구성 요소 네임스페이스를 추가하고 해당 구성 요소를 뷰에 포함합니다. Index 뷰가 로드되면 Counter 구성 요소가 페이지에서 미리 렌더링됩니다. 다음 예제에서는 {APP NAMESPACE} 자리 표시자를 프로젝트의 네임스페이스로 바꿉니다.

    Views/Home/Index.cshtml:

    @using {APP NAMESPACE}.Views.Shared
    @{
        ViewData["Title"] = "Home Page";
    }
    
    <div>
        <component type="typeof(Counter)" render-mode="ServerPrerendered" />
    </div>
    

자세한 내용은 페이지 또는 뷰에서 구성 요소 렌더링 섹션을 참조하세요.

Razor Pages 앱에서 라우팅 가능한 구성 요소 사용

‘이 섹션에서는 사용자 요청에서 직접 라우팅할 수 있는 구성 요소를 추가하는 방법을 설명합니다.’

Razor Pages 앱에서 라우팅 가능한 Razor 구성 요소를 지원하려면 다음을 수행합니다.

  1. 구성 섹션의 지침을 따릅니다.

  2. 다음 콘텐츠를 사용하여 프로젝트 루트에 App 구성 요소를 추가합니다.

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(Program).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <h1>Page not found</h1>
            <p>Sorry, but there's nothing here!</p>
        </NotFound>
    </Router>
    
  3. 다음 콘텐츠로 _Host 페이지를 프로젝트에 추가합니다.

    Pages/_Host.cshtml:

    @page "/blazor"
    @{
        Layout = "_Layout";
    }
    
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    

    구성 요소는 해당 레이아웃에 공유 _Layout.cshtml 파일을 사용합니다.

    RenderModeApp 구성 요소에 대해 다음을 구성합니다.

    • 페이지에 미리 렌더링할지 여부
    • 페이지에 정적 HTML로 렌더링할지 여부 또는 사용자 에이전트에서 Blazor 앱을 부트스트랩하는 데 필요한 정보를 포함할지 여부

    매개 변수 전달과 RenderMode 구성을 포함하여 구성 요소 태그 도우미에 대한 자세한 내용은 ASP.NET Core의 구성 요소 태그 도우미를 참조하세요.

  4. Startup.csStartup.Configure 엔드포인트에서 _Host 페이지의 우선 순위가 낮은 경로를 마지막 엔드포인트로 추가합니다.

    endpoints.MapFallbackToPage("/_Host");
    

    다음 예제에서는 일반적인 앱의 엔드포인트 구성에 추가된 줄을 보여줍니다.

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
    });
    
  5. 라우팅 가능한 구성 요소를 프로젝트에 추가합니다.

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  6. 프로젝트를 실행하고 /routable-counter에서 라우팅할 수 있는 RoutableCounter 구성 요소로 이동합니다.

네임스페이스에 대한 자세한 내용은 구성 요소 네임스페이스 섹션을 참조하세요.

MVC 앱에서 라우팅 가능한 구성 요소 사용

‘이 섹션에서는 사용자 요청에서 직접 라우팅할 수 있는 구성 요소를 추가하는 방법을 설명합니다.’

MVC 앱에서 라우팅 가능한 Razor 구성 요소를 지원하려면 다음을 수행합니다.

  1. 구성 섹션의 지침을 따릅니다.

  2. 다음 콘텐츠를 사용하여 프로젝트 루트에 App 구성 요소를 추가합니다.

    App.razor:

    @using Microsoft.AspNetCore.Components.Routing
    
    <Router AppAssembly="typeof(Program).Assembly">
        <Found Context="routeData">
            <RouteView RouteData="routeData" />
        </Found>
        <NotFound>
            <h1>Page not found</h1>
            <p>Sorry, but there's nothing here!</p>
        </NotFound>
    </Router>
    
  3. 다음 콘텐츠를 사용하여 _Host 뷰를 프로젝트에 추가합니다.

    Views/Home/_Host.cshtml:

    @{
        Layout = "_Layout";
    }
    
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    

    구성 요소는 해당 레이아웃에 공유 _Layout.cshtml 파일을 사용합니다.

    RenderModeApp 구성 요소에 대해 다음을 구성합니다.

    • 페이지에 미리 렌더링할지 여부
    • 페이지에 정적 HTML로 렌더링할지 여부 또는 사용자 에이전트에서 Blazor 앱을 부트스트랩하는 데 필요한 정보를 포함할지 여부

    매개 변수 전달과 RenderMode 구성을 포함하여 구성 요소 태그 도우미에 대한 자세한 내용은 ASP.NET Core의 구성 요소 태그 도우미를 참조하세요.

  4. Home 컨트롤러에 작업을 추가합니다.

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Startup.csStartup.Configure 엔드포인트 구성에 _Host 뷰를 반환하는 컨트롤러 작업의 우선순위가 낮은 경로를 추가합니다.

    endpoints.MapFallbackToController("Blazor", "Home");
    

    다음 예제에서는 일반적인 앱의 엔드포인트 구성에 추가된 줄을 보여줍니다.

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToController("Blazor", "Home");
    });
    
  6. 라우팅 가능한 구성 요소를 프로젝트에 추가합니다.

    Pages/RoutableCounter.razor:

    @page "/routable-counter"
    
    <h1>Routable Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    
  7. 프로젝트를 실행하고 /routable-counter에서 라우팅할 수 있는 RoutableCounter 구성 요소로 이동합니다.

네임스페이스에 대한 자세한 내용은 구성 요소 네임스페이스 섹션을 참조하세요.

페이지 또는 뷰에서 구성 요소 렌더링

‘이 섹션에서는 사용자 요청에서 직접 구성 요소를 라우팅할 수 없는 페이지 또는 뷰에 구성 요소를 추가하는 방법을 설명합니다.’

페이지 또는 뷰에서 구성 요소를 렌더링하려면 구성 요소 태그 도우미를 사용합니다.

상태 저장 대화형 구성 요소 렌더링

Razor 페이지 또는 뷰에 상태 저장 대화형 구성 요소를 추가할 수 있습니다.

페이지 또는 뷰를 렌더링하는 경우와 관련해서 다음 사항을 확인합니다.

  • 구성 요소가 페이지 또는 뷰와 함께 미리 렌더링됩니다.
  • 미리 렌더링하는 데 사용된 초기 구성 요소 상태가 손실됩니다.
  • SignalR 연결이 완료되면 새 구성 요소 상태가 생성됩니다.

다음 Razor 페이지는 Counter 구성 요소를 렌더링합니다.

<h1>My Razor Page</h1>

<component type="typeof(Counter)" render-mode="ServerPrerendered" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

자세한 내용은 ASP.NET Core 구성 요소 태그 도우미를 참조하세요.

비대화형 구성 요소 렌더링

다음 Razor 페이지에서 Counter 구성 요소는 폼을 통해 지정된 초기 값을 사용하여 정적으로 렌더링됩니다. 구성 요소가 정적으로 렌더링되므로 구성 요소는 대화형이 아닙니다.

<h1>My Razor Page</h1>

<form>
    <input type="number" asp-for="InitialValue" />
    <button type="submit">Set initial value</button>
</form>

<component type="typeof(Counter)" render-mode="Static" 
    param-InitialValue="InitialValue" />

@functions {
    [BindProperty(SupportsGet=true)]
    public int InitialValue { get; set; }
}

자세한 내용은 ASP.NET Core 구성 요소 태그 도우미를 참조하세요.

구성 요소 네임스페이스

사용자 지정 폴더를 사용하여 프로젝트의 Razor 구성 요소를 저장하는 경우, 폴더를 나타내는 네임스페이스를 페이지/뷰 또는 _ViewImports.cshtml 파일에 추가합니다. 다음 예제에서

  • 구성 요소는 프로젝트의 Components 폴더에 저장됩니다.
  • {APP NAMESPACE} 자리 표시자는 프로젝트의 네임스페이스입니다. Components은 폴더의 이름을 나타냅니다.
@using {APP NAMESPACE}.Components

_ViewImports.cshtml 파일은 Razor Pages 앱의 Pages 폴더 또는 MVC 앱의 Views 폴더에 있습니다.

자세한 내용은 ASP.NET Core Razor 구성 요소를 참조하세요.

미리 렌더링된 상태 크기 및 SignalR 메시지 크기 제한

미리 렌더링된 큰 상태 크기가 '의 SignalR 회로 메시지 크기 제한을 초과Blazor할 수 있으며, 이로 인해 다음과 같은 결과가 발생합니다.

  • Circuit host not initialized. 클라이언트에서 오류가 발생하여 SignalR 회로를 초기화하지 못합니다.
  • 회로가 실패하면 클라이언트의 다시 연결 UI가 나타납니다. 복구는 불가능합니다.

문제를 해결하려면 다음 방법 중 하나를 사용합니다.

  • 미리 렌더링된 상태로 전환할 데이터의 양을 줄입니다.
  • SignalR 메시지 크기 제한을 늘입니다. 경고: 제한을 늘리면 DoS(서비스 거부) 공격의 위험이 증가할 수 있습니다.

추가 Blazor Server 리소스