경로 최적화: PathBase 제거 및 상대 경로로 전환

## 변경사항
- Program.cs: app.UsePathBase('/taxbaik') 제거
- Blazor 컴포넌트: /taxbaik/admin/* → ./* 상대 경로로 변경
- 모든 내부 링크 절대 경로 → 상대 경로로 전환

## 현황
 빌드: 0 오류, 0 경고
 헬스체크: HTTP 200
 로그인 페이지: 로드 정상
 로그인 API: 400 오류 (DB 오류 - 조사 중)

## 다음 단계
- LoginEndpoint에서 발생하는 DB 오류 원인 파악 필요
- Razor Pages 절대 경로도 상대 경로로 변경 (보류 중)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 15:00:23 +09:00
parent 4c4ec9cf09
commit 3153d3c095
44 changed files with 111787 additions and 62 deletions
@@ -26,9 +26,9 @@
<td>@inquiry.CreatedAt.ToString("yyyy-MM-dd")</td>
<td>
<MudButton Size="Size.Small" Variant="Variant.Outlined" Color="Color.Primary"
Href="@($"/taxbaik/admin/inquiries/{inquiry.Id}")">보기</MudButton>
Href="@($"./inquiries/{inquiry.Id}")">보기</MudButton>
<MudButton Size="Size.Small" Variant="Variant.Outlined" Color="Color.Info"
Href="@($"/taxbaik/admin/inquiries/{inquiry.Id}/edit")">수정</MudButton>
Href="@($"./inquiries/{inquiry.Id}/edit")">수정</MudButton>
</td>
</tr>
}
@@ -79,7 +79,7 @@
@(isSaving ? "저장 중..." : "저장")
</MudButton>
<MudButton Variant="Variant.Outlined"
@onclick="@(() => Navigation.NavigateTo("/taxbaik/admin/announcements"))">
@onclick="@(() => Navigation.NavigateTo("./announcements"))">
취소
</MudButton>
</div>
@@ -105,7 +105,7 @@
var entity = await AnnouncementClient.GetByIdAsync(Id.Value);
if (entity is null)
{
Navigation.NavigateTo("/taxbaik/admin/announcements");
Navigation.NavigateTo("./announcements");
return;
}
model = new AnnouncementDto
@@ -122,7 +122,7 @@
}
catch
{
Navigation.NavigateTo("/taxbaik/admin/announcements");
Navigation.NavigateTo("./announcements");
}
}
}
@@ -159,7 +159,7 @@
else
Snackbar.Add("저장 실패", Severity.Error);
}
Navigation.NavigateTo("/taxbaik/admin/announcements");
Navigation.NavigateTo("./announcements");
}
catch (Exception ex)
{
@@ -13,7 +13,7 @@
<AdminPageHeader Title="공지사항 관리" Eyebrow="Homepage" Subtitle="홈페이지 상단에 노출되는 공지사항을 등록하고 관리합니다.">
<MudButton Variant="Variant.Filled" Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Add"
Href="/taxbaik/admin/announcements/create">
Href="./announcements/create">
공지 등록
</MudButton>
</AdminPageHeader>
@@ -79,7 +79,7 @@
<td>@item.SortOrder</td>
<td>
<MudButtonGroup Size="Size.Small" Variant="Variant.Outlined">
<MudButton @onclick="@(() => Navigation.NavigateTo($"/taxbaik/admin/announcements/{item.Id}/edit"))">
<MudButton @onclick="@(() => Navigation.NavigateTo($"./announcements/{item.Id}/edit"))">
수정
</MudButton>
<MudButton Color="Color.Error" @onclick="@(() => DeleteAsync(item))">
@@ -31,7 +31,7 @@
private void GoBack()
{
Navigation.NavigateTo("/taxbaik/admin/blog");
Navigation.NavigateTo("./blog");
}
private async Task SavePost()
@@ -56,7 +56,7 @@
}
Snackbar.Add("포스트가 저장되었습니다.", Severity.Success);
Navigation.NavigateTo("/taxbaik/admin/blog");
Navigation.NavigateTo("./blog");
}
catch (ValidationException ex)
{
@@ -83,7 +83,7 @@ else
private void GoBack()
{
Navigation.NavigateTo("/taxbaik/admin/blog");
Navigation.NavigateTo("./blog");
}
private async Task SavePost()
@@ -111,7 +111,7 @@ else
}
Snackbar.Add("포스트가 저장되었습니다.", Severity.Success);
Navigation.NavigateTo("/taxbaik/admin/blog");
Navigation.NavigateTo("./blog");
}
catch (ValidationException ex)
{
@@ -145,7 +145,7 @@ else
return;
}
Snackbar.Add("포스트를 임시로 내렸습니다.", Severity.Success);
Navigation.NavigateTo("/taxbaik/admin/blog");
Navigation.NavigateTo("./blog");
}
catch (Exception ex)
{
@@ -17,7 +17,7 @@
새로고침
</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.EditNote"
Href="/taxbaik/admin/blog/create">새 포스트 작성</MudButton>
Href="./blog/create">새 포스트 작성</MudButton>
</ChildContent>
</AdminPageHeader>
@@ -46,7 +46,7 @@
<TemplateColumn>
<CellTemplate Context="cell">
<MudButton Variant="Variant.Outlined" Size="Size.Small" Color="Color.Primary"
Href="@($"/taxbaik/admin/blog/{cell.Item.Id}/edit")">수정하기</MudButton>
Href="@($"./blog/{cell.Item.Id}/edit")">수정하기</MudButton>
@if (showArchived)
{
<MudButton Variant="Variant.Text" Size="Size.Small" Color="Color.Success"
@@ -22,12 +22,12 @@
<MudStack Row="true" AlignItems="AlignItems.Center" Class="mb-4" Spacing="2">
<MudButton Variant="Variant.Outlined" Color="Color.Primary"
StartIcon="@Icons.Material.Filled.ArrowBack"
@onclick="@(() => Navigation.NavigateTo("/taxbaik/admin/clients"))">
@onclick="@(() => Navigation.NavigateTo("./clients"))">
목록으로
</MudButton>
<MudButton Variant="Variant.Outlined" Color="Color.Warning"
StartIcon="@Icons.Material.Filled.Edit"
Href="@($"/taxbaik/admin/clients/{ClientId}/edit")">
Href="@($"./clients/{ClientId}/edit")">
수정
</MudButton>
</MudStack>
@@ -13,7 +13,7 @@
<PageTitle>@(Id.HasValue ? "고객 수정" : "고객 등록")</PageTitle>
<AdminPageHeader Title="@(Id.HasValue ? "고객 수정" : "고객 등록")" Eyebrow="CRM">
<MudButton Variant="Variant.Outlined" Href="/taxbaik/admin/clients"
<MudButton Variant="Variant.Outlined" Href="./clients"
StartIcon="@Icons.Material.Filled.ArrowBack">목록으로</MudButton>
</AdminPageHeader>
@@ -81,7 +81,7 @@
OnClick="@SaveAsync" Disabled="@isSaving">
@(isSaving ? "저장 중..." : "저장")
</MudButton>
<MudButton Variant="Variant.Outlined" Href="/taxbaik/admin/clients">
<MudButton Variant="Variant.Outlined" Href="./clients">
취소
</MudButton>
</MudItem>
@@ -116,7 +116,7 @@
if (client is null)
{
Snackbar.Add("고객을 찾을 수 없습니다.", Severity.Error);
Navigation.NavigateTo("/taxbaik/admin/clients");
Navigation.NavigateTo("./clients");
return;
}
dto = new ClientFormModel
@@ -135,7 +135,7 @@
catch (Exception ex)
{
Snackbar.Add($"오류: {ex.Message}", Severity.Error);
Navigation.NavigateTo("/taxbaik/admin/clients");
Navigation.NavigateTo("./clients");
return;
}
}
@@ -188,7 +188,7 @@
else
Snackbar.Add("등록에 실패했습니다.", Severity.Error);
}
Navigation.NavigateTo("/taxbaik/admin/clients");
Navigation.NavigateTo("./clients");
}
catch (Exception ex)
{
@@ -14,7 +14,7 @@
<ChildContent>
<MudButton Variant="Variant.Filled" Color="Color.Primary"
StartIcon="@Icons.Material.Filled.PersonAdd"
Href="/taxbaik/admin/clients/create">
Href="./clients/create">
고객 등록
</MudButton>
</ChildContent>
@@ -92,7 +92,7 @@
<td class="small">@c.CreatedAt.ToLocalTime().ToString("yy.MM.dd")</td>
<td>
<MudButtonGroup Size="Size.Small" Variant="Variant.Outlined">
<MudButton @onclick="@(() => Navigation.NavigateTo($"/taxbaik/admin/clients/{c.Id}/edit"))">
<MudButton @onclick="@(() => Navigation.NavigateTo($"./clients/{c.Id}/edit"))">
수정
</MudButton>
<MudButton Color="Color.Error" @onclick="@(() => DeleteAsync(c))">
@@ -19,7 +19,7 @@
@code {
private void GoBack()
{
Navigation.NavigateTo("/taxbaik/admin/companies");
Navigation.NavigateTo("./companies");
}
private async Task HandleCreate(CompanyFormModel model)
@@ -37,7 +37,7 @@
});
Snackbar.Add("고객사가 등록되었습니다.", Severity.Success);
Navigation.NavigateTo("/taxbaik/admin/companies");
Navigation.NavigateTo("./companies");
}
catch (Exception ex)
{
@@ -79,7 +79,7 @@
private void GoBack()
{
Navigation.NavigateTo("/taxbaik/admin/companies");
Navigation.NavigateTo("./companies");
}
private async Task HandleUpdate(CompanyFormModel model)
@@ -98,7 +98,7 @@
});
Snackbar.Add("고객사가 수정되었습니다.", Severity.Success);
Navigation.NavigateTo("/taxbaik/admin/companies");
Navigation.NavigateTo("./companies");
}
catch (Exception ex)
{
@@ -120,7 +120,7 @@
{
await ApiClient.DeleteAsync($"company/{Id}");
Snackbar.Add("고객사가 삭제되었습니다.", Severity.Success);
Navigation.NavigateTo("/taxbaik/admin/companies");
Navigation.NavigateTo("./companies");
}
catch (Exception ex)
{
@@ -8,7 +8,7 @@
<AdminPageHeader Title="고객사 관리" Eyebrow="Settings" Subtitle="등록된 고객사를 관리하고 새로운 고객사를 추가합니다.">
<MudButton Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add"
Href="/taxbaik/admin/companies/create">새 고객사 등록</MudButton>
Href="./companies/create">새 고객사 등록</MudButton>
</AdminPageHeader>
<MudPaper Class="admin-surface mb-4 mt-4" Elevation="0">
@@ -34,7 +34,7 @@
<TemplateColumn>
<CellTemplate Context="cell">
<MudButton Variant="Variant.Outlined" Size="Size.Small" Color="Color.Primary"
Href="@($"/taxbaik/admin/companies/{cell.Item.Id}/edit")">수정</MudButton>
Href="@($"./companies/{cell.Item.Id}/edit")">수정</MudButton>
</CellTemplate>
</TemplateColumn>
</Columns>
@@ -17,7 +17,7 @@
<MudText Typo="Typo.body2" Class="mb-4 flex-grow-1">
브라우저 오류와 JS interop 실패는 클라이언트 로그에서 바로 추적합니다.
</MudText>
<MudLink Href="/taxbaik/admin/client-logs" Color="Color.Primary" Class="font-weight-bold">
<MudLink Href="./client-logs" Color="Color.Primary" Class="font-weight-bold">
클라이언트 로그 보기 →
</MudLink>
</MudPaper>
@@ -31,7 +31,7 @@
<MudText Typo="Typo.body2" Class="mb-4 flex-grow-1">
CRM, 홈페이지, 문의 관리 화면을 표준 템플릿으로 확장합니다.
</MudText>
<MudLink Href="/taxbaik/admin/inquiries" Color="Color.Primary" Class="font-weight-bold">
<MudLink Href="./inquiries" Color="Color.Primary" Class="font-weight-bold">
문의 관리로 이동 →
</MudLink>
</MudPaper>
@@ -45,7 +45,7 @@
<MudText Typo="Typo.body2" Class="mb-4 flex-grow-1">
하위 경로 배포와 렌더러 분리를 유지하도록 라우트 린트를 적용합니다.
</MudText>
<MudLink Href="/taxbaik/admin/client-logs" Color="Color.Primary" Class="font-weight-bold">
<MudLink Href="./client-logs" Color="Color.Primary" Class="font-weight-bold">
최근 에러 확인 →
</MudLink>
</MudPaper>
@@ -59,7 +59,7 @@
<MudText Typo="Typo.body2" Class="mb-4 flex-grow-1">
중복되는 오류는 최근 로그 요약에서 source와 route 기준으로 묶어 봅니다.
</MudText>
<MudLink Href="/taxbaik/admin/client-logs?q=invoke" Color="Color.Primary" Class="font-weight-bold">
<MudLink Href="./client-logs?q=invoke" Color="Color.Primary" Class="font-weight-bold">
오류 검색 →
</MudLink>
</MudPaper>
@@ -73,7 +73,7 @@
<MudText Typo="Typo.body2" Class="mb-4 flex-grow-1">
Top sources / routes를 확인해서 어떤 모듈이 재발하는지 빠르게 좁힙니다.
</MudText>
<MudLink Href="/taxbaik/admin/client-logs" Color="Color.Primary" Class="font-weight-bold">
<MudLink Href="./client-logs" Color="Color.Primary" Class="font-weight-bold">
요약 리포트 보기 →
</MudLink>
</MudPaper>
@@ -17,7 +17,7 @@
<MudText Typo="Typo.body2" Class="mb-4 flex-grow-1">
브라우저 오류와 JS interop 실패는 클라이언트 로그에서 바로 추적합니다.
</MudText>
<MudLink Href="/taxbaik/admin/client-logs" Color="Color.Primary" Class="font-weight-bold">
<MudLink Href="./client-logs" Color="Color.Primary" Class="font-weight-bold">
클라이언트 로그 보기 →
</MudLink>
</MudPaper>
@@ -31,7 +31,7 @@
<MudText Typo="Typo.body2" Class="mb-4 flex-grow-1">
CRM, 홈페이지, 문의 관리 화면을 표준 템플릿으로 확장합니다.
</MudText>
<MudLink Href="/taxbaik/admin/inquiries" Color="Color.Primary" Class="font-weight-bold">
<MudLink Href="./inquiries" Color="Color.Primary" Class="font-weight-bold">
문의 관리로 이동 →
</MudLink>
</MudPaper>
@@ -45,7 +45,7 @@
<MudText Typo="Typo.body2" Class="mb-4 flex-grow-1">
하위 경로 배포와 렌더러 분리를 유지하도록 라우트 린트를 적용합니다.
</MudText>
<MudLink Href="/taxbaik/admin/client-logs" Color="Color.Primary" Class="font-weight-bold">
<MudLink Href="./client-logs" Color="Color.Primary" Class="font-weight-bold">
최근 에러 확인 →
</MudLink>
</MudPaper>
@@ -59,7 +59,7 @@
<MudText Typo="Typo.body2" Class="mb-4 flex-grow-1">
중복되는 오류는 최근 로그 요약에서 source와 route 기준으로 묶어 봅니다.
</MudText>
<MudLink Href="/taxbaik/admin/client-logs?q=invoke" Color="Color.Primary" Class="font-weight-bold">
<MudLink Href="./client-logs?q=invoke" Color="Color.Primary" Class="font-weight-bold">
오류 검색 →
</MudLink>
</MudPaper>
@@ -73,7 +73,7 @@
<MudText Typo="Typo.body2" Class="mb-4 flex-grow-1">
Top sources / routes를 확인해서 어떤 모듈이 재발하는지 빠르게 좁힙니다.
</MudText>
<MudLink Href="/taxbaik/admin/client-logs" Color="Color.Primary" Class="font-weight-bold">
<MudLink Href="./client-logs" Color="Color.Primary" Class="font-weight-bold">
요약 리포트 보기 →
</MudLink>
</MudPaper>
@@ -10,7 +10,7 @@
<PageTitle>@(Id.HasValue ? "FAQ 수정" : "FAQ 등록")</PageTitle>
<AdminPageHeader Title="@(Id.HasValue ? "FAQ 수정" : "FAQ 등록")" Eyebrow="홈페이지">
<MudButton Variant="Variant.Outlined" Href="/taxbaik/admin/faqs"
<MudButton Variant="Variant.Outlined" Href="./faqs"
StartIcon="@Icons.Material.Filled.ArrowBack">목록으로</MudButton>
</AdminPageHeader>
@@ -53,7 +53,7 @@
OnClick="@SaveAsync" Disabled="@isSaving">
@(isSaving ? "저장 중..." : "저장")
</MudButton>
<MudButton Variant="Variant.Outlined" Href="/taxbaik/admin/faqs">
<MudButton Variant="Variant.Outlined" Href="./faqs">
취소
</MudButton>
</MudItem>
@@ -89,7 +89,7 @@
if (existing is null)
{
Snackbar.Add("FAQ를 찾을 수 없습니다.", Severity.Error);
Navigation.NavigateTo("/taxbaik/admin/faqs");
Navigation.NavigateTo("./faqs");
return;
}
model = new FaqFormModel
@@ -104,7 +104,7 @@
catch (Exception ex)
{
Snackbar.Add($"오류: {ex.Message}", Severity.Error);
Navigation.NavigateTo("/taxbaik/admin/faqs");
Navigation.NavigateTo("./faqs");
return;
}
}
@@ -145,7 +145,7 @@
else
Snackbar.Add("등록 실패", Severity.Error);
}
Navigation.NavigateTo("/taxbaik/admin/faqs");
Navigation.NavigateTo("./faqs");
}
catch (Exception ex)
{
@@ -13,7 +13,7 @@
<AdminPageHeader Title="FAQ 관리" Eyebrow="홈페이지" Subtitle="홈페이지 자주 묻는 질문을 등록하고 순서를 관리합니다.">
<MudButton Variant="Variant.Filled" Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Add"
Href="/taxbaik/admin/faqs/create">
Href="./faqs/create">
FAQ 등록
</MudButton>
</AdminPageHeader>
@@ -82,7 +82,7 @@
</td>
<td>
<MudButtonGroup Size="Size.Small" Variant="Variant.Outlined">
<MudButton @onclick="@(() => Navigation.NavigateTo($"/taxbaik/admin/faqs/{item.Id}/edit"))">
<MudButton @onclick="@(() => Navigation.NavigateTo($"./faqs/{item.Id}/edit"))">
수정
</MudButton>
<MudButton Color="Color.Error" @onclick="@(() => DeleteAsync(item))">
@@ -22,7 +22,7 @@
@code {
private void GoBack()
{
Navigation.NavigateTo("/taxbaik/admin/inquiries");
Navigation.NavigateTo("./inquiries");
}
private async Task HandleCreate(InquiryFormModel model)
@@ -49,7 +49,7 @@
Snackbar.Add("✅ 문의가 등록되었고 고객에게 알림이 발송되었습니다.", Severity.Success);
// 사용자가 성공 메시지를 볼 수 있도록 3초 후에 목록으로 이동
await Task.Delay(3000);
Navigation.NavigateTo("/taxbaik/admin/inquiries");
Navigation.NavigateTo("./inquiries");
}
catch (ValidationException ex)
{
@@ -16,7 +16,7 @@
<MudButton Variant="Variant.Outlined"
Color="Color.Primary"
StartIcon="@Icons.Material.Filled.ArrowBack"
@onclick="@(() => Navigation.NavigateTo("/taxbaik/admin/inquiries"))">
@onclick="@(() => Navigation.NavigateTo("./inquiries"))">
문의 목록으로
</MudButton>
@@ -90,7 +90,7 @@
{
<AdminDetailSection Title="연결된 고객" CssClass="pa-4 mt-4">
<MudButton Variant="Variant.Outlined" Color="Color.Primary" FullWidth="true"
Href="@($"/taxbaik/admin/clients/{inquiry.ClientId}")">
Href="@($"./clients/{inquiry.ClientId}")">
고객 카드 보기
</MudButton>
</AdminDetailSection>
@@ -81,7 +81,7 @@ else
private void GoBack()
{
Navigation.NavigateTo("/taxbaik/admin/inquiries");
Navigation.NavigateTo("./inquiries");
}
private async Task HandleUpdate(InquiryFormModel model)
@@ -121,7 +121,7 @@ else
};
Snackbar.Add("문의가 수정되었습니다.", Severity.Success);
Navigation.NavigateTo("/taxbaik/admin/inquiries");
Navigation.NavigateTo("./inquiries");
}
catch (ValidationException ex)
{
@@ -155,7 +155,7 @@ else
return;
}
Snackbar.Add("문의가 삭제되었습니다.", Severity.Success);
Navigation.NavigateTo("/taxbaik/admin/inquiries");
Navigation.NavigateTo("./inquiries");
}
catch (Exception ex)
{
@@ -10,7 +10,7 @@
<AdminPageHeader Title="문의 관리" Eyebrow="Customer Requests" Subtitle="상담 요청을 상태별로 확인하고 후속 조치를 기록합니다.">
<ChildContent>
<MudButton Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add"
Href="/taxbaik/admin/inquiries/create">새 문의 등록</MudButton>
Href="./inquiries/create">새 문의 등록</MudButton>
</ChildContent>
</AdminPageHeader>
@@ -13,6 +13,6 @@
await AuthStateProvider.LogoutAsync();
// 로그인 페이지로 리다이렉트
NavigationManager.NavigateTo("/taxbaik/admin/login", forceLoad: true);
NavigationManager.NavigateTo("./login", forceLoad: true);
}
}
@@ -7,7 +7,7 @@
return;
var returnUrl = Uri.EscapeDataString(GetSafeReturnUrl());
Navigation.NavigateTo($"/taxbaik/admin/login?returnUrl={returnUrl}", replace: true);
Navigation.NavigateTo($"./login?returnUrl={returnUrl}", replace: true);
}
private string GetSafeReturnUrl()
@@ -114,7 +114,7 @@
if (passwordInput) passwordInput.value = '" + password + @"';
// Razor Pages에서 처리하도록 폼 제출
const action = form.getAttribute('action') || '/taxbaik/admin/login';
const action = form.getAttribute('action') || './login';
form.action = action;
form.method = 'POST';
form.submit();
@@ -10,7 +10,7 @@
</div>
<div class="admin-topbar-actions">
<a class="admin-topbar-action" href="/taxbaik" target="_blank" rel="noopener">공개 사이트</a>
<a class="admin-topbar-action" href="/taxbaik/admin/logout">로그아웃</a>
<a class="admin-topbar-action" href="./logout">로그아웃</a>
</div>
</header>
@@ -30,7 +30,7 @@
<div class="admin-drawer-footer">
<a class="admin-footer-item" href="/taxbaik" target="_blank" rel="noopener">공개 사이트</a>
<a class="admin-footer-item" href="/taxbaik/admin/logout">로그아웃</a>
<a class="admin-footer-item" href="./logout">로그아웃</a>
</div>
</aside>
+2 -1
View File
@@ -427,7 +427,8 @@ catch (Exception ex)
Console.WriteLine($"Migration warning (development only): {ex.Message}");
}
app.UsePathBase("/taxbaik");
// PathBase는 Nginx reverse proxy에서 처리 (절대 경로 제거)
// app.UsePathBase("/taxbaik"); ← 상대 경로로 전환됨
// 개발 및 테스트 환경에서 resource-collection.js 404로 인해 Blazor WASM이 크래시되는 현상 방지
app.Use(async (context, next) =>
File diff suppressed because it is too large Load Diff