refactor: move buildable .NET source into src/, update CI/doc paths
TaxBaik CI/CD / build-and-deploy (push) Successful in 2m7s

Groups the repo root into src (buildable source), docs (already existed),
and everything else (db/, scripts/, tests/, deploy/ - deployment/ops/test
assets that aren't compiled, already organized as their own folders). CI
now only needs src/ to build: dotnet restore/build/test/publish all point
at src/TaxBaik.sln, src/TaxBaik.Web/, src/TaxBaik.Proxy/.

- git mv every project (Domain, Infrastructure, Application,
  Application.Tests, Web, Web.Client, Proxy) and TaxBaik.sln into src/ as a
  unit, so relative ProjectReference/.sln paths stay valid unchanged.
- .gitea/workflows/deploy.yml: 6 dotnet restore/clean/build/test/publish
  invocations now point at src/. db/migrations and scripts/ stay at root
  (deploy_gb.sh and browser-e2e.yml only touch published output and the
  deployed URL, not source paths - verified, no changes needed there).
- scripts/validate_admin_render.sh: admin render-mode file paths now
  src/TaxBaik.Web.Client/...
- scripts/validate_kst_timestamps.sh: dropped deploy.sh from its target
  list - that script was removed in the prior cleanup commit (dead, no
  CI workflow referenced it) but this validator still expected it to exist.
- CLAUDE.md, docs/ENGINEERING_HARNESS.md, docs/ADMIN_PATTERN_CRITIQUE_WBS.md:
  updated project-structure diagram, dotnet run/build commands, and grep
  targets to the new src/ paths (also fixed a pre-existing stale path in
  ADMIN_PATTERN_CRITIQUE_WBS.md that still said TaxBaik.Web/Components/Admin
  from before that ever moved to TaxBaik.Web.Client).
- Added a Repo Root harness rule + Architecture Guardrail entries: new files
  belong under src/docs/tests/scripts/db/deploy, not loose at root; temp
  work stays outside the repo (or under a gitignored .scratch/) and is
  never committed.

Verified locally: dotnet build/test src/TaxBaik.sln (26/26 tests), and all
three scripts/validate_*.sh pass against the new layout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 10:37:37 +09:00
parent c00d002972
commit ea447495d3
277 changed files with 36 additions and 29 deletions
+6 -6
View File
@@ -20,21 +20,21 @@ jobs:
dotnet-version: '10.0' dotnet-version: '10.0'
- name: Restore dependencies - name: Restore dependencies
run: dotnet restore TaxBaik.sln run: dotnet restore src/TaxBaik.sln
- name: Build solution - name: Build solution
run: | run: |
dotnet clean TaxBaik.sln -c Release dotnet clean src/TaxBaik.sln -c Release
dotnet build TaxBaik.sln -c Release --no-restore dotnet build src/TaxBaik.sln -c Release --no-restore
- name: Test solution - name: Test solution
run: dotnet test TaxBaik.sln -c Release --no-build run: dotnet test src/TaxBaik.sln -c Release --no-build
- name: Publish Web (auto-includes WASM from referenced TaxBaik.Web.Client) - name: Publish Web (auto-includes WASM from referenced TaxBaik.Web.Client)
run: dotnet publish TaxBaik.Web/ -c Release -o ./publish --no-restore run: dotnet publish src/TaxBaik.Web/ -c Release -o ./publish --no-restore
- name: Publish Proxy - name: Publish Proxy
run: dotnet publish TaxBaik.Proxy/ -c Release -o ./publish/proxy run: dotnet publish src/TaxBaik.Proxy/ -c Release -o ./publish/proxy
- name: Write production secrets - name: Write production secrets
run: | run: |
+3
View File
@@ -60,3 +60,6 @@ PublishProfiles/
.env .env
.env.local .env.local
appsettings.Development.json appsettings.Development.json
# Scratch / temporary work - never commit, see docs/ENGINEERING_HARNESS.md
.scratch/
+10 -9
View File
@@ -350,17 +350,18 @@ Repositories (데이터 계층)
**단일 앱 구조** (공개 사이트 + 관리자까지 하나의 ASP.NET Core 앱): **단일 앱 구조** (공개 사이트 + 관리자까지 하나의 ASP.NET Core 앱):
``` ```
TaxBaik.Domain 클래스 라이브러리 (엔티티, 인터페이스, enum) src/ 빌드 가능한 .NET 소스 전체 (CI는 이 폴더만 빌드 대상으로 참조)
TaxBaik.Infrastructure 클래스 라이브러리 (Dapper repository, DB 마이그레이션) TaxBaik.Domain 클래스 라이브러리 (엔티티, 인터페이스, enum)
TaxBaik.Application 클래스 라이브러리 (서비스, DTO, 비즈니스 로직) TaxBaik.Infrastructure 클래스 라이브러리 (Dapper repository, DB 마이그레이션)
TaxBaik.Web ASP.NET Core 앱 (포트 5001 - 서버는 순수 API) TaxBaik.Application 클래스 라이브러리 (서비스, DTO, 비즈니스 로직)
TaxBaik.Web ASP.NET Core 앱 (포트 5001 - 서버는 순수 API)
├─ Pages/ Razor Pages (공개 홈페이지, 블로그, 문의폼) ├─ Pages/ Razor Pages (공개 홈페이지, 블로그, 문의폼)
├─ Components/ ├─ Components/
│ ├─ (Web pages) │ ├─ (Web pages)
│ └─ App.razor Blazor Root (WebAssembly 렌더링) │ └─ App.razor Blazor Root (WebAssembly 렌더링)
└─ Services/ 인증, 블로그, 문의 등 (API만 제공) └─ Services/ 인증, 블로그, 문의 등 (API만 제공)
TaxBaik.Web.Client (NEW) Blazor WebAssembly WASM 클라이언트 TaxBaik.Web.Client (NEW) Blazor WebAssembly WASM 클라이언트
├─ _Imports.razor 네임스페이스 임포트 ├─ _Imports.razor 네임스페이스 임포트
└─ Components/ └─ Components/
└─ Admin/ 관리자 페이지 (클라이언트 사이드) └─ Admin/ 관리자 페이지 (클라이언트 사이드)
@@ -460,7 +461,7 @@ ssh taxbaik-tunnel # 터널 유지
psql -h localhost -U taxbaik -d taxbaikdb -c "\dt" psql -h localhost -U taxbaik -d taxbaikdb -c "\dt"
# 또는 .NET 앱 실행 (자동으로 마이그레이션 실행) # 또는 .NET 앱 실행 (자동으로 마이그레이션 실행)
dotnet run -p TaxBaik.Web dotnet run -p src/TaxBaik.Web
``` ```
#### 단계 3: 개발 워크플로우 (단일 앱 통합) #### 단계 3: 개발 워크플로우 (단일 앱 통합)
@@ -470,7 +471,7 @@ dotnet run -p TaxBaik.Web
ssh -L 5432:127.0.0.1:5432 kjh2064@178.104.200.7 ssh -L 5432:127.0.0.1:5432 kjh2064@178.104.200.7
# 터미널 2: 통합 Web 앱 (Razor Pages + Blazor Server Admin) # 터미널 2: 통합 Web 앱 (Razor Pages + Blazor Server Admin)
cd TaxBaik.Web cd src/TaxBaik.Web
dotnet run dotnet run
# 접속: # 접속:
# - 홈페이지: http://localhost:5001/taxbaik # - 홈페이지: http://localhost:5001/taxbaik
@@ -1762,7 +1763,7 @@ public interface INtsApiClient
### 빌드 ### 빌드
```bash ```bash
dotnet build TaxBaik.sln dotnet build src/TaxBaik.sln
``` ```
### 서버 상태 확인 (SSH) ### 서버 상태 확인 (SSH)
@@ -2166,7 +2167,7 @@ else
| 11/15 ~ 11/30 | 종합부동산세 납부 | `comprehensive-real-estate-tax` | real-estate-tax | | 11/15 ~ 11/30 | 종합부동산세 납부 | `comprehensive-real-estate-tax` | real-estate-tax |
| 12/1 ~ 12/31 | 연말 증여·절세 플래닝 | `year-end-gift` | family-asset | | 12/1 ~ 12/31 | 연말 증여·절세 플래닝 | `year-end-gift` | family-asset |
캘린더 정의 위치: `TaxBaik.Application/Seasonal/TaxSeasonCalendar.cs` 캘린더 정의 위치: `src/TaxBaik.Application/Seasonal/TaxSeasonCalendar.cs`
시즌 추가/수정은 이 파일만 변경하면 된다. DB·마이그레이션 변경 없음. 시즌 추가/수정은 이 파일만 변경하면 된다. DB·마이그레이션 변경 없음.
+1 -1
View File
@@ -33,7 +33,7 @@ Razor Page/Form
| 지표 | 기준값 | 측정 방법 | | 지표 | 기준값 | 측정 방법 |
| --- | --- | --- | | --- | --- | --- |
| Admin direct service injection | 0건 | `rg "@inject .*Service|@inject I.*Repository" TaxBaik.Web/Components/Admin` | | Admin direct service injection | 0건 | `rg "@inject .*Service|@inject I.*Repository" src/TaxBaik.Web.Client/Components/Admin` |
| Blog create/edit duplicate fields | 0개 중복 폼 | `BlogForm.razor` 단일 사용 여부 | | Blog create/edit duplicate fields | 0개 중복 폼 | `BlogForm.razor` 단일 사용 여부 |
| Admin JavaScript surface | 필수 module만 허용 | `window.*` 전역 admin JS 0건, JS interop 사유 문서화 | | Admin JavaScript surface | 필수 module만 허용 | `window.*` 전역 admin JS 0건, JS interop 사유 문서화 |
| Inquiry visible-but-unsaved fields | 0개 | E2E로 수정 후 API 재조회 | | Inquiry visible-but-unsaved fields | 0개 | E2E로 수정 후 API 재조회 |
+7 -3
View File
@@ -13,8 +13,9 @@
| Auth | JWT 인증, 관리자 API는 `[Authorize]` | 익명으로 관리자 데이터 접근 가능 | | Auth | JWT 인증, 관리자 API는 `[Authorize]` | 익명으로 관리자 데이터 접근 가능 |
| Deploy | Gitea Actions CI/CD만 배포 경로 | 수동 SSH/복사로 운영 반영 | | Deploy | Gitea Actions CI/CD만 배포 경로 | 수동 SSH/복사로 운영 반영 |
| Evidence | 빌드, 테스트, E2E, API smoke 로그 | "확인함", "될 것" 같은 진술 | | Evidence | 빌드, 테스트, E2E, API smoke 로그 | "확인함", "될 것" 같은 진술 |
| Admin Render | 어드민 기본 셸은 `InteractiveWebAssemblyRenderMode(prerender: true)`초기 마크업을 확보하고, 로그인은 예외적으로 서버 프리렌더 허용 | 어드민 셸이 순수 클라이언트 렌더만으로 첫 화면을 비우거나, 로그인 폼이 HTML에 없다 | | Admin Render | Router/Routes에는 전역 `@rendermode`를 두지 않고 페이지별로 지정한다. 로그인 페이지만 `prerender: true`최초 HTML에 폼을 포함시키고, 나머지 `[Authorize]` 페이지는 `prerender: false`를 유지한다 | Router/Routes에 전역 렌더모드가 다시 생기거나, 로그인 폼이 최초 HTML에 없다 |
| KST Timestamp | CI/배포/백업 폴더명과 추적 일시는 `TZ=Asia/Seoul` | `date`가 기본 UTC 또는 서버 로캘에 종속 | | KST Timestamp | CI/배포/백업 폴더명과 추적 일시는 `TZ=Asia/Seoul` | `date`가 기본 UTC 또는 서버 로캘에 종속 |
| Repo Root | 소스는 `src/`, 문서는 `docs/`, 테스트는 `tests/`, 스크립트는 `scripts/`, 마이그레이션은 `db/`, 배포 참조 설정은 `deploy/`에 둔다. 루트에는 진입점 설정(`CLAUDE.md`, `README.md`, `.gitignore`, `package.json` 등)만 남긴다 | 루트에 스크린샷/로그/1회성 디버그 스크립트/빌드 산출물이 커밋된다 |
## Architecture Guardrails ## Architecture Guardrails
@@ -36,6 +37,9 @@
- 브라우저에서 발생한 JS 오류는 운영 장애 탐지를 위한 샘플 데이터로만 취급하고, 전체 이벤트 스트림을 보존하려는 설계는 금지한다. - 브라우저에서 발생한 JS 오류는 운영 장애 탐지를 위한 샘플 데이터로만 취급하고, 전체 이벤트 스트림을 보존하려는 설계는 금지한다.
- 텔레그램 알림은 운영자의 주의 채널이지 이벤트 버스가 아니다. 같은 원인/같은 기간의 중복 알림은 억제하고, 리포트/오류/문의/시작 장애는 종류별 시간창을 분리한다. - 텔레그램 알림은 운영자의 주의 채널이지 이벤트 버스가 아니다. 같은 원인/같은 기간의 중복 알림은 억제하고, 리포트/오류/문의/시작 장애는 종류별 시간창을 분리한다.
- 오류 알림에는 재현성 6요소를 포함한다: 화면, 기능, 액션, 단계, 데이터 식별자, 현재 라우트. 이 정보가 없으면 운영 대응이 끝나지 않은 것으로 본다. - 오류 알림에는 재현성 6요소를 포함한다: 화면, 기능, 액션, 단계, 데이터 식별자, 현재 라우트. 이 정보가 없으면 운영 대응이 끝나지 않은 것으로 본다.
- 루트에 새 파일을 직접 추가하지 않는다. 소스는 `src/`, 문서는 `docs/`, 테스트는 `tests/`, 스크립트는 `scripts/`, 마이그레이션은 `db/`, 배포 참조 설정은 `deploy/`에 둔다.
- 임시/스크래치 작업(스크린샷, 1회성 디버그 스크립트, 로그)은 저장소 밖(OS/세션 임시 폴더)에서 하고 절대 커밋하지 않는다. 저장소 안에서 꼭 필요하면 `.gitignore`에 등록된 `.scratch/`만 사용한다.
- 커밋 전 `git status`로 루트에 낯선 파일이 생기지 않았는지 확인한다. 빌드 산출물(runtimeconfig.json, deps.json, wwwroot 산출물 등)이 루트나 프로젝트 폴더 밖에 커밋되면 안 된다.
- 재현 맥락은 페이지별 수동 JS 호출이 아니라 `AdminTelemetryContext` 같은 공통 컴포넌트가 담당한다. 새 어드민 화면은 레이아웃 경유 기본값을 자동 상속해야 하며, 예외만 명시적으로 덮어쓴다. - 재현 맥락은 페이지별 수동 JS 호출이 아니라 `AdminTelemetryContext` 같은 공통 컴포넌트가 담당한다. 새 어드민 화면은 레이아웃 경유 기본값을 자동 상속해야 하며, 예외만 명시적으로 덮어쓴다.
## Code Quality Harness ## Code Quality Harness
@@ -100,8 +104,8 @@
| Gate | Command/Check | Target | | Gate | Command/Check | Target |
| --- | --- | --- | | --- | --- | --- |
| Build | `dotnet build TaxBaik.sln -c Release --no-restore` | error 0 | | Build | `dotnet build src/TaxBaik.sln -c Release --no-restore` | error 0 |
| Unit | `dotnet test TaxBaik.sln -c Release --no-build` | failed 0 | | Unit | `dotnet test src/TaxBaik.sln -c Release --no-build` | failed 0 |
| Browser | `npx playwright test --project="Desktop Chrome"` | failed 0 | | Browser | `npx playwright test --project="Desktop Chrome"` | failed 0 |
| API Smoke | login + protected admin API curl | HTTP 2xx | | API Smoke | login + protected admin API curl | HTTP 2xx |
| Deploy | `.gitea/workflows/deploy.yml` | success | | Deploy | `.gitea/workflows/deploy.yml` | success |
+4 -4
View File
@@ -15,9 +15,9 @@ set -euo pipefail
# #
# See CLAUDE.md Phase 9 for architecture details. # See CLAUDE.md Phase 9 for architecture details.
app_file="TaxBaik.Web.Client/Components/Admin/App.razor" app_file="src/TaxBaik.Web.Client/Components/Admin/App.razor"
routes_file="TaxBaik.Web.Client/Components/Admin/Routes.razor" routes_file="src/TaxBaik.Web.Client/Components/Admin/Routes.razor"
login_file="TaxBaik.Web.Client/Components/Admin/Pages/Login.razor" login_file="src/TaxBaik.Web.Client/Components/Admin/Pages/Login.razor"
for file in "$app_file" "$routes_file" "$login_file"; do for file in "$app_file" "$routes_file" "$login_file"; do
if [ ! -f "$file" ]; then if [ ! -f "$file" ]; then
@@ -64,7 +64,7 @@ while IFS= read -r -d '' page; do
echo "⚠️ $page has no @rendermode directive (will not be interactive)." >&2 echo "⚠️ $page has no @rendermode directive (will not be interactive)." >&2
missing_rendermode=1 missing_rendermode=1
fi fi
done < <(find TaxBaik.Web.Client/Components/Admin/Pages -name "*.razor" -print0) done < <(find src/TaxBaik.Web.Client/Components/Admin/Pages -name "*.razor" -print0)
if [ "$missing_rendermode" -ne 0 ]; then if [ "$missing_rendermode" -ne 0 ]; then
echo "One or more admin pages are missing an explicit @rendermode directive." >&2 echo "One or more admin pages are missing an explicit @rendermode directive." >&2
-1
View File
@@ -3,7 +3,6 @@ set -euo pipefail
targets=( targets=(
".gitea/workflows/deploy.yml" ".gitea/workflows/deploy.yml"
"deploy.sh"
"deploy_gb.sh" "deploy_gb.sh"
) )

Some files were not shown because too many files have changed in this diff Show More