박용준 강사님 blazor 강의 후 메모 용도로 작성
blazor에 장점
쉽게 SPA(single Page Application)을 만들 수 있고 생산성이 높다.
장점 | 단점 |
---|---|
전체페이지를 업데이트할 필요가 없어서 깜빡 거림이 없다. (자연스러운 사용자 경험 - ux) | 초기 구동 속도가 느리다 (웹팩의 code splitting으로 해결 가능) |
필요한 리소스만 부분적으로 로딩(성능)SPA의 어플리케이션은 서버에게 정적리소르를 한 번만 요청하고 받은 데이터는 전부 저장해놓는다. | SEO가 어렵다(SSR로 해결 가능) |
서버의 템플릿 연산을 클라이언트로 분산(성능) | 보안 이슈(프론트엔드 비즈니스 로직 최소화) |
컴포넌트별 개발 용이(생산성) | |
모바일 앱 개발을 생각하고 있다면 동일한 API를 사용하도록 설계 가능 (생산성) |
아래 쉽게 설명을 잘 해주신거 같아 참조
https://blog.naver.com/dev_wise/222707159385
using System.ComponentModel.DataAnnotations;
namespace BlazorApp.Models
{
public class Idea
{
public int Id { get; set; }
[Required] // Required 필수 한정자 초기화를 강제성 부여
public string Note { get; set; }
}
}
namespace BlazorApp.Models
{
public interface IIdeaRepository
{
Task<Idea> AddIdea(Idea idea);
Task<List<Idea>> GetIdeas();
}
}
using BlazorApp.Data;
using Microsoft.EntityFrameworkCore;
namespace BlazorApp.Models
{
public class IdeaRepository : IIdeaRepository
{
private readonly ApplicationDbContext _context;
public IdeaRepository(ApplicationDbContext context)
{
_context = context;
}
public async Task<Idea> AddIdea(Idea idea)
{
_context.Ideas.Add(idea);
_context.SaveChanges(); //Db동기화
return idea;
}
//Db에서 목록 조회 하여 return;
public async Task<List<Idea>> GetIdeas()
{
return await _context.Ideas.ToListAsync();
}
}
}
using BlazorApp.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace BlazorApp.Data
{
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
/*모델 추가*/
public DbSet<Idea> Ideas { get; set; }
}
}
미리 만들어둔 모델을 추가
public DbSet Ideas { get; set; }
패키지콘솔에서
1. Add-Migration 마이그레이션 추가.
2. Update-Database 데이터 베이스 동기화
@using BlazorApp.Data
@using BlazorApp.Models;
<!--라우팅 경로-->
@page "/Idea"
<!--의존성주입-->
@inject IIdeaRepository Repository
<h3>Idea</h3>
<!--IdeaList를 db에서 받아오지 못했을때 loading.. 문구 출력-->
@if (IdeaList == null)
{
<p><em>Loading...</em></p>
}
else
{
<!--IdeaList를 테이블 형태로 출력-->
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>NOTE</th>
</tr>
</thead>
<tbody>
@foreach (var idea in IdeaList)
{
<tr>
<td>@idea.Id</td>
<td>@idea.Note</td>
</tr>
}
</tbody>
</table>
}
<!--idea를 입력할 모달폼 팝업-->
<button style="button" class="close" @onclick="btnCreate_Click">글쓰기</button>
<!--note를 등록하기 위한 모달폼-->
@if(isShow)
{
<div class="modal" tabindex="-1" role="dialog" style="display:block;">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">어떤 아이디어가 있나요?</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" @onclick="btnClose_Click">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<label for="note">아이디어</label>
<input type="text" class="form-control" @bind="@idea.Note">
<button type="button" class="btn btn-primary" @onclick="btnSave_Click">Submit</button>
</div>
</div>
</div>
</div>
}
@code {
private Idea idea = new Idea() ;
private List<Idea> IdeaList;
private bool isShow;
//처음 페이지 실행시 실행하는 메소드
protected override async Task OnInitializedAsync()
{
IdeaList = await Repository.GetIdeas();
}
private async Task btnSave_Click()
{
await Repository.AddIdea(idea); //Db에 insert
IdeaList = await Repository.GetIdeas(); //Db에서 리스트 조회
idea = new Idea();
isShow = false;
}
//모달폼 팝업
private void btnCreate_Click()
{
isShow = true;
}
private void btnClose_Click()
{
isShow = false;
idea = new Idea();
}
}
새로 생성한 IdeaRepoistory만 추가.
builder.Services.AddTransient<IIdeaRepository, IdeaRepository>();
강의에서는 Transient로 했지만 Scoped가 더 나은거 같아 보임.
using BlazorApp.Areas.Identity;
using BlazorApp.Data;
using BlazorApp.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddTransient<IIdeaRepository, IdeaRepository>(); //IdeaRepository 의존성 주입 요청 할때마다 새로운 개체 생성
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
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.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
1. AddTransient
Transient 수명 서비스(AddTransient)는 서비스 컨테이너에서 요청할 때마다 만들어집니다.
이 수명은 간단한 상태 비저장 서비스에 가장 적합합니다.
2. Scoped
Scoped 수명 서비스(AddScoped)는 클라이언트 요청(연결)당 한 번 생성됩니다.
3. singleton
싱글톤 수명 서비스(AddSingleton)는 처음 요청할 때(또는 Startup.ConfigureServices를 실행하고 서비스 등록에서 인스턴스를 지정하는 경우) 생성됩니다. 모든 후속 요청에서는 같은 인스턴스를 사용합니다. 앱에 싱글톤 동작이 필요한 경우 서비스 컨테이너가 서비스 수명을 관리하도록 허용하는 것이 좋습니다. 싱글톤 디자인 패턴을 구현하거나 클래스의 개체 수명을 관리하는 사용자 코드를 제공하지 마세요.
코드 실행 화면
말하기 조심스럽습니다만 박용준씨는 너무 돈에 미친사람같습니다.
고급강의를 유료화 한다면 아무생각하지 않고 결제하겠지만
초중급 강의의 후반부를 유료화 해서 초반에 접근하는 사람들을 당혹스럽게 하는 영상들이 좀 있더라구요.
4년전인가.. ASP 관련 외국 레퍼런스들을 보면 이해충돌이 생기는 문장들로 인해 한국 강의를 찾던중 우연히 찾게 되었는데..
요즘은 어떤지 모르겠지만 초반에 너무 돈미새 느낌을 확 받았더니 목소리만 들어도 짜증이 나서 다시는 보고 싶지도 추천하고싶지도 않습니다.