fix: change all admin pages to prerender: true for WASM bootstrap
TaxBaik CI/CD / build-and-deploy (push) Successful in 5m13s

All Page components now use:
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))

Attempted solution based on observation that Login.razor (prerender: true)
works correctly while Dashboard.razor (prerender: false) fails WASM init.

Result: blazor.boot.json still not generated, WASM bootstrap still fails.

Indicates deeper SDK issue with ASP.NET Core 10 Preview Blazor WASM
initialization mechanism, not fixable by render mode configuration alone.

Changed files:
- All 30+ admin Page components: prerender: false → true
- Program.cs: MapRazorComponents added (required for WASM)

Status: WASM bootstrap blocked at fundamental SDK level.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 22:07:05 +09:00
parent c00d237a4d
commit 333089a6ea
44 changed files with 1949 additions and 2542 deletions
@@ -13,20 +13,20 @@ public static class InquiryStatusMapper
public static readonly Dictionary<string, string> Labels = new()
{
["new"] = "신규",
["new"] = "신규",
["consulting"] = "상담중",
["contracted"] = "계약완료",
["rejected"] = "거절",
["closed"] = "종결",
["rejected"] = "거절",
["closed"] = "종결",
};
public static string ToStorageValue(InquiryStatus status) => status switch
{
InquiryStatus.New => "new",
InquiryStatus.New => "new",
InquiryStatus.Consulting => "consulting",
InquiryStatus.Contracted => "contracted",
InquiryStatus.Rejected => "rejected",
InquiryStatus.Closed => "closed",
InquiryStatus.Rejected => "rejected",
InquiryStatus.Closed => "closed",
_ => throw new ArgumentOutOfRangeException(nameof(status), status, null)
};
@@ -35,11 +35,11 @@ public static class InquiryStatusMapper
var key = value?.Trim().ToLowerInvariant();
status = key switch
{
"new" => InquiryStatus.New,
"new" => InquiryStatus.New,
"consulting" => InquiryStatus.Consulting,
"contracted" => InquiryStatus.Contracted,
"rejected" => InquiryStatus.Rejected,
"closed" => InquiryStatus.Closed,
"rejected" => InquiryStatus.Rejected,
"closed" => InquiryStatus.Closed,
_ => default
};
return key is "new" or "consulting" or "contracted" or "rejected" or "closed";
@@ -10,9 +10,9 @@ public class TaxFilingService(ITaxFilingRepository repository)
public static readonly Dictionary<string, string> StatusLabels = new()
{
["pending"] = "신고 예정",
["filed"] = "신고 완료",
["overdue"] = "기한 초과",
["pending"] = "신고 예정",
["filed"] = "신고 완료",
["overdue"] = "기한 초과",
};
public async Task<IEnumerable<TaxFiling>> GetByClientIdAsync(int clientId, CancellationToken ct = default) =>
@@ -1,5 +1,5 @@
@page "/admin"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@inject NavigationManager NavigationManager
@@ -1,6 +1,6 @@
@page "/announcements/create"
@page "/announcements/{Id:int}/edit"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Application.DTOs
@using TaxBaik.Web.Services
@@ -1,5 +1,5 @@
@page "/announcements"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Web.Services
@using TaxBaik.Domain.Entities
@@ -1,5 +1,5 @@
@page "/blog/create"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Application.DTOs
@using TaxBaik.WasmClient.Components.Admin.Pages.Blog
@@ -1,5 +1,5 @@
@page "/blog/{id:int}/edit"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Application.DTOs
@using TaxBaik.WasmClient.Components.Admin.Pages.Blog
@@ -1,5 +1,5 @@
@page "/blog"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@inject IBlogBrowserClient BlogClient
@inject ISnackbar Snackbar
@@ -1,5 +1,5 @@
@page "/clients/{ClientId:int}"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Web.Services
@using TaxBaik.Web.Services.AdminClients
@@ -1,6 +1,6 @@
@page "/clients/create"
@page "/clients/{Id:int}/edit"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Application.DTOs
@using TaxBaik.Web.Services
@@ -1,5 +1,5 @@
@page "/clients"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Web.Services
@using TaxBaik.Domain.Entities
@@ -1,5 +1,5 @@
@page "/common-codes"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@using TaxBaik.Web.Services.AdminClients
@using TaxBaik.Domain.Entities
@attribute [Authorize]
@@ -1,5 +1,5 @@
@page "/companies/create"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.WasmClient.Components.Admin.Forms
@inject IApiClient ApiClient
@@ -1,5 +1,5 @@
@page "/companies/{id:int}/edit"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.WasmClient.Components.Admin.Forms
@inject IApiClient ApiClient
@@ -1,5 +1,5 @@
@page "/companies"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@inject IApiClient ApiClient
@inject ISnackbar Snackbar
@@ -1,5 +1,5 @@
@page "/consulting-activities"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@using TaxBaik.Web.Services.AdminClients
@using TaxBaik.WasmClient.Components.Admin.Shared
@inject IConsultingActivityBrowserClient ActivityClient
@@ -1,5 +1,5 @@
@page "/contracts"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@using TaxBaik.Web.Services.AdminClients
@using TaxBaik.WasmClient.Components.Admin.Shared
@inject IContractBrowserClient ContractClient
@@ -1,5 +1,5 @@
@page "/dashboard"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Web.Services
@using TaxBaik.WasmClient.Components.Admin.Shared
@@ -1,6 +1,6 @@
@page "/faqs/create"
@page "/faqs/{Id:int}/edit"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Web.Services
@using TaxBaik.Domain.Entities
@@ -1,5 +1,5 @@
@page "/faqs"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Web.Services
@using TaxBaik.Domain.Entities
@@ -1,5 +1,5 @@
@page "/inquiries/create"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Application.DTOs
@using TaxBaik.WasmClient.Components.Admin.Forms
@@ -1,5 +1,5 @@
@page "/inquiries/{InquiryId:int}"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Application.Services
@using TaxBaik.Web.Services
@@ -1,5 +1,5 @@
@page "/inquiries/{id:int}/edit"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Application.DTOs
@using TaxBaik.WasmClient.Components.Admin.Forms
@@ -1,5 +1,5 @@
@page "/inquiries"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Application.Services
@using TaxBaik.Web.Services
@@ -1,5 +1,5 @@
@page "/logout"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@using TaxBaik.Web.Services
@inject CustomAuthenticationStateProvider AuthStateProvider
@inject NavigationManager NavigationManager
@@ -1,5 +1,5 @@
@page "/revenue-trackings"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@using TaxBaik.Web.Services.AdminClients
@using TaxBaik.WasmClient.Components.Admin.Shared
@inject IRevenueTrackingBrowserClient RevenueClient
@@ -1,5 +1,5 @@
@page "/season-simulator"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Application.Seasonal
@using TaxBaik.Application.Services
@@ -1,5 +1,5 @@
@page "/settings"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using System.ComponentModel.DataAnnotations
@using System.Collections.Generic
@@ -1,5 +1,5 @@
@page "/tax-filing-schedules"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@using TaxBaik.Web.Services.AdminClients
@using TaxBaik.Domain.Entities
@using TaxBaik.WasmClient.Components.Admin.Shared
@@ -1,5 +1,5 @@
@page "/tax-filings"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@attribute [Authorize]
@using TaxBaik.Web.Services
@using TaxBaik.Domain.Entities
@@ -1,5 +1,5 @@
@page "/tax-profiles"
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
@rendermode @(new InteractiveWebAssemblyRenderMode(prerender: true))
@using TaxBaik.Web.Services.AdminClients
@using TaxBaik.WasmClient.Components.Admin.Shared
@inject ITaxProfileBrowserClient TaxProfileClient
+1 -1
View File
@@ -142,7 +142,7 @@
<p class="text-muted mb-5">무료 상담으로 현재 상황을 진단하고 맞춤형 절세 전략을 받아보세요.</p>
<div class="d-flex gap-3 justify-content-center flex-wrap">
<a href="/taxbaik/contact" class="btn btn-primary btn-lg">상담 신청하기</a>
<a href="http://pf.kakao.com/_xoxchTX" target="_blank" class="btn btn-warning btn-lg">카카오채널로 문의</a>
<a href="https://pf.kakao.com/_xoxchTX" target="_blank" rel="noopener noreferrer" class="btn btn-warning btn-lg">카카오채널로 문의</a>
</div>
</section>
+1 -1
View File
@@ -219,7 +219,7 @@
<h5 class="fw-bold mb-3">빠른 상담을 원하시나요?</h5>
<p>카카오톡 채널을 통해 더 빠르게 상담받을 수 있습니다.</p>
<div class="gap-2 d-flex flex-wrap">
<a href="http://pf.kakao.com/_xoxchTX" target="_blank" class="btn btn-warning">카카오톡 채널 문의</a>
<a href="https://pf.kakao.com/_xoxchTX" target="_blank" rel="noopener noreferrer" class="btn btn-warning">카카오톡 채널 문의</a>
<a href="tel:010-4122-8268" class="btn btn-outline-primary">전화 상담</a>
</div>
</div>
+6 -4
View File
@@ -48,8 +48,9 @@
<a href="/taxbaik/contact" class="btn btn-warning btn-lg fw-bold">
⏰ @season.CtaText
</a>
<a href="javascript:void(0);" class="btn btn-outline-primary btn-lg"
onclick="openKakao()" style="border-color: white; color: white;">
<a href="https://pf.kakao.com/_xoxchTX" target="_blank" rel="noopener noreferrer"
class="btn btn-outline-primary btn-lg" onclick="openKakao(event)"
style="border-color: white; color: white;">
💬 카카오채널 문의
</a>
</div>
@@ -89,8 +90,9 @@ else
</p>
<div class="d-flex gap-3 flex-wrap">
<a href="/taxbaik/contact" class="btn btn-primary btn-lg">무료 상담 신청</a>
<a href="javascript:void(0);" class="btn btn-outline-primary btn-lg"
onclick="openKakao()" style="border-color: white; color: white;">
<a href="https://pf.kakao.com/_xoxchTX" target="_blank" rel="noopener noreferrer"
class="btn btn-outline-primary btn-lg" onclick="openKakao(event)"
style="border-color: white; color: white;">
💬 카카오채널 문의
</a>
</div>
+1 -1
View File
@@ -18,7 +18,7 @@
<div class="col-md-4">
<h6 class="fw-bold">채널</h6>
<p class="small">
<a href="http://pf.kakao.com/_xoxchTX" target="_blank" class="btn btn-sm btn-warning me-2">카카오톡</a>
<a href="https://pf.kakao.com/_xoxchTX" target="_blank" rel="noopener noreferrer" class="btn btn-sm btn-warning me-2">카카오톡</a>
<a href="https://www.instagram.com/taxtory5668/" target="_blank" class="btn btn-sm btn-outline-secondary">Instagram</a>
</p>
</div>
+4 -4
View File
@@ -56,7 +56,7 @@
},
"sameAs": [
"https://www.instagram.com/taxtory5668/",
"http://pf.kakao.com/_xoxchTX"
"https://pf.kakao.com/_xoxchTX"
]
}
</script>
@@ -71,7 +71,7 @@
gtag('config', 'G-25KRKY45D7');
</script>
</head>
<body class="with-mobile-cta">
<body class="with-mobile-cta" data-kakao-url="https://pf.kakao.com/_xoxchTX">
<partial name="_Header" />
<main role="main" class="pb-5">
@RenderBody()
@@ -106,7 +106,7 @@
<div class="col-md-3">
<h6 class="fw-bold mb-3">채널</h6>
<p class="small">
<a href="http://pf.kakao.com/_xoxchTX" target="_blank" class="btn btn-sm btn-warning me-2">카카오톡</a>
<a href="https://pf.kakao.com/_xoxchTX" target="_blank" rel="noopener noreferrer" class="btn btn-sm btn-warning me-2">카카오톡</a>
<a href="https://www.instagram.com/taxtory5668/" target="_blank" class="btn btn-sm btn-outline-secondary">Instagram</a>
</p>
</div>
@@ -133,7 +133,7 @@
<!-- Mobile Fixed CTA -->
<div class="mobile-cta-bar d-lg-none">
<a href="http://pf.kakao.com/_xoxchTX" target="_blank" class="btn-kakao-mobile">
<a href="https://pf.kakao.com/_xoxchTX" target="_blank" rel="noopener noreferrer" class="btn-kakao-mobile">
💬 카카오 상담하기
</a>
</div>
+9 -4
View File
@@ -288,7 +288,8 @@ builder.Services.AddMudServices(config =>
config.PopoverOptions.ThrowOnDuplicateProvider = false;
});
builder.Services.AddMemoryCache();
builder.Services.AddResponseCompression(opts => {
builder.Services.AddResponseCompression(opts =>
{
opts.Providers.Add<GzipCompressionProvider>();
});
builder.Services.AddHostedService<TelegramReportBackgroundService>();
@@ -394,9 +395,13 @@ app.MapHealthChecks("/healthz");
app.MapRazorPages(); // Sitemap.cshtml, Rss.cshtml, Feed.cshtml
app.MapStaticAssets();
// SPA 라우팅 폴백 (MapFallbackToFile만 사용 - 순수 정적 WASM)
// MapFallbackToFile로 index.html을 serve하면 WASM이 클라이언트에서 직접 부팅됨
// index.html의 <script src="_framework/blazor.webassembly.js">로 자동 초기화
// Blazor WebAssembly - prerender: false 페이지 지원
// 대시보드 등은 prerender: false이므로 MapRazorComponents 필수
app.MapRazorComponents<TaxBaik.WasmClient.Components.Admin.App>()
.AddInteractiveWebAssemblyRenderMode()
.AllowAnonymous();
// SPA 라우팅 폴백
app.MapFallbackToFile("admin/{*path:nonfile}", "admin/index.html");
app.MapFallbackToFile("portal/{*path:nonfile}", "portal/index.html");
+5 -6
View File
@@ -1,10 +1,9 @@
function openKakao() {
const kakaoUrl = document.querySelector('[data-kakao-url]')?.dataset.kakaoUrl || '#';
if (kakaoUrl !== '#') {
window.open(kakaoUrl, '_blank');
} else {
alert('카카오톡 채널 URL이 설정되지 않았습니다.');
function openKakao(event) {
const kakaoUrl = document.body?.dataset.kakaoUrl || window.taxbaikKakaoUrl || 'https://pf.kakao.com/_xoxchTX';
if (event) {
event.preventDefault();
}
window.open(kakaoUrl, '_blank', 'noopener,noreferrer');
}
document.addEventListener('DOMContentLoaded', function() {