다음을 통해 공유


페이지, 라우팅, 레이아웃

이 콘텐츠는 .NET Docs 또는 오프라인으로 읽을 수 있는 다운로드 가능한 무료 PDF로 제공되는 Blazor for ASP NET Web Forms Developers for Azure eBook에서 발췌한 것입니다.

Blazor-for-ASP-NET-Web-Forms-Developers eBook cover thumbnail.

ASP.NET Web Forms 앱은 .aspx 파일에 정의된 페이지로 구성됩니다. 각 페이지의 주소는 프로젝트의 실제 파일 경로를 기반으로 합니다. 브라우저에서 페이지에 대한 요청을 수행하면 페이지의 콘텐츠가 서버에서 동적으로 렌더링됩니다. 렌더링에서는 페이지의 HTML 태그와 해당 서버 컨트롤을 둘 다 고려합니다.

Blazor에서 앱의 각 페이지는 일반적으로 하나 이상의 지정된 경로를 사용하여 .razor 파일에 정의된 구성 요소입니다. 라우팅은 주로 특정 서버 요청을 포함하지 않고 클라이언트 쪽에서 발생합니다. 브라우저는 먼저 앱의 루트 주소에 대한 요청을 수행합니다. 그러면 Blazor 앱의 루트 Router 구성 요소가 탐색 요청 가로채기를 처리하고 해당 요청을 올바른 구성 요소에 전달합니다.

Blazor는 딥 링크 설정도 지원합니다. 브라우저에서 앱의 루트가 아닌 특정 경로에 대한 요청을 수행하면 딥 링크 설정이 발생합니다. 서버로 전송되는 딥 링크에 대한 요청은 Blazor 앱으로 라우팅되며 이후 해당 앱은 클라이언트 쪽 요청을 올바른 구성 요소로 라우팅합니다.

ASP.NET Web Forms의 간단한 페이지에는 다음 태그가 포함될 수 있습니다.

Name.aspx

<%@ Page Title="Name" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Name.aspx.cs" Inherits="WebApplication1.Name" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
    <div>
        What is your name?<br />
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" Text="Submit" OnClick="Button1_Click" />
    </div>
    <div>
        <asp:Literal ID="Literal1" runat="server" />
    </div>
</asp:Content>

Name.aspx.cs

public partial class Name : System.Web.UI.Page
{
    protected void Button1_Click1(object sender, EventArgs e)
    {
        Literal1.Text = "Hello " + TextBox1.Text;
    }
}

Blazor 앱의 동일한 페이지는 다음과 같습니다.

Name.razor

@page "/Name"
@layout MainLayout

<div>
    What is your name?<br />
    <input @bind="text" />
    <button @onclick="OnClick">Submit</button>
</div>
<div>
    @if (name != null)
    {
        @:Hello @name
    }
</div>

@code {
    string text;
    string name;

    void OnClick() {
        name = text;
    }
}

페이지 만들기

Blazor에서 페이지를 만들려면 구성 요소를 만들고 @page Razor 지시문을 추가하여 구성 요소의 경로를 지정합니다. @page 지시문은 해당 구성 요소에 추가할 경로 템플릿인 단일 매개 변수를 사용합니다.

@page "/counter"

경로 템플릿 매개 변수는 필수입니다. ASP.NET Web Forms와 달리 Blazor 구성 요소의 경로는 파일 위치에서 유추되지 ‘않습니다’(나중에 추가되는 기능일 수도 있음).

경로 템플릿 구문은 ASP.NET Web Forms의 라우팅에 사용되는 것과 동일한 기본 구문입니다. 경로 매개 변수는 중괄호를 사용하여 템플릿에 지정됩니다. Blazor는 경로 값을 같은 이름의 구성 요소 매개 변수에 바인딩합니다(대/소문자 구분 안 함).

@page "/product/{id}"

<h1>Product @Id</h1>

@code {
    [Parameter]
    public string Id { get; set; }
}

경로 매개 변수 값의 제약 조건을 지정할 수도 있습니다. 예를 들어 제품 ID를 int로 제한합니다.

@page "/product/{id:int}"

<h1>Product @Id</h1>

@code {
    [Parameter]
    public int Id { get; set; }
}

Blazor에서 지원하는 경로 제약 조건의 전체 목록은 경로 제약 조건을 참조하세요.

라우터 구성 요소

Blazor의 라우팅은 Router 구성 요소에 의해 처리됩니다. Router 구성 요소는 일반적으로 앱의 루트 구성 요소(App.razor)에서 사용됩니다.

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="@typeof(MainLayout)">
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

Router 구성 요소는 지정된 AppAssembly 및 선택적으로 지정된 AdditionalAssemblies에서 라우팅 가능한 구성 요소를 검색합니다. 브라우저가 탐색할 때 Router는 탐색을 가로채고 경로가 주소와 일치하는 경우 RouteData를 사용하여 Found 매개 변수의 콘텐츠를 렌더링합니다. 일치하지 않는 경우 Router는 해당 NotFound 매개 변수를 렌더링합니다.

RouteView 구성 요소는 레이아웃이 있는 경우 해당 레이아웃을 사용하여 RouteData에 지정된 일치하는 구성 요소 렌더링을 처리합니다. 일치하는 구성 요소에 레이아웃이 없으면 선택적으로 지정된 DefaultLayout이 사용됩니다.

LayoutView 구성 요소는 지정된 레이아웃 내에서 자식 콘텐츠를 렌더링합니다. 이 장의 뒷부분에서 레이아웃에 관해 자세히 살펴보겠습니다.

ASP.NET Web Forms에서는 브라우저에 리디렉션 응답을 반환하여 다른 페이지로 이동을 트리거합니다. 예시:

protected void NavigateButton_Click(object sender, EventArgs e)
{
    Response.Redirect("Counter");
}

Blazor에서는 일반적으로 리디렉션 응답을 반환할 수 없습니다. Blazor는 요청-회신 모델을 사용하지 않습니다. 그러나 JavaScript를 사용하는 경우처럼 브라우저 탐색을 직접 트리거할 수 있습니다.

Blazor는 다음 작업에 사용할 수 있는 NavigationManager 서비스를 제공합니다.

  • 현재 브라우저 주소 가져오기
  • 기준 주소 가져오기
  • 탐색 트리거
  • 주소가 변경될 때 알림 받기

다른 주소로 이동하려면 NavigateTo 메서드를 사용합니다.

@page "/"
@inject NavigationManager NavigationManager

<button @onclick="Navigate">Navigate</button>

@code {
    void Navigate() {
        NavigationManager.NavigateTo("counter");
    }
}

모든 NavigationManager 멤버에 관한 설명은 URI 및 탐색 상태 도우미를 참조하세요.

기준 URL

Blazor 앱이 기본 경로 아래에 배포되는 경우 라우팅이 제대로 작동하려면 <base> 태그를 사용하여 페이지 메타데이터에서 기준 URL을 지정해야 합니다. 앱의 호스트 페이지가 Razor를 사용하여 서버에서 렌더링되는 경우 ~/ 구문을 사용하여 앱의 기준 주소를 지정할 수 있습니다. 호스트 페이지가 정적 HTML인 경우에는 기준 URL을 명시적으로 지정해야 합니다.

<base href="~/" />

페이지 레이아웃

ASP.NET Web Forms의 페이지 레이아웃은 마스터 페이지에서 처리됩니다. 마스터 페이지는 개별 페이지에서 제공될 수 있는 하나 이상의 콘텐츠 자리 표시자를 사용하여 템플릿을 정의합니다. 마스터 페이지는 .master 파일에 정의되고 <%@ Master %> 지시문으로 시작합니다. .master 파일의 콘텐츠는 .aspx 페이지를 코딩하는 것처럼 코딩되지만 페이지가 콘텐츠를 제공할 수 있는 위치를 표시하는 <asp:ContentPlaceHolder> 컨트롤을 추가합니다.

Site.master

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="WebApplication1.SiteMaster" %>

<!DOCTYPE html>
<html lang="en">
<head runat="server">
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><%: Page.Title %> - My ASP.NET Application</title>
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
</head>
<body>
    <form runat="server">
        <div class="container body-content">
            <asp:ContentPlaceHolder ID="MainContent" runat="server">
            </asp:ContentPlaceHolder>
            <hr />
            <footer>
                <p>&copy; <%: DateTime.Now.Year %> - My ASP.NET Application</p>
            </footer>
        </div>
    </form>
</body>
</html>

Blazor에서는 레이아웃 구성 요소를 사용하여 페이지 레이아웃을 처리합니다. 레이아웃 구성 요소는 RenderFragment 형식의 단일 Body 속성을 정의하는 LayoutComponentBase에서 상속됩니다. 해당 속성은 페이지의 콘텐츠를 렌더링하는 데 사용할 수 있습니다.

MainLayout.razor

@inherits LayoutComponentBase
<h1>Main layout</h1>
<div>
    @Body
</div>

레이아웃이 있는 페이지가 렌더링될 때 페이지는 레이아웃이 해당 Body 속성을 렌더링하는 위치에 지정된 레이아웃의 콘텐츠 내에서 렌더링됩니다.

페이지에 레이아웃을 적용하려면 @layout 지시문을 사용합니다.

@layout MainLayout

_Imports razor 파일을 사용하여 폴더 및 하위 폴더에 있는 모든 구성 요소의 레이아웃을 지정할 수 있습니다. 또한 라우터 구성 요소를 사용하여 모든 페이지의 기본 레이아웃을 지정할 수 있습니다.

마스터 페이지는 여러 콘텐츠 자리 표시자를 정의할 수 있지만 Blazor의 레이아웃에는 단일 Body 속성만 있습니다. Blazor 레이아웃 구성 요소의 해당 제한 사항은 향후 릴리스에서 해결될 것입니다.

ASP.NET Web Forms의 마스터 페이지는 중첩할 수 있습니다. 즉, 마스터 페이지에서 마스터 페이지를 사용할 수도 있습니다. Blazor의 레이아웃 구성 요소도 중첩할 수 있습니다. 레이아웃 구성 요소에 레이아웃 구성 요소를 적용할 수 있습니다. 내부 레이아웃의 콘텐츠는 외부 레이아웃 내에서 렌더링됩니다.

ChildLayout.razor

@layout MainLayout
<h2>Child layout</h2>
<div>
    @Body
</div>

Index.razor

@page "/"
@layout ChildLayout
<p>I'm in a nested layout!</p>

페이지의 렌더링된 출력은 다음과 같습니다.

<h1>Main layout</h1>
<div>
    <h2>Child layout</h2>
    <div>
        <p>I'm in a nested layout!</p>
    </div>
</div>

Blazor의 레이아웃은 일반적으로 페이지의 루트 HTML 요소(<html>, <body>, <head> 등)를 정의하지 않습니다. 대신, 루트 HTML 요소는 앱의 초기 HTML 콘텐츠를 렌더링하는 데 사용되는 Blazor 앱의 호스트 페이지에 정의됩니다(부트스트랩Blazor 참조). 호스트 페이지는 둘러싸는 태그를 사용하여 앱의 여러 루트 구성 요소를 렌더링할 수 있습니다.

페이지를 포함한 Blazor의 구성 요소는 <script> 태그를 렌더링할 수 없습니다. <script> 태그는 한 번 로드된 후에는 변경될 수 없기 때문에 해당 렌더링 제한 사항이 존재합니다. Razor 구문을 사용하여 동적으로 태그를 렌더링하려고 하면 예기치 않은 동작이 발생할 수 있습니다. 대신, 모든 <script> 태그를 앱의 호스트 페이지에 추가해야 합니다.