Fluent UI Blazor v5 / InteractiveServer 방침을 폐기하고 MudBlazor 컴포넌트 + Interactive WebAssembly 렌더 모드 + API-First 를 신규 표준으로 확정한다. 기존 CLAUDE.md(Fluent UI)와 AGENTS.md §5b(MudBlazor)의 상충을 해소한다. - CLAUDE.md: Framework & Design System, Component Rules, 매핑표를 MudBlazor 로 갱신 - AGENTS.md §5b: 렌더 모드 표준(Interactive WebAssembly) 신설, Server 표기 정렬 - ROADMAP_WBS.md: WBS-10 보강 문서 상호 참조 링크 추가 - WBS_10_DOTNET_MIGRATION_HARDENING: 마이그레이션 완성/상용화 로드맵 신규, UI 코드 전환을 WBS-A7 로 등록 코드 전환(csproj/Program.cs/.razor)은 미수행, 본 커밋은 방침 문서만 수정. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
15 KiB
WBS-10 보강: .NET Core 마이그레이션 완성 & 상용화 로드맵 (2026-06-30)
본 문서는 docs/ROADMAP_WBS.md 의 WBS-10(.NET 엔진 고도화) 을 현 시점 실측 기준으로 재진단하고, 마이그레이션 완성과 단일 사용자 상용 운영에 필요한 잔여 작업을 재정의한다.
작성 배경: 기존 WBS-10 의 다수 항목이
완료로 표기되어 있으나, 2026-06-30 소스 실측 결과 표기와 실제 상태 간 괴리가 확인되었다. 본 문서는 그 괴리를 정리하고 실제 잔여 작업을 추적한다.의사결정(사용자 확정): ① 우선순위 = 마이그레이션 완성 우선, ② 산출물 = 로드맵/WBS 문서, ③ 인증 모델 = 단일 사용자 + 기본 보호.
1. Context — 왜 이 보강이 필요한가
QuantEngine 은 은퇴자산 포트폴리오 운용을 위한 결정론적 퀀트 엔진이다. canonical 권위는 여전히 Python 구현(219 파일, 24,683 lines) 에 있고, .NET 10 마이그레이션은 Core / Application / Infrastructure / Web / Tools / Tests 6개 프로젝트로 구조화되어 Phase 1(Web UI)·Phase 2(KIS 수집)까지 도달했다.
그러나 다음 세 가지 근본 결손으로 마이그레이션 완료 및 상용 기준에 미달한다.
- 마이그레이션 미완성 — 도메인 단일 권위가 Python 에 잔존.
PipelineOrchestrator가 실제 로직이 아닌 시뮬레이션 스텁. Python↔.NET 패리티가 일부 도메인 계산기에만 존재. GAS 공식 14건 미이관. - 상용 운영 결손 — 소스에 하드코딩 시크릿 잔존,
.gitignore의bin/obj누락으로 빌드 산출물 git 추적, 헬스체크·메트릭·재시도·스케줄러·운영 구성(appsettings.Production.json) 부재. - 검증 공백 — KIS→스냅샷→정성매도 전 구간 E2E 와 CI 커버리지 게이트 부재.
2. 표기 vs 실제 괴리 정리 (2026-06-30 실측)
| 기존 WBS | 기존 표기 | 실측 상태 | 괴리 / 조치 |
|---|---|---|---|
| WBS-10.6 파이프라인 오케스트레이터 | 완료 | PipelineOrchestrator.cs 가 각 단계를 Task.Delay(10) 로만 시뮬레이션. 실제 서비스 호출 없음 |
🔴 실질 미완성. → 본 문서 A1 로 재추적 |
| WBS-10.9 보안 강화 | 완료 | appsettings.json 은 Password=; 처리됨. 그러나 Program.cs:19 텔레그램 토큰 평문, Program.cs:34 DB 패스워드 폴백 평문 잔존. .gitignore 에 bin/obj 없음 → 산출물 git 추적 |
🔴 부분 완료(핵심 누락). → 본 문서 P0 로 재추적 |
| WBS-10.8 데이터 수집 오케스트레이터 | TODO | 실제로는 DataCollectionService.cs(KIS 수집 오케스트레이션) 구현·커밋됨. 단 파일명/구조가 WBS 기재(DataCollectionOrchestrator.cs)와 불일치 |
🟡 표기 미갱신. → 본 문서 A3 로 정합화 |
| WBS-10.3~10.5 도메인/공식/하네스 패리티 | 완료 | DomainParityTests, FormulaEngineTests, HarnessInjector 패리티 존재 확인 |
✅ 유효. 단 패리티 범위가 도메인 계산기에 한정 → 수집/정성매도/스냅샷은 미커버 (A2 확장) |
| WBS-10.7 Application 서비스 | 부분 완료 | 4개 서비스 구현 확인 | ✅ 유효 |
핵심 시사점: 기존 WBS-10 은 "완료" 표기가 실제보다 앞서 있다. 특히 보안(10.9)과 파이프라인(10.6)은 표기와 달리 실질 미완성이므로, 후속 작업은 표기를 신뢰하지 말고 본 문서의 실측 기준을 따른다.
3. 로드맵 (마이그레이션 완성 우선)
[P0 선행 게이트] 보안·위생 차단 ──► 반드시 먼저
│
▼
[Track A] 마이그레이션 완성 (PRIMARY) [Track B] 상용 안정화 (SECONDARY, 병행)
A1 PipelineOrchestrator 실구현 B1 구성/시크릿 체계화
A2 패리티 하네스 확장(수집·정성매도) B2 기본 인증(단일 사용자)
A3 데이터 수집 파이프라인 E2E 정합화 B3 헬스체크·메트릭
A4 정성매도/스냅샷 어드민 포팅 B4 재시도(Polly)·스케줄러
A5 GAS 잔여 14개 공식 이관 B5 배포(Docker/CI 게이트)
A6 SQLite→PostgreSQL 단일화 + Python 폐기 B6 통합/E2E 테스트·커버리지 게이트
마일스톤
| 마일스톤 | 구성 | 완료 기준 |
|---|---|---|
| M1 위생 확보 | P0 | git 에서 시크릿/산출물 제거, 시크릿 외부화·회전 |
| M2 패리티 기반 | A1·A2 | .NET 도메인이 Python 골든 벡터와 1:1 일치, 실 파이프라인 산출 |
| M3 수집 자립 | A3·A4·B4 | .NET 단독 KIS→스냅샷→정성매도 무인 실행 |
| M4 단일 권위 전환 | A5·A6 | Python 런타임 의존 제거, .NET canonical 승격 |
| M5 상용 운영 | B1~B6 | 단일 사용자 보호·관측·배포 체계 가동 |
4. WBS (작업 분해 구조)
각 항목: 목표 / 완료 판정(Acceptance) / 주요 파일 / 검증 명령.
P0 — 선행 보안·위생 게이트 (🔴 Critical, 최우선)
WBS-P0.1 빌드 산출물 git 추적 제거
- 목표:
.gitignore에 .NET 표준 패턴(bin/,obj/,publish-output/,*.user) 추가, 추적 중 산출물git rm -r --cached처리. - 판정:
git status에bin/obj변경 미표시. - 파일:
.gitignore. - 검증:
git status --porcelain | grep -E 'bin/|obj/'→ 0건.
WBS-P0.2 하드코딩 시크릿 제거·회전
- 목표:
Program.cs:19텔레그램 토큰·채팅ID,Program.cs:34DB 패스워드 폴백을 환경변수/dotnet user-secrets/appsettings.Production.json(비추적)로 이전. 노출 토큰·DB 비밀번호 회전. - 판정: 소스 전역 시크릿 평문 0건, 구성 누락 시 앱 기동 거부(fail-fast).
- 파일:
Program.cs,appsettings*.json,Infrastructure/TelegramSink.cs. - 검증:
Select-String -Pattern '8734507814|C8RFlZ9f' src/dotnet -Recurse→ 0건.
WBS-P0.3 git 이력 시크릿 정리 (선택)
- 목표: 노출 토큰 회전 완료 시 이력 재작성 생략 가능. 회전 불가 시
git filter-repo로 이력 제거 검토. - 판정: 회전 완료 또는 이력 정리 완료 중 택1 기록.
주의: WBS-10.9 가
완료로 표기되어 있으나 위 P0.1·P0.2 는 미해결 상태다. 본 게이트 완료 전까지 후속 트랙 착수를 보류한다.
Track A — 마이그레이션 완성 (PRIMARY)
WBS-A1 PipelineOrchestrator 실제 구현
- 목표:
Task.Delay시뮬레이션 제거. 7단계(수집→정규화→팩터→결정→리스크게이트→리포트→영속화)를 실제 서비스 호출로 연결. - 판정: 입력 스냅샷에 대해 결정 패킷 산출, 각 단계 결과가
engine_history에 기록. - 파일:
QuantEngine.Application/Services/PipelineOrchestrator.cs, 관련Services/*. - 검증:
dotnet test --filter Pipeline→ 실데이터 기반 산출물gate: PASS.
WBS-A2 패리티 하네스 확장 (수집·정성매도)
- 목표: 기존 도메인 계산기 패리티(10.3~10.5)를 수집 정규화·정성매도·하네스 주입 전체로 확장.
spec/13_formula_registry.yaml(149 공식) 기준 골든 벡터를 Python 에서 추출해.NET결과와 비교. - 판정: 핵심 공식 전부 Python 과 동일 출력(부동소수 허용오차 내), 패리티 리포트 JSON 생성.
- 파일:
QuantEngine.Core.Tests/ParityTests/,tests/golden/. - 검증:
dotnet test --filter Parity→ 전건 PASS.
WBS-A3 데이터 수집 파이프라인 E2E 정합화
- 목표:
DataCollectionService.cs(구현됨)를 기준으로 WBS 표기 정합화,kis_data_collection_v1.py잔여 로직 완전 이관, KIS→PostgreSQL 스냅샷 E2E 검증. Naver/Yahoo 폴백 다중화 명문화. - 판정:
.NET단독 실데이터 수집·저장 성공, 폴백 동작 확인. - 파일:
Application/Services/DataCollectionService.cs,Infrastructure/External/*.
WBS-A4 정성매도·스냅샷 어드민 포팅
- 목표:
qualitative_sell_strategy_v1.py,snapshot_admin_*_v1.py를.NET서비스/엔드포인트로 이관. - 판정: 정성매도 5팩터 confluence 결과 Python 일치, 스냅샷 승인 워크플로우가 Web UI 에서 동작.
- 파일:
QuantEngine.Core/Domain/,QuantEngine.Web/Endpoints/,Components/Pages/.
WBS-A5 GAS 잔여 14개 공식 이관
- 목표:
governance/gas_logic_migration_ledger_v1.yaml의 TODO 14건을.NET포팅 + parity. - 판정: 원장 전 항목
status: DONE, parity 통과. - 파일:
QuantEngine.Core/Domain/,governance/gas_logic_migration_ledger_v1.yaml.
WBS-A6 SQLite→PostgreSQL 단일화 및 Python 런타임 폐기
- 목표: canonical DB 를 PostgreSQL 로 일원화,
src/quant_engine/*.db의존 제거, Python 런타임 도구를.NET/Tools로 대체. - 판정: 운영 경로 Python 호출 0건, 모든 데이터 PostgreSQL 단일 소스.
- 파일:
Infrastructure/Data/DbMigrator.cs,Makefile,tools/.
WBS-A7 UI 프레임워크 전환 — Fluent UI → MudBlazor + Interactive WebAssembly (2026-06-30 방침)
- 배경: UI 표준을 MudBlazor 컴포넌트 + Interactive WebAssembly 렌더 모드 + API-First 로 전환(방침 확정). 기존 Fluent UI v5 / InteractiveServer 는 폐기. 정책은 CLAUDE.md 및 AGENTS.md §5b 에 반영 완료.
- 목표:
- csproj 패키지 교체:
Microsoft.FluentUI.AspNetCore.Components*제거 →MudBlazor추가. - 렌더 모드 전환:
Program.cs의AddInteractiveServerComponents/AddInteractiveServerRenderMode→AddInteractiveWebAssemblyComponents/AddInteractiveWebAssemblyRenderMode, 클라이언트 프로젝트(QuantEngine.Web.Client) 분리. App.razor: Fluent CSS/JS·FluentDesignSystemProvider제거 → MudBlazor<MudThemeProvider>/<MudDialogProvider>/<MudSnackbarProvider>+MudBlazor.min.css/js삽입.- 전체
.razor컴포넌트의Fluent*→Mud*치환(매핑표는 CLAUDE.md Component Mapping 참조). - API-First: UI 의 직접 DI 호출을
IXxxBrowserClient(HTTP) 경유로 전환,TokenRefreshHandler패턴 적용.
- csproj 패키지 교체:
- 판정: Fluent UI 패키지/참조 0건,
dotnet build오류 0, WASM 로드 후/quant/및 주요 페이지 정상 렌더, 비-API 라우트 동작 확인. - 주요 파일:
QuantEngine.Web/QuantEngine.Web.csproj,Program.cs,Components/App.razor,Components/Layout/*.razor,Components/Pages/*.razor, 신규QuantEngine.Web.Client/. - 검증:
Select-String -Pattern 'Fluent' src/dotnet/QuantEngine.Web -Recurse→ 0건; 브라우저에서 WASM 모드 동작 확인.
Track B — 상용 안정화 (SECONDARY, 단일 사용자)
WBS-B1 구성·시크릿 체계화
- 목표:
appsettings.Production.json(비추적),IOptions<T>+ 시작 시 구성 검증(fail-fast), 연결 문자열/토큰 환경변수 표준화. - 판정: 개발/운영 구성 분리, 필수 구성 누락 시 명확 오류로 기동 중단.
WBS-B2 기본 인증 (단일 사용자 보호)
- 목표: 공개 서버 노출 방어용 최소 인증 — 리버스 프록시 Basic Auth 또는 API Key 미들웨어 1종(
/api/*·UI 보호). 본격 Identity/JWT 는 범위 외. - 판정: 비인증 요청 401, 인증 요청만 수집/조회 가능.
- 파일:
Program.cs,Endpoints/CollectionEndpoints.cs, Nginx 구성.
WBS-B3 헬스체크·메트릭
- 목표:
MapHealthChecks("/health")(liveness) +/health/ready(PostgreSQL/KIS 토큰 점검),prometheus-net기반 기본 메트릭. - 판정: 배포 스크립트 헬스체크가
/health/ready사용, 메트릭 엔드포인트 응답. - 파일:
Program.cs,.gitea/workflows/deploy-prod.yml.
WBS-B4 재시도(Polly)·백그라운드 스케줄러
- 목표: KIS/Naver/Yahoo HTTP 호출에 Polly 재시도·서킷브레이커, 주기적 수집을
BackgroundService(또는 systemd timer 연계)로 자동화. - 판정: 일시적 5xx/네트워크 오류 자동 복구, 정해진 스케줄 무인 수집.
- 파일:
Program.cs(HttpClient+Polly), 신규Application/Services/*BackgroundService.cs.
WBS-B5 배포 (Docker/CI 게이트)
- 목표: 멀티스테이지
Dockerfile+docker-compose.yml(app+PostgreSQL),.giteaCI 에dotnet build+dotnet test게이트 추가. - 판정: 컨테이너 로컬 기동 성공, CI 에서 테스트 실패 시 배포 차단.
- 파일: 신규
Dockerfile,docker-compose.yml,.gitea/workflows/ci.yml.
WBS-B6 통합·E2E 테스트 및 커버리지 게이트
- 목표: Testcontainers(PostgreSQL) 통합테스트, KIS→스냅샷→정성매도 E2E, coverlet 커버리지 임계값을 CI 게이트로 연결.
- 판정: E2E 1건 이상 그린, 커버리지 임계 미달 시 CI 실패.
- 파일:
QuantEngine.Core.Tests/(통합/E2E),.gitea/workflows/ci.yml.
5. 개선·보완·고도화 제안 (Track A/B 외 권고)
- 결정 재현성 감사: 동일 입력 → 동일 출력 결정론 검증을 CI 상시 게이트로 편입 (governance/adr/0003-no-llm-numeric-generation.md 정신 계승).
- 캘리브레이션 실증 연계: spec/27_bch_calibration_runbook.yaml 의
0/190 CALIBRATED문제를 마이그레이션과 분리된 데이터 트랙으로 별도 추적(본 WBS 범위 밖, 링크 유지). - 장애 단일점 보강: Naver Cloudflare 403 폴백 경로를 Yahoo/KIS 다중화로 명문화(WBS-A3 연동).
- 운영 가시성: 구조화 로깅에 상관관계 ID(correlation id) 추가, 수집 실행별 추적 가능화.
- 비밀 회전 정책: KIS appkey/secret, 텔레그램 토큰, DB 비밀번호의 주기적 회전 절차를 docs/runbook.md 에 문서화.
- WBS 표기 정합성 거버넌스: 본 문서에서 드러난 "완료 표기 vs 실측" 괴리 재발 방지를 위해, 각 WBS 완료 시 검증 명령 출력 캡처를 증빙으로 첨부하는 규칙을 강화(AGENTS.md 의 검증·증빙 강제 원칙 적용).
6. 검증 방법 (각 단계 실행 시)
- P0:
git status산출물 미추적 확인, 시크릿 평문 grep 0건, 회전된 자격증명으로 정상 기동. - Track A:
cd src/dotnet && dotnet test로 패리티/단위/E2E 그린. 패리티 리포트 JSON 을 Python 출력과 diff. 운영 경로 Python 호출 0건. - Track B:
curl /health/ready200, 비인증 요청 401,docker compose up기동, CI 테스트/커버리지 게이트 동작. Polly 재시도는 장애 주입 테스트로 검증.
7. 실행 순서 요약
- P0 선행 게이트 (WBS-P0.1~P0.3) — 보안·위생 차단. (기존 10.9 完了 표기 무시, 실측 기준 처리)
- Track A (A1→A2→A3→A4→A5→A6) — 마이그레이션 완성(우선).
- Track B (B1~B6) — 단일 사용자 상용 안정화(A 와 병행, B1·B3 조기 착수 권장).