[.NET] Visual Studio 2022 Blazor Web App에 Ant Design 적용하기

.NET에 Ant Design을 적용하려면 크게 두가지 방법이 있음

 

1. 처음부터 Ant Design 적용된 프로젝트 생성

2. 기존 프로젝트에 Ant Design 추가

 

1번으로 해봤는데 기본 레이아웃이 지저분하고, 구조도 어떤 구조로 (Blazor Server 앱인지, Blazor WebAssembly 독립 실행형 앱인지, Blazor Web App인지) 만든건지 잘 모르겠음

 

그래서 2번으로 하는걸 추천

 

관련 내용은 https://antblazor.com/en-US/docs/introduce 이 링크를 참고(하면 될줄 알았는데 누락된 내용이 있음)

 

아래 내용은 https://github.com/ant-design-blazor/ant-design-blazor GitHub README.md Option 2 참고하여 진행한 내용

 

etc-image-0

VS 2022 새 프로젝트 만들기에서 Blazor Web App 프로젝트 선택

etc-image-1

프로젝트 이름, 위치 변경

etc-image-2

 

프레임워크는 특별한 이유 없으면 최신버전인 .NET 9.0

인증 유형은 기본으로 로그인 기능 추가해주냐는건데 없음으로

HTTPS에 대한 구성은 자체 인증서를 사용해서 HTTPS 로컬 서버를 돌린다는 얘기.

HTTPS는 API 호출할 때 이슈가 있을 수 있기 때문에 (프로토콜이 다르면 API 호출 불가. HTTP -> HTTPS, HTTPS -> HTTP) 로컬 환경을 고려해서 선택

Include sample pages는 샘플 페이지 추가할거냐는건데 공부할 목적이므로 체크

 

PS C:\Users\user> cd D:\Project\BlazorApp\BlazorApp\
PS D:\Project\BlazorApp\BlazorApp> dotnet add package AntDesign

성공 빌드(0.6초)
info : X.509 인증서 체인 유효성 검사는 코드 서명에 .NET에서 선택한 기본 신뢰 저장소를 사용합니다.
info : X.509 인증서 체인 유효성 검사는 타임스탬프에 .NET에서 선택한 기본 신뢰 저장소를 사용합니다.
info : 'D:\Project\BlazorApp\BlazorApp\BlazorApp.csproj' 프로젝트에 'AntDesign' 패키지에 대한 PackageReference를 추가하 는 중입니다.
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/index.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/index.json 711밀리초
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.0.1-v5-240718134117/0.1.0-nightly-200617074142.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.0.1-v5-240718134117/0.1.0-nightly-200617074142.json 699밀리초
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.1.0-nightly-200619143949/0.2.0-nightly-200709062450.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.1.0-nightly-200619143949/0.2.0-nightly-200709062450.json 701밀리초
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.2.0-nightly-200709081807/0.2.0-nightly-200729162305.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.2.0-nightly-200709081807/0.2.0-nightly-200729162305.json 706밀리초
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.2.0-nightly-200730011207/0.3.0-nightly-2008310357.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.2.0-nightly-200730011207/0.3.0-nightly-2008310357.json 700밀리초
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.3.0-nightly-2008310805/0.4.0-nightly-2010090340.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.3.0-nightly-2008310805/0.4.0-nightly-2010090340.json 691밀리초
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.4.0-nightly-2010090618/0.5.0-nightly-2011160229.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.4.0-nightly-2010090618/0.5.0-nightly-2011160229.json 713밀리초
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.5.0-nightly-2011160506/0.5.0-nightly-2012291552.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.5.0-nightly-2011160506/0.5.0-nightly-2012291552.json 700밀리초
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.5.0-nightly-2012300110/0.6.0-nightly-2102030652.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.5.0-nightly-2012300110/0.6.0-nightly-2102030652.json 699밀리초
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.6.0-nightly-2102030742/0.10.3.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.6.0-nightly-2102030742/0.10.3.json 702밀 리초
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.10.3.1/0.16.4-beta2.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.10.3.1/0.16.4-beta2.json 691밀리초
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.17.0/2.0.0-nightly-241223160948.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/antdesign/page/0.17.0/2.0.0-nightly-241223160948.json 698 밀리초
info : D:\Project\BlazorApp\BlazorApp\BlazorApp.csproj의 패키지를 복원하는 중...
info :   GET https://api.nuget.org/v3/vulnerabilities/index.json
info :   OK https://api.nuget.org/v3/vulnerabilities/index.json 527밀리초
info :   GET https://api.nuget.org/v3-vulnerabilities/2024.12.21.05.12.11/vulnerability.base.json
info :   GET https://api.nuget.org/v3-vulnerabilities/2024.12.21.05.12.11/2024.12.23.23.12.18/vulnerability.update.json
info :   OK https://api.nuget.org/v3-vulnerabilities/2024.12.21.05.12.11/vulnerability.base.json 133밀리초
info :   OK https://api.nuget.org/v3-vulnerabilities/2024.12.21.05.12.11/2024.12.23.23.12.18/vulnerability.update.json 136밀리초
info : 'AntDesign' 패키지는 'D:\Project\BlazorApp\BlazorApp\BlazorApp.csproj' 프로젝트에 지정된 모든 프레임워크와 호환됩니다.
info : 'AntDesign' 패키지 '1.0.1' 버전에 대한 PackageReference가 'D:\Project\BlazorApp\BlazorApp\BlazorApp.csproj' 파일 에 추가되었습니다.
info : MSBuild 파일 D:\Project\BlazorApp\BlazorApp\obj\BlazorApp.csproj.nuget.g.props을(를) 생성하고 있습니다.
info : MSBuild 파일 D:\Project\BlazorApp\BlazorApp\obj\BlazorApp.csproj.nuget.g.targets을(를) 생성하고 있습니다.
info : 자산 파일을 디스크에 쓰는 중입니다. 경로: D:\Project\BlazorApp\BlazorApp\obj\project.assets.json
log  : D:\Project\BlazorApp\BlazorApp\BlazorApp.csproj을(를) 876밀리초 동안 복원했습니다.

 

프로젝트 생성 완료하였으면 PowerShell열고 Ant Design 라이브러리 추가

using BlazorApp.Components;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAntDesign();

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
}


app.UseAntiforgery();

app.MapStaticAssets();
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

 

Program.cs 파일에 builder.Services.AddAntDesign(); 코드 추가

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using BlazorApp
@using BlazorApp.Components
@using AntDesign

 

Components\_Imports.razor 파일에 @using AntDesign 코드 추가

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
    <link rel="stylesheet" href="@Assets["app.css"]" />
    <link rel="stylesheet" href="@Assets["BlazorApp.styles.css"]" />
    <link href="_content/AntDesign/css/ant-design-blazor.css" rel="stylesheet">
    <ImportMap />
    <link rel="icon" type="image/png" href="favicon.png" />
    <HeadOutlet />
</head>

<body>
    <Routes />
    <script src="_framework/blazor.web.js"></script>
    <script src="_content/AntDesign/js/ant-design-blazor.js"></script>
</body>

</html>

 

Components\App.razor 파일에 Ant Design css, js 파일 추가

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
    <link rel="stylesheet" href="@Assets["app.css"]" />
    <link rel="stylesheet" href="@Assets["BlazorApp.styles.css"]" />
    <link href="_content/AntDesign/css/ant-design-blazor.css" rel="stylesheet">
    <ImportMap />
    <link rel="icon" type="image/png" href="favicon.png" />
    <HeadOutlet />
</head>

<body>
    <Routes @rendermode="RenderMode.InteractiveServer" />
    <script src="_framework/blazor.web.js"></script>
    <script src="_content/AntDesign/js/ant-design-blazor.js"></script>
</body>

</html>

 

Components\App.razor 파일에 있는 Routes 태그에 @rendermode 속성을 RenderMode.InteractiveServer로 추가해준다.

@page "/counter"

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

 

App.razor 파일의 Routes에서 rendermode를 지정했으므로, Components\Pages\Counter.razor 파일에 있는 @rendermode InteractiveServer 코드를 지워준다.

 

이제 잘 적용되었는지 컴포넌트를 추가해서 확인해보자

 

<Button Type="@ButtonType.Primary">Primary</Button>

https://antblazor.com/en-US/components/button 링크를 클릭하여 Button 컴포넌트 코드를 복사한다.

@page "/counter"

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<Button Type="@ButtonType.Primary">Primary</Button>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

 

Components\Pages\Counter.razor 파일 <h1>Counter</h1> 아래에 복사한 Button 컴포넌트 코드를 추가해준다.

PS D:\Project\BlazorApp\BlazorApp> dotnet run watch
D:\Project\BlazorApp\BlazorApp\Properties\launchSettings.json의 시작 설정을 사용하는 중...
빌드하는 중...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5084
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\Project\BlazorApp\BlazorApp

etc-image-3

PowerShell에서 실행하거나 Visual Studio 2022에서 초록색 http 버튼을 눌러서 실행한다.

etc-image-4

왼쪽 Counter 메뉴를 클릭하면 오른쪽에 Ant Design이 적용된 Primary 버튼이 추가된것을 볼 수 있다.