구성 요소 통신과 DI
부모 구성 요소와 자식 구성 요소 사이에 데이터를 전달하고 계단식 매개 변수를 사용하며 구성 요소에 서비스를 주입합니다.
구성 요소 통신과 DI은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
컴포넌트 통신 패턴
Blazor 컴포넌트는 세 방향으로 통신합니다. 부모에서 자식으로(매개 변수), 자식에서 부모로(EventCallback), 그리고 트리 전체에서(CascadingParameters 또는 DI를 통한 공유 서비스) 통신할 수 있습니다.
부모에서 자식으로: 매개 변수
컴포넌트 속성에 [Parameter]를 지정하면 부모에서 해당 속성의 값을 설정할 수 있습니다. 부모는 컴포넌트 태그의 HTML 속성으로 값을 전달합니다.
@* Child: Alert.razor *@
<div class="alert alert-@Type">
@Message
</div>
@code {
[Parameter] public string Type { get; set; } = "info"; // primary, warning, danger
[Parameter, EditorRequired] public string Message { get; set; } = "";
}
@* Parent usage: *@
<Alert Type="danger" Message="Something went wrong!" />
<Alert Message="Record saved." />자식에서 부모로: EventCallback
자식 컴포넌트는 EventCallback 매개 변수를 노출합니다. 부모는 처리기 메서드를 제공합니다. 자식은 어떤 일이 발생했을 때 이 메서드를 호출합니다.
@* Child: QuantityPicker.razor *@
<button @onclick="() => OnChanged.InvokeAsync(Value - 1)">-</button>
<span>@Value</span>
<button @onclick="() => OnChanged.InvokeAsync(Value + 1)">+</button>
@code {
[Parameter] public int Value { get; set; } = 1;
[Parameter] public EventCallback<int> OnChanged { get; set; }
}
@* Parent: *@
<QuantityPicker Value="@_qty" OnChanged="q => _qty = q" />
<p>Quantity: @_qty</p>부모를 통한 형제 컴포넌트 통신
형제 컴포넌트가 통신해야 한다면 공통 부모를 통해 데이터를 전달합니다. 부모가 공유 상태를 보유하고 이를 매개 변수로 자식 컴포넌트에 전달합니다.
@* Parent holds shared state *@
<CategoryFilter OnChanged="c => _category = c" />
<ProductList Category="_category" />
@code {
private string _category = "All";
}
@* CategoryFilter raises an event -> Parent updates _category
-> ProductList re-renders with new Category *@계단식 매개 변수
<CascadingValue>로 하위 트리를 감싸면 모든 하위 컴포넌트에 데이터를 전달할 수 있으며, 중간 컴포넌트마다 데이터를 전달할 필요가 없습니다.
@* Wrap a subtree *@
<CascadingValue Value="_theme">
<MainLayout />
</CascadingValue>
@code { private Theme _theme = new Theme { PrimaryColor = "#6366f1" }; }
@* Any descendant can receive it: *@
@code {
[CascadingParameter]
public Theme AppTheme { get; set; } = default!;
}
<h1 style="color: @AppTheme.PrimaryColor">Hello</h1>@inject를 사용한 서비스 주입
@inject 지시문을 사용하면 등록된 DI 서비스를 컴포넌트에 직접 주입할 수 있습니다. 서비스는 프레임워크가 자동으로 확인합니다.
@inject IProductService ProductSvc
@inject ILogger<ProductList> Logger
@inject NavigationManager Nav
@code {
private List<Product> _products = new();
protected override async Task OnInitializedAsync()
{
Logger.LogInformation("Loading products");
_products = await ProductSvc.GetAllAsync();
}
private void GoToProduct(int id)
=> Nav.NavigateTo($"/products/{id}");
}Blazor Server의 범위 지정 서비스
Blazor Server에서는 DI 범위가 단일 요청에만 한정되지 않고 SignalR 연결의 전체 수명 동안 유지됩니다. 범위 지정 서비스가 하나의 회로에 있는 모든 컴포넌트에서 공유된다는 점에 유의하십시오.
// Blazor Server: scoped = per circuit (connection lifetime)
builder.Services.AddScoped<CartService>();
// All components in the same browser tab share the SAME CartService
// This is GOOD for cart state (user's items persist across pages)
// This is BAD for request-scoped data — treat as session-like scope
// For true per-render-cycle scope, create your own:
using var scope = ScopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();라우팅에 사용하는 NavigationManager
NavigationManager를 주입하면 프로그래밍 방식으로 이동하고, 현재 URL을 읽으며, 탐색 이벤트를 처리할 수 있습니다.
@inject NavigationManager Nav
@code {
private void GoHome() => Nav.NavigateTo("/");
private void GoToProduct(int id) => Nav.NavigateTo($"/products/{id}");
private void ForceReload() => Nav.NavigateTo("/", forceLoad: true);
protected override void OnInitialized()
{
// Read current URL
var uri = Nav.Uri;
var path = new Uri(uri).AbsolutePath;
}
}Blazor WASM의 HttpClient
Blazor WebAssembly에서는 미리 구성된 HttpClient를 주입하여 API를 호출합니다. Program.cs에서 기본 주소와 함께 등록하십시오.
// Program.cs (Blazor WASM)
builder.Services.AddScoped(sp => new HttpClient
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
// Component:
@inject HttpClient Http
@code {
private List<Product> _products = new();
protected override async Task OnInitializedAsync()
{
_products = await Http.GetFromJsonAsync<List<Product>>("/api/products")
?? new();
}
}실전: 사용자 컨텍스트 서비스
범위 지정 UserContextService를 앱 전체의 여러 컴포넌트에 주입하면 각 컴포넌트가 속성을 여러 단계로 전달하지 않고도 동일한 사용자 데이터를 확인할 수 있습니다.
public class UserContextService
{
public string? Name { get; private set; }
public bool IsAdmin { get; private set; }
public async Task InitializeAsync(AuthenticationState auth)
{
var user = auth.User;
Name = user.Identity?.Name;
IsAdmin = user.IsInRole("Admin");
}
}
// Registered as scoped:
builder.Services.AddScoped<UserContextService>();
// Used in any component:
@inject UserContextService UserCtx
<p>Hello, @UserCtx.Name @(UserCtx.IsAdmin ? "(Admin)" : "")</p>빠른 확인
Blazor Server에서 '범위 지정' DI 서비스의 수명은 얼마나 지속됩니까?
복습: 컴포넌트 통신과 DI
핵심 요점:
- 부모 → 자식: [Parameter] 속성, 필수 매개 변수에는 [EditorRequired] 사용
- 자식 → 부모: EventCallback, 부모의 StateHasChanged를 자동으로 트리거
- 형제 컴포넌트: 부모 상태를 통해 전달하거나 공유 DI 서비스 사용
- 트리 전체: 깊은 하위 트리에는 CascadingValue/CascadingParameter 사용
- 서비스에는 @inject 사용, Blazor Server의 범위 지정 서비스는 회로의 수명 동안 유지
- 프로그래밍 방식 라우팅에는 NavigationManager 사용
자주 묻는 질문
“구성 요소 통신과 DI” 강의는 무료인가요?
네 — “구성 요소 통신과 DI” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“구성 요소 통신과 DI”에서 뭘 배우나요?
부모 구성 요소와 자식 구성 요소 사이에 데이터를 전달하고 계단식 매개 변수를 사용하며 구성 요소에 서비스를 주입합니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
C# Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“구성 요소 통신과 DI” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- Blazor 구성 요소 모델
- 데이터 바인딩과 이벤트 처리
- 구성 요소 통신과 DI
- Blazor의 상태 관리