MVVM 툴킷 및 RelayCommands로 Blazor 서버 애플리케이션 만들기 | bromix

MVVM 툴킷 및 RelayCommands로 Blazor 서버 애플리케이션 만들기 | bromix

·

4 min read

bromix님의 Creating a Blazor Server Application with MVVM Toolkit and RelayCommands를 번역하였습니다.


이전 글에서는 Blazor와 함께 MVVM 툴킷을 시작하기 위한 기본 사항을 살펴보았습니다. 뷰모델에서 속성과 커스텀 함수를 사용하는 방법을 시연했습니다. 하지만 명령어 사용에 대해서는 자세히 다루지 않았습니다.

이번 후속 글에서는 이전 작업을 기반으로 최적의 코드를 작성하고 웹페이지에서 로직을 분리하여 유지 관리가 훨씬 더 쉬운 코드를 생성하는 RelayCommands를 도입하여 이전 작업을 구축할 것입니다.

새 WeatherViewModel 만들기

프로젝트에서 ViewModels 폴더 아래에서 WeatherViewModel.cs 파일을 찾습니다. WeatherViewModel2.cs 라는 이름으로 ViewModel의 복사본을 만듭니다.

MVVM 툴킷의 RelayCommands를 사용하기 위해 CommunityToolkit.Mvvm.Input 네임스페이스를 가져와서 WeatherViewModel2.cs 파일을 업데이트합니다. 그런 다음 이전의 메서드를 대체하고 날씨 데이터의 로딩을 처리하기 위해 Load라는 비공개 메서드를 추가하고 RelayCommand 특성으로 꾸밉니다. MVVM 툴킷의 소스 생성기는 LoadCommand라는 공용 속성을 생성하며, 이 속성은 나중에 FetchData2.razor 페이지에서 사용할 수 있습니다. 또한 이전에 로딩 상태를 추적하는 데 사용했던 비공개 _isLoading 프로퍼티를 제거할 수 있는데, 이는 나중에 LoadCommand에서 처리할 것이기 때문입니다.

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ExamplesBlazorMvvmToolkit.Data;

namespace ExamplesBlazorMvvmToolkit.ViewModels;

internal sealed partial class WeatherViewModel2 : ObservableObject
{
    private readonly WeatherForecastService _weatherService;

    public WeatherViewModel2(WeatherForecastService weatherService)
    {
        _weatherService = weatherService;
    }

    [ObservableProperty] private WeatherForecast[] _forecasts = Array.Empty<WeatherForecast>();

    [RelayCommand]
    private async Task Load()
    {
        await Task.Delay(TimeSpan.FromSeconds(2)); // simulate loading
        Forecasts = await _weatherService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
    }
}

새 FetchData 페이지 만들기

프로젝트의 페이지 폴더에서 FetchData.razor 파일을 찾습니다. 파일 이름을 FetchData2.razor로 지정하고 복사본을 만듭니다.

FetchData2.razor에서 마크업과 코드 뒷부분을 약간 변경합니다. @page 지시문을 "/fetchdata2"로 업데이트하고 @inject 지시문을 업데이트하여 새 WeatherViewModel2를 페이지에 삽입합니다. 또한 날씨 데이터를 로드하는 명령을 트리거하는 버튼을 추가하는데, 이 버튼은 명령이 실행되는 동안에는 비활성화됩니다. 또한 IsLoading 속성의 사용을 제거하고 이를 WeatherViewModel2의 일부인 LoadCommandIsRunning 속성으로 대체했습니다. 코드 비하인드에서는 사용자가 버튼을 클릭할 때 LoadCommand를 실행하는 Reload라는 메서드도 추가합니다. 또한 명령이 실행 중인지 여부에 따라 버튼 텍스트를 변경하기 위해 개인 속성 ReloadText를 추가합니다.

@page "/fetchdata2"
@using ExamplesBlazorMvvmToolkit.ViewModels
@inject WeatherViewModel2 ViewModel

<PageTitle>Weather forecast</PageTitle>

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from a view model by using commands.</p>

<button class="btn btn-primary" disabled="@ViewModel.LoadCommand.IsRunning" @onclick="Reload">@ReloadText</button>
<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 ViewModel.Forecasts)
    {
        <tr>
            <td>@forecast.Date.ToShortDateString()</td>
            <td>@forecast.TemperatureC</td>
            <td>@forecast.TemperatureF</td>
            <td>@forecast.Summary</td>
        </tr>
    }
    </tbody>
</table>

@code {

    protected override async Task OnInitializedAsync()
    {
        await ViewModel.LoadCommand.ExecuteAsync(null);
    }

    private async Task Reload()
    {
        await ViewModel.LoadCommand.ExecuteAsync(null);
    }

    private string ReloadText => ViewModel.LoadCommand.IsRunning ? "Loading..." : "Reload";
}

FetchData2.razor에서 가장 중요한 변경 사항은 ViewModel에서 LoadCommand 속성을 사용한다는 것입니다. 이 속성은 WeatherViewModel2.cs파일의 RelayCommand 속성을 기반으로 MVVM 툴킷의 소스 생성기에 의해 자동으로 생성됩니다.

LoadCommand 속성은 이전 버전의 뷰 모델에서 사용되었던 IsLoading 프로퍼티를 대체합니다. 이는 LoadCommand 속성에 명령의 실행 상태를 추적하는 IsRunning 속성이 내장되어 있기 때문입니다.

Razor 컴포넌트에서는 날씨 데이터의 로딩을 처리하기 위해 LoadCommand 속성을 사용합니다. LoadCommand가 실행 중일 때는 다시 로드 버튼을 비활성화하고 "로드 중..."이라는 텍스트를 표시합니다. 데이터가 로드되면 버튼을 활성화하고 "다시 로드"라는 텍스트를 표시합니다.

내비게이션 및 서비스 등록 업데이트

NavMenu에 새 탐색 항목을 추가하려면 NavMenu.razor 파일을 수정해야 합니다. FetchData 페이지로 이동하는 기존 NavLink 컴포넌트를 복사하고 새로운 FetchData2 페이지로 이동하도록 수정하면 됩니다:

using ExamplesBlazorMvvmToolkit.Data;
using ExamplesBlazorMvvmToolkit.ViewModels;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddScoped<WeatherViewModel>();
builder.Services.AddScoped<WeatherViewModel2>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

쇼타임

프로젝트를 시작하고 '데이터 가져오기(#2)'를 선택하면 초기 로딩이 나타납니다. 이 시간 동안에는 원치 않는 클릭을 방지하기 위해 다시 로드 버튼이 비활성화됩니다. 날씨 데이터가 로드되면 다시 로드 버튼이 활성화됩니다. 그러나 이후 다시 로드 버튼을 클릭하면 다시 한 번 비활성화됩니다.

결론

MVVM 툴킷을 Blazor와 함께 사용하여 보다 유지 관리가 용이하고 분리된 코드베이스를 만드는 방법을 배웠습니다. RelayCommands의 사용법을 소개하고 로딩 상태를 수동으로 추적할 필요성을 내장된 IsRunning 속성으로 대체하는 방법을 시연했습니다. 또한 MVVM 툴킷의 소스 제너레이터를 사용하여 뷰모델의 릴레이 명령 속성을 기반으로 공개 명령을 자동으로 생성하는 방법도 보여드렸습니다. 이러한 단계를 따라 개발자는 유지 관리 및 업데이트가 더 쉬운 강력하고 확장 가능한 Blazor 애플리케이션을 만들 수 있습니다.

3부 MVVM 툴킷을 사용한 블레이저에서 쉽게 비동기 명령 취소하기에서는 릴레이 명령과 비동기 메서드에 대해 자세히 살펴봅니다.

Blazor와 함께 MVVM 툴킷을 사용하기 위한 예제 프로젝트는 GitHub 리포지토리에서 확인할 수 있습니다:

https://github.com/bromix/ExamplesBlazorMvvmToolkit.