feat: complete legacy UI and playout parity migration
This commit is contained in:
@@ -1,101 +1,141 @@
|
||||
# 원본 호환 마이그레이션 기준선
|
||||
|
||||
## 결정
|
||||
기준일: 2026-07-15
|
||||
|
||||
기존 저장소와 검증된 `Core / Infrastructure / Playout`은 유지한다. 기존 루트 WinUI 앱은 비교용 프로토타입으로 보존하고, 원본 UI와 이벤트를 먼저 재현하는 `MBN_STOCK_WEBVIEW.LegacyParityApp`을 같은 솔루션에서 병행 개발한다.
|
||||
## 현재 결정
|
||||
|
||||
WebView는 HTML 컨트롤 표시와 사용자 입력 전달만 담당한다. 검색 정책, 선택 상태, 플레이리스트 필드, 장면 alias, PageN 및 송출 상태의 권위는 C# Application 계층에 둔다.
|
||||
마이그레이션의 실행 대상은 `MBN_STOCK_WEBVIEW.LegacyParityApp`이다. 이 앱은
|
||||
`.NET 8 / C# / WinUI 3 / Windows App SDK 1.8 / WebView2 / Windows x64 / MSIX`로
|
||||
구성된 Windows 데스크톱 프로그램이다. WebView2는 앱에 포함된 로컬 HTML/CSS/JavaScript를
|
||||
표시하는 컨트롤이며, 별도 웹 서버에 배포하는 웹사이트가 아니다.
|
||||
|
||||
## 기준 원본
|
||||
원본 WinForms UI의 화면 구성과 클릭 이벤트를 먼저 동등하게 옮긴 뒤 개선한다. 기존에
|
||||
검증된 `Core / Infrastructure / Playout`은 재사용하며, 원본 업무 규칙과 송출 권위는
|
||||
C#에 둔다.
|
||||
|
||||
- 읽기 전용 저장소: `C:\Users\MD\source\repos\MBN_STOCK_N`
|
||||
- 조사 시 HEAD: `309286309eaf20b58172247263f575753a860700`
|
||||
- 실제 실행 컷 목록: `MBN_STOCK_N\bin\Debug\Res\종목.ini`
|
||||
- 실행 컷 목록 SHA-256: `45DFB1804828F0E4A45F73D681AF0709CE5662872FAA49CFC9F7A0B940409E20`
|
||||
- 실행 컷 목록은 구분행 2개를 포함한 33개 물리행이며 실제 컷은 31개다.
|
||||
- 3번 컷은 고객 화면과 실행본을 따라 `1열판기본_시간외단일가`를 사용한다. 소스 `Res`의 `시간외종가`는 기준으로 사용하지 않는다.
|
||||
## 기준 원본과 보존 원칙
|
||||
|
||||
원본 작업 트리에는 기존 수정이 있으므로 커밋 SHA만으로 동등성을 판단하지 않는다. 원본은 계속 읽기 전용으로 취급한다.
|
||||
- 읽기 전용 원본: `C:\Users\MD\source\repos\MBN_STOCK_N`
|
||||
- 원본 저장소와 `MBN_STOCK_N\MBN_STOCK_N\bin\Debug\Cuts`는 분석·검증에만 사용한다.
|
||||
- 원본 파일, 원본 설정, 실제 컷과 자산을 수정하거나 새 저장소에 복사하지 않는다.
|
||||
- 벤더 DLL, K3D 라이선스, 인증서, DB 비밀번호, 실제 컷·배경 파일과 로컬 운영 설정은
|
||||
Git/MSIX에 넣지 않는다.
|
||||
- 실행 컷 목록은 구분행 2개를 포함한 물리행 33개와 실제 종목 컷 31개다.
|
||||
- 원본 scene inventory는 35개 builder이며, MainForm에서 도달 가능한 runtime은 34개
|
||||
builder와 45개 active alias다. `s8086`은 원본과 같이 무alias 진단 전용이다.
|
||||
|
||||
## 신규 프로젝트
|
||||
## 실행 구조와 권위 경계
|
||||
|
||||
| 프로젝트 | 책임 |
|
||||
| 계층 | 책임 |
|
||||
|---|---|
|
||||
| `MBN_STOCK_WEBVIEW.LegacyApplication` | 원본 MainForm/UC 상태, 이벤트 및 업무 규칙 |
|
||||
| `MBN_STOCK_WEBVIEW.LegacyBridge` | 허용된 WebView 입력 intent와 표시 snapshot 계약 |
|
||||
| `MBN_STOCK_WEBVIEW.LegacyParityApp` | WinUI 3 창, WebView2, DB composition root, 별도 개발 MSIX |
|
||||
| `LegacyApplication.Tests` | 원본 이벤트 및 결과 DTO 동등성 테스트 |
|
||||
| `LegacyBridge.Tests` | strict JSON과 Web 권한 경계 테스트 |
|
||||
| `LegacyWeb.Tests` | Visual Studio에서 항상 실행되는 Web thin-client 계약 테스트 |
|
||||
| `MBN_STOCK_WEBVIEW.LegacyApplication` | 원본 MainForm/UC/Form 상태, 클릭 이벤트, playlist와 업무 규칙의 C# 권위 |
|
||||
| `MBN_STOCK_WEBVIEW.LegacyBridge` | WebView가 보낼 수 있는 intent의 strict JSON allowlist와 표시 snapshot 계약 |
|
||||
| `MBN_STOCK_WEBVIEW.LegacyParityApp` | WinUI 3 창, 로컬 WebView2 UI, DB composition root, 송출 연결과 개발 MSIX |
|
||||
| `MBN_STOCK_WEBVIEW.Core` | DTO, scene resolver/builder, PageN과 `LegacyPlayoutWorkflow` |
|
||||
| `MBN_STOCK_WEBVIEW.Infrastructure` | Oracle/MariaDB와 신뢰 파일 저장소 구현 |
|
||||
| `MBN_STOCK_WEBVIEW.Playout` | `IPlayoutEngine` 뒤의 K3D/Tornado2 어댑터, STA 큐와 안전 게이트 |
|
||||
|
||||
개발 패키지 identity는 `Wickedness.MBNStockWebView.LegacyParity`다. 운영 identity `Wickedness.MBNStockWebView`를 대체하지 않는다.
|
||||
WebView는 표시와 사용자 입력 수집만 담당한다. 종목·시장 identity, 7필드 playlist 행,
|
||||
scene alias, DB mutation, PageN, PREPARED/PROGRAM 상태는 Web에서 임의 생성하거나
|
||||
확정할 수 없다. 모든 입력은 `LegacyBridgeProtocol`의 폐쇄형 intent로 파싱되고
|
||||
`LegacyOperatorController`가 다시 검증한 뒤 실행된다.
|
||||
|
||||
## 첫 수직 흐름 상태
|
||||
## 이관된 원본 UI와 이벤트
|
||||
|
||||
구현됨:
|
||||
- 원본 10개 업무 탭과 탭 순서 변경
|
||||
- 모든 탭에서 유지되는 종목 검색, 종목 결과, 31개 컷과 playlist 편집
|
||||
- 328개 fixed action, 코스피·코스닥 업종 44개 action, 비교 대상 24개와 비교 9개 action
|
||||
- UC4 테마, UC6 전문가와 UC7 거래정지의 원본 단일 클릭 동작
|
||||
- UC4/UC6 목록 행과 고정 action 트리의 독립 클릭 경계
|
||||
- GraphE 네 수동 재무 화면과 행 더블클릭 추가
|
||||
- FSell 개인·외국인·기관 5행 입력과 VI 목록·정렬·페이지 입력
|
||||
- PList/AList의 목록, 신규 생성, 저장, 불러오기, 삭제와 행 더블클릭
|
||||
- ThemeA와 EList의 검색, 생성, 편집, 삭제, 종목 구성과 순서 변경
|
||||
- UC5 해외업종·해외종목·해외지수
|
||||
- playlist 단일/Ctrl/Shift 선택, enabled, 위/아래 이동, 선택/전체 삭제
|
||||
- F2/F3 배경, Fade, NEXT/Page NEXT, TAKE OUT, 종료 확인과 자동 갱신
|
||||
|
||||
- 검색 버튼의 정확한 빈 문자열 no-op과 Enter 빈 검색 허용
|
||||
- KOSPI → KOSDAQ → NXT KOSPI → NXT KOSDAQ 순서 및 DB 반환 순서 유지
|
||||
- trim, 전체 정렬, 결과 제한 및 wildcard escape를 하지 않는 원본 호환 검색
|
||||
- 바인드 파라미터를 통한 SQL injection 방지
|
||||
- master snapshot을 이름으로 다시 순회하고 마지막 일치를 채택하는 `jongmokCode` 규칙
|
||||
- 33개 물리 컷 행과 31개 display 번호
|
||||
- 원본 `ClientSize 1905 x 1015`, `FixedSingle`, 최대화 불가 창 계약
|
||||
- 일반/Ctrl/Shift/Ctrl+Shift 선택을 C# 상태로 처리
|
||||
- 0.5초 이내, 동일 행, 동일 좌표 조건의 원본 더블클릭 판정
|
||||
- 선택 컷 drag/drop과 물리 index 오름차순 추가
|
||||
- 원본 7필드 플레이리스트 행과 중복 추가 허용
|
||||
- NXT `1열판기본_현재가`만 허용하고 나머지는 원본 경고 표시
|
||||
- PREPARE 직전 `LegacyPlaylistEntry`로 변환할 수 있는 31개 컷 행의 alias 매핑
|
||||
FarPoint 표 자체는 Web table로 바뀌었지만 원본의 선택, 정렬, 이동, 단일/더블클릭,
|
||||
저장·불러오기 이벤트 경계는 C# intent와 snapshot으로 유지한다.
|
||||
|
||||
아직 이관하지 않음:
|
||||
## 송출 동작
|
||||
|
||||
- 좌측 수동 입력 GraphE 4개 모달
|
||||
- 중앙 UC1~UC7과 모든 탭 이벤트
|
||||
- 플레이리스트 선택/삭제/정렬/DB 저장·불러오기
|
||||
- 배경, 이동평균, Fade/Update 시간 컨트롤
|
||||
- PREPARE/TAKE IN/NEXT/TAKE OUT 실제 연결
|
||||
- 운영 DB write와 Tornado2/PGM 검증
|
||||
운영자 화면에는 원본처럼 `TAKE IN`, `NEXT`, `TAKE OUT`을 제공한다. 별도 native
|
||||
`PREPARE` 버튼은 엔지니어링 진단용으로 DOM에 유지하지만 숨겨져 있다. idle 상태에서
|
||||
`TAKE IN` 또는 F8을 한 번 실행하면 C#이 같은 게이트 안에서 다음 순서를 정확히 한 번씩
|
||||
수행한다.
|
||||
|
||||
미이관 버튼은 현재 disabled 상태이며, 연결 상태는 `미연결`로 명시한다. 새 앱은 Tornado2에 연결하지 않는다.
|
||||
1. 선택 playlist와 page를 C# snapshot으로 고정
|
||||
2. 실제 DB/신뢰 파일에서 DTO를 다시 조회
|
||||
3. `BeginTransaction` → mutation → `QueryVariables` → `EndTransaction`
|
||||
4. `Prepare`
|
||||
5. `TakeIn`
|
||||
|
||||
PREPARE 성공 뒤 TAKE IN이 실패하거나 결과가 불명확하면 prepared 소유권을 유지하고
|
||||
자동 재시도하지 않는다. `NEXT`는 같은 scene의 다음 PageN과 다음 enabled playlist 행을
|
||||
원본 조건으로 구분한다. timeout과 `OutcomeUnknown`에서는 반대 명령, cleanup 명령 또는
|
||||
동일 명령을 추측해 반복하지 않는다.
|
||||
|
||||
기본 송출 모드는 계속 `DryRun`이다. Live는 개발 Tornado2/PGM 설정, 프로세스별 명시적
|
||||
환경 승인, scene allowlist, 명령 예산을 모두 통과해야 한다. 이 안전 게이트는 개발 환경에서도
|
||||
완화하지 않는다.
|
||||
|
||||
## scene, alias와 PageN 기준선
|
||||
|
||||
- 원본 scene builder source inventory: **35/35**
|
||||
- 도달 가능한 active alias: **45개**, 승인된 읽기 전용 Cuts에 대응 `.t2s` 존재
|
||||
- PageN: `s5074=5`, `s5077=6`, `s5088=12`개 단위
|
||||
- page count: `min(20, ceil(itemCount / pageSize))`
|
||||
- 빈 결과, 첫/마지막 부분 페이지, 정확한 경계, 20페이지 cap, 21페이지 거부,
|
||||
같은 scene Page NEXT와 다음 playlist NEXT를 자동 테스트로 고정
|
||||
|
||||
장면별 세부 상태는 [`SCENE_EQUIVALENCE.md`](SCENE_EQUIVALENCE.md), 호출 순서는
|
||||
[`LEGACY_PLAYOUT_ANALYSIS.md`](LEGACY_PLAYOUT_ANALYSIS.md)를 따른다.
|
||||
|
||||
## DB 검증 기준선
|
||||
|
||||
실제 Oracle/MariaDB read-only 스모크는 필수 scene selector **33/33**, 전체 query 58건을
|
||||
통과했다. 이는 실제 DB → DTO → mutation 경로 검증이며 외부 영상 자산이나 PGM 출력 성공을
|
||||
뜻하지 않는다.
|
||||
|
||||
개발 DB write 스모크는 충돌 격리된 임시 식별자로 다음 9개 시나리오의
|
||||
create/save → fresh readback → delete → absence를 통과했다.
|
||||
|
||||
- GraphE `INPUT_PIE`, `INPUT_GROW`, `INPUT_SELL`, `INPUT_PROFIT` 4개
|
||||
- PList/AList named playlist 1개
|
||||
- ThemeA KRX 1개와 NXT 1개
|
||||
- EList/expert 1개
|
||||
|
||||
스모크는 production executor를 사용하고 write 재시도를 하지 않는다. 결과가
|
||||
`OutcomeUnknown`이면 cleanup이나 다음 시나리오를 실행하지 않는 규칙도 유지한다.
|
||||
DB 비밀번호와 원문 데이터는 문서와 로그에 기록하지 않는다.
|
||||
|
||||
## 외부자산 상태
|
||||
|
||||
45개 active alias의 `.t2s`는 존재한다. 다만 다음 14개 종속 파일은 현재 승인 Cuts에
|
||||
제공되지 않았다.
|
||||
|
||||
- `s5006`: `Video\큐브배경.vrv` 1개
|
||||
- `s6001`: 국가별 `Video\20201008_<국가>.vrv` 13개
|
||||
|
||||
또한 원본 sibling `배경` 디렉터리의 `기본.vrv`도 이 장비에 없다. 이 상태는 scene/UI
|
||||
코드 누락이나 마이그레이션 실패가 아니라 **Git/MSIX 밖 외부자산 미제공**이다. 자산이
|
||||
없으면 해당 경로는 COM 호출 전에 fail closed하고, 다른 파일로 추정 대체하지 않는다.
|
||||
|
||||
## Visual Studio 실행
|
||||
|
||||
1. `MBN_STOCK_WEBVIEW.sln`을 연다.
|
||||
2. 솔루션 구성을 `ParityDebug | x64`로 선택한다.
|
||||
3. `MBN_STOCK_WEBVIEW.LegacyParityApp`을 시작 프로젝트로 지정한다.
|
||||
4. 실행한다.
|
||||
2. `x64` 구성을 선택한다.
|
||||
3. `src\MBN_STOCK_WEBVIEW.LegacyParityApp\MBN_STOCK_WEBVIEW.LegacyParityApp.csproj`를
|
||||
시작 프로젝트로 지정한다.
|
||||
4. Debug 실행 또는 Release x64 MSIX를 생성한다.
|
||||
|
||||
`PrototypeDebug | x64`는 기존 루트 앱을 배포하는 비교용 구성이다. 두 앱은 서로 다른 MSIX identity와 single-instance key를 사용한다.
|
||||
개발 패키지 identity는 `Wickedness.MBNStockWebView.LegacyParity`이며 기존 운영 패키지
|
||||
identity를 대체하지 않는다.
|
||||
|
||||
기존 `Release | x64`의 자동 배포 대상은 비교용 루트 앱으로 유지한다. 호환 앱 Release는 두 패키지를 동시에 배포하지 않도록 `MBN_STOCK_WEBVIEW.LegacyParityApp` 프로젝트의 MSIX 생성 명령으로 명시적으로 만든다.
|
||||
## 2026-07-15 검증 기록
|
||||
|
||||
## 2026-07-15 기준선 검증
|
||||
|
||||
- `ParityDebug | x64`와 `Release | x64` 솔루션 빌드: 경고 0, 오류 0
|
||||
- Debug/Release 각각 C# 테스트 1,980개 통과
|
||||
- Core 1,383 / Infrastructure 173 / Playout 393
|
||||
- LegacyApplication 17 / LegacyBridge 7 / LegacyWeb 7
|
||||
- Node 기반 JavaScript syntax 및 Web 계약 테스트 7개 통과
|
||||
- Release x64 개발 MSIX `0.1.0.0` 생성 및 `CN=Comtrophy` 서명 검증
|
||||
- MSIX SHA-256: `D3FF9CF1F63E6BC68AA147C0ED47690FE130CF425C0276B3201F763EC5C50A4B`
|
||||
- 패키지 76개 항목 중 인증서, 비밀번호, 라이선스, `.t2s`, 운영 설정 파일 0개
|
||||
- 패키지의 `Web/index.html`, `styles.css`, `app.js`가 소스와 byte 단위로 일치
|
||||
- 별도 패키지 전체 이름 `Wickedness.MBNStockWebView.LegacyParity_0.1.0.0_x64__qbv3jkvsn3aj0`, package family `Wickedness.MBNStockWebView.LegacyParity_qbv3jkvsn3aj0` 설치·실행 성공
|
||||
- 패키지 창의 실제 WebView client bounds `1905 x 1015` 확인
|
||||
- 격리 WinForms ListView trace로 최초 Shift의 native 선택 `0..현재행`과 별도 pointer 목록의 `-1..현재행`, 같은 행 Shift의 native 선택 유지와 pointer 목록 clear를 확인하고 두 상태를 분리
|
||||
- 실제 DB read-only 경로로 `삼성` 검색 → `삼성출판사` 선택 → `현재가` 동일 좌표 더블클릭 → 원본 7필드 플레이리스트 행 생성 확인
|
||||
- 검색 시작 직후 정상 창 닫기 경합 검증에서 10초 이내 종료 및 Windows Application 오류 이벤트 0개
|
||||
|
||||
이 검증에서는 DB write, PREPARE, TAKE IN, NEXT, TAKE OUT 및 Tornado2 연결을 실행하지 않았다. 화면의 송출 버튼도 계속 비활성 상태다.
|
||||
|
||||
## 다음 이관 순서
|
||||
|
||||
1. 플레이리스트 row 선택·Ctrl/Shift·삭제·전체/개별 enabled
|
||||
2. 중앙 탭과 UC1부터 원본 이벤트 단위로 수직 이관
|
||||
3. 수동 입력 Form과 격리 DB write/read-back
|
||||
4. C# playlist authority를 기존 `LegacyPlayoutWorkflow`에 연결한 DryRun PREPARE
|
||||
5. 35개 scene/PageN differential trace
|
||||
6. 승인된 실제 Tornado2/PGM 검증
|
||||
|
||||
각 기능은 원본 입력과 신규 입력의 snapshot, DB 파라미터, 플레이리스트 7필드 및 K3D trace를 비교한 뒤 완료 처리한다.
|
||||
확정된 전체 회귀, 새 Release MSIX SHA-256, package-context DryRun/Live, 개발
|
||||
Tornado2 Network Monitoring과 PGM 결과는
|
||||
[`LEGACY_PARITY_VALIDATION_20260715.md`](LEGACY_PARITY_VALIDATION_20260715.md)에
|
||||
기록했다. 이전 패키지의 숫자나 해시는 현재 결과로 재사용하지 않았다.
|
||||
|
||||
Reference in New Issue
Block a user