9.6 KiB
9.6 KiB
Stack Template And WBS
이 문서는 MudBlazor + ASP.NET Core 10 + Dapper + PostgreSQL 18.4 + API-first 기준의 기본 템플릿과 작업 순서를 정의한다. 기준은 공식 문서로 확인한 다음 반영한다.
Verified Assumptions
- MudBlazor는 static rendering을 지원하지 않는다. MudBlazor를 쓰는 화면은 interactive render mode가 필요하다.
- Blazor Web App은 static rendering과 interactive rendering을 구분한다.
- Interactive WebAssembly 컴포넌트는
.Client프로젝트에 두는 것이 공식 구조다. - ASP.NET Core 10은
Microsoft.AspNetCore.OpenApi기반 OpenAPI 문서 생성을 지원한다. - PostgreSQL 18.4는 2026-05-14 릴리스이며, 18.x 내 minor upgrade는 dump/restore가 필요하지 않다.
- Dapper는 SQL 중심의 micro ORM으로 repository layer에 맞는다.
- DTO 검증은
DataAnnotations를 기본으로 하고, 표현력이 부족한 경우에만 FluentValidation을 보완으로 둔다. - Blazor UI의 화면 상태는 MVVM 스타일 ViewModel로 분리한다.
Target Template
| 영역 | 권장 방식 | 비고 |
|---|---|---|
| Public Home | Static SSR + 필요한 부분만 Interactive WebAssembly | 초기 로딩과 SEO 우선 |
| Login | Static SSR 또는 Razor Page form | MudBlazor 의존 금지 |
| Home/Dashboard | Interactive WebAssembly + MudBlazor | 사용자 인터랙션 중심 |
| Admin CRUD | Interactive WebAssembly + API-first | BrowserClient 경유 |
| API | Minimal API 또는 Controller + OpenAPI | 계약 우선 |
| Persistence | Dapper + NpgsqlDataSource singleton |
connection pool 직접 관리 금지 |
| Auth | 브라우저는 HttpOnly Secure Cookie 우선, 외부 클라이언트만 JWT | localStorage 저장 금지 |
현재 저장소 기준 예외:
- 포털 로그인은 이미 Razor Page SSR로 구현돼 있다.
- 관리자 로그인은 아직 Interactive WebAssembly 경로를 사용한다.
- 따라서 본 템플릿의 로그인 SSR 기준은 포털/공개 사용자 흐름에 우선 적용하고, 관리자 로그인은 별도 마이그레이션 WBS로 분리한다.
Authentication Rules
- 브라우저 사용자 흐름은 SSR 로그인 form으로 시작한다.
- 서버는 자격 증명을 검증한 뒤 HttpOnly + Secure + SameSite cookie를 발급한다.
- 같은 origin에서 WebAssembly 화면은 쿠키 기반 API 호출을 우선 사용한다.
- JWT는 외부 API 클라이언트, 모바일, 파트너용으로만 분리한다.
- 토큰 원문은 로그에 남기지 않는다.
- DB 접속 문자열은 고정 검증 대상이다. 현재 개발/로컬 기준은
Host=localhost;Database=taxbaikdb;Username=taxbaik;Password=taxbaik123이며, 변경 시에는 문서와 검증 스크립트를 동시에 갱신해야 한다.
Render Mode Rules
/account/login은 Static SSR 또는 Razor Page로 구현한다./또는 홈 대시는 Interactive WebAssembly로 구현한다.- MudBlazor 컴포넌트는 interactive render mode가 없는 페이지에 두지 않는다.
- 로그인 화면에서
MudButton,MudTextField,MudDialog,MudSnackbar같은 interactive 의존은 금지한다.
Architecture Skeleton
src/
TaxBaik.Web/ # Host, SSR shell, auth, API, OpenAPI
TaxBaik.Web.Client/ # Interactive WebAssembly UI
TaxBaik.Contracts/ # DTO, request/response, validation contracts
TaxBaik.Application/ # Use cases, interfaces, policies
TaxBaik.Infrastructure/ # Dapper repositories, external integrations
TaxBaik.Migrations/ # SQL migration scripts
tests/
TaxBaik.UnitTests/
TaxBaik.ApiTests/
TaxBaik.Playwright/
scripts/
smoke/
deploy/
evidence/
Roadmap
| Phase | Goal | Exit Criteria |
|---|---|---|
| P0 Baseline | 공식 전제와 템플릿 기준 고정 | 본 문서와 ENGINEERING_HARNESS.md가 INDEX.md에 연결 |
| P1 Local Verify | 로컬 빌드/테스트/증빙 먼저 통과 | 로컬 dotnet build, unit, Playwright 1차 통과 |
| P2 CI Deploy | CI 배포와 중간 smoke 통과 | 배포 workflow success |
| P3 Domain Verify | 실제 도메인 최종 검증 | https://www.taxbaik.com/taxbaik 기준 브라우저 E2E 성공 |
| P1 Shell | SSR login / interactive home / API host 분리 | 로그인 SSR, 홈 WASM, API 계약 분리 확인 |
| P2 Auth | Cookie/JWT 이중 경로 정착 | 브라우저 cookie, 외부 JWT 경로 분리 완료 |
| P3 Data | Dapper + PostgreSQL 18.4 안정화 | repository, migration, index, connection 규칙 확정 |
| P4 Verify | Playwright와 데이터 증빙 자동화 | 화면 캡처, DOM 캡처, 실제 데이터 비교 통과 |
| P5 Operate | 배포/장애/FAQ 표준화 | CI/CD, smoke, rollback, incident FAQ 정착 |
Detailed WBS
WBS 항목은 다음 데이터가 모두 있어야 완료다.
- 변경 diff 링크 또는 파일명
- 로컬 빌드 결과
- 로컬 Playwright 결과
- Playwright 시나리오 이름
- 화면 캡처 파일 경로
- DOM 캡처 파일 경로
- 기대값과 실제값 비교 결과
- CI 배포 결과
- 실제 도메인 최종 검증 결과
- CI 또는 배포 로그 링크
| ID | 작업 | 산출물 | 완료 데이터 정의 |
|---|---|---|---|
| P0-01 | 공식 전제 검증 문서화 | Verified Assumptions | MudBlazor static rendering 비지원, Blazor render mode, OpenAPI, PostgreSQL 18.4, Dapper 근거 링크 |
| P0-02 | 엔지니어링 하네스 반영 | ENGINEERING_HARNESS.md |
완료 정의에 build + Playwright + screenshot + DOM + data proof 포함 |
| P0-03 | 인덱스 연결 | INDEX.md |
새 템플릿 문서가 canonical list에 포함 |
| P1-01 | 솔루션 구조 확정 | src/, tests/, scripts/ tree |
호스트/클라이언트/계약/애플리케이션/인프라 분리 확인 |
| P1-02 | 로그인 SSR 구현 가이드 | /account/login 기준 |
static SSR form, antiforgery, cookie issuance 흐름 문서화 |
| P1-03 | 홈 WASM 가이드 | / 또는 dashboard |
interactive WebAssembly + MudBlazor 사용 경계 문서화 |
| P1-04 | 관리자 로그인 마이그레이션 분리 | /admin/login 또는 equivalent |
현재 WASM 로그인과 목표 SSR 경계를 문서화하고 후속 WBS로 분리 |
| P1-05 | API-first 계약 정의 | /api/v1/* |
DTO, OpenAPI, ProblemDetails, auth policy 정의 |
| P1-06 | DTO/MVVM 규칙 확정 | 모든 Blazor form/list | DTO는 DataAnnotations, UI는 ViewModel, 보완 검증은 FluentValidation |
| P2-01 | Cookie auth 템플릿 | auth middleware | HttpOnly/Secure/SameSite settings, 401/403 behavior 확인 |
| P2-02 | JWT 분리 템플릿 | external auth endpoint | refresh rotation, revocation, expiry, no localStorage rule |
| P2-03 | CSRF/antiforgery 검증 | login POST flow | token present, POST accepted, stale tab failure case documented |
| P3-01 | Dapper repository pattern | singleton NpgsqlDataSource |
open-conn-per-method, transaction short-lived, query mapping test |
| P3-02 | PostgreSQL 18.4 migration policy | SQL scripts | versioned migrations, restore drill evidence |
| P3-03 | schema/index baseline | core tables | PK/FK/unique/check/index list and explain output |
| P4-01 | Playwright user journeys | login/home/admin scenario suite | each test has screenshot, DOM snapshot, assert on real data |
| P4-02 | evidence capture harness | scripts/evidence | screenshot + DOM + response capture persisted per run |
| P4-03 | build gate | CI/local build | 로컬 dotnet build warning/error zero evidence |
| P5-01 | deployment smoke | deploy workflow | CI 배포 success + 실제 도메인 smoke success |
| P5-02 | incident FAQ | docs FAQ section | common failure, root cause, and recovery steps documented |
Playwright Evidence Standard
- 시나리오는 실제 사용자 관점이어야 한다.
- 버튼 클릭, 입력, 저장, 조회 같은 동작을 포함해야 한다.
- 결과는 화면 캡처만으로 끝내지 않고 DOM 캡처를 함께 남긴다.
- API 응답 또는 화면 텍스트를 기준으로 기대값과 실제값을 assert한다.
- 실패 시에는 어떤 데이터가 달랐는지 로그로 남긴다.
- 최종 완료 검증은
https://www.taxbaik.com/taxbaik도메인에서 수행한다. IP 직결 주소는 로컬/임시 점검용으로만 쓴다.
Deployment and Trouble FAQ
Q1. 로그인 화면에 MudBlazor를 쓰면 안 되나?
Static SSR 로그인이라면 쓰지 않는 것이 맞다. MudBlazor는 static rendering을 지원하지 않으므로 login은 HTML form 또는 Razor Page가 안전하다.
Q2. 브라우저 앱에 JWT를 localStorage에 저장해도 되나?
피해야 한다. 브라우저 사용자 인증은 HttpOnly cookie가 기본이고, JWT는 외부 API 클라이언트용으로 분리한다.
Q3. WebAssembly 홈에서 cookie 인증 API 호출이 복잡한가?
same-origin이면 단순하다. cross-origin이면 CORS, SameSite, credentials 정책이 추가되어 장애 포인트가 늘어난다.
Q4. Dapper를 쓰면 ORM의 변경 추적이 없는데 괜찮나?
이 구조는 조회와 명령을 분리하는 쪽에 맞는다. SQL을 명시적으로 관리하고 repository 테스트와 migration으로 정합성을 유지한다.
Q5. PostgreSQL 18.4로 업그레이드할 때 dump/restore가 필요한가?
같은 18.x minor 업그레이드는 dump/restore가 필요하지 않다. 다만 운영 적용 전 staging restore drill은 필수다.
Stop Conditions
- MudBlazor를 static rendering 화면에 억지로 넣는 시도는 중단한다.
- 로그인 SSR과 WASM home 경계를 흐리는 구현은 중단한다.
- 관리자 로그인 WASM을 즉시 제거하지 말고, 먼저 migration WBS와 대체 SSR 경로를 정의한다.
- JWT를 브라우저 저장소에 넣는 설계는 중단한다.
- 완료 데이터 정의가 없는 WBS는 완료로 보지 않는다.