203 lines
14 KiB
Markdown
203 lines
14 KiB
Markdown
# LegacyParityApp 이관 검증 증적 — 2026-07-15
|
|
|
|
이 문서는 현재 `MBN_STOCK_WEBVIEW.LegacyParityApp`의 구현 증적과 지금 채택할 수 있는
|
|
검증 경계를 한곳에 모은다. 2026-07-15의 signed Release MSIX 설치·실행, 실제 마우스/CDP
|
|
UI 동작과 제한된 Live 연결 실측은 아래 범위로 기록한다. 병렬 변경 전체의 최종
|
|
Debug/Release 및 Web 회귀 수는 확정했지만, scene PREPARE/TAKE IN/PGM 출력은 이 회차의
|
|
증적으로 확정하지 않는다. 원본
|
|
`C:\Users\MD\source\repos\MBN_STOCK_N`은 모든 조사와 테스트에서 읽기 전용으로
|
|
취급했다.
|
|
|
|
## 제품 형태와 권위 경계
|
|
|
|
| 항목 | 결과 |
|
|
|---|---|
|
|
| 제품 형태 | `.NET 8 / C# / WinUI 3 / Windows App SDK 1.8 / WebView2 / x64 / MSIX` Windows 데스크톱 앱 |
|
|
| 웹사이트 여부 | 웹사이트가 아님. WinUI 3 프로세스가 패키지의 로컬 Web 자산을 WebView2로 표시 |
|
|
| 업무 권위 | `LegacyOperatorController`의 C# 상태와 검증된 DTO가 권위 |
|
|
| Web 경계 | `LegacyBridgeProtocol`의 strict JSON intent allowlist; Web은 DB identity, scene alias, playlist 또는 송출 상태를 확정하지 않음 |
|
|
| 벤더 경계 | COM/K3D/Tornado 구현은 `IPlayoutEngine` 뒤에 격리하고 STA 큐와 안전 게이트 유지 |
|
|
| 기본 송출 모드 | `DryRun`; Live는 별도 개발 설정, 프로세스별 승인, allowlist와 명령 예산 필요 |
|
|
| VS Development Live | 정확한 `--development-live` + Debug + Git 제외 strict 로컬 승인 파일이 모두 맞을 때만 process-scope Live 설정; Release와 오류 경로에서는 이 bootstrap이 Live를 새로 설정하지 않음 |
|
|
| 불명확 결과 | timeout/`OutcomeUnknown`에서 자동 재시도·반대 명령·추측 cleanup 금지 |
|
|
|
|
## 원본 UI와 클릭 이벤트
|
|
|
|
| 범위 | 현재 증적 |
|
|
|---|---|
|
|
| Designer 전수 감사 | 원본 Designer 구독 **186개**, 화면별 고유 핸들러 **171개**를 IMPL/DEAD/VISUAL/DRAG/SAFETY로 전수 분류 |
|
|
| 업무 탭 | 원본 10개 탭, identity 기반 활성화와 순서 변경 |
|
|
| 종목 영역 | 모든 탭에서 유지되는 종목 검색, 결과, 31개 컷과 playlist 추가 |
|
|
| 고정/업종/비교 | fixed 328개, 업종 44개, 비교 대상 24개와 action 9개를 폐쇄형 inventory로 고정 |
|
|
| 독립 클릭 | UC4 테마, UC6 전문가, UC7 거래정지의 원본 단일 클릭과 UC4/UC6 행별 독립 처리 |
|
|
| 전용 입력 | GraphE, FSell, VI, PList, AList, ThemeA, EList를 WebView 화면과 C# intent로 연결; ThemeA exact-title 중복확인 포함 |
|
|
| 해외 | UC5 해외업종·해외종목·해외지수 조회와 playlist 생성 |
|
|
| playlist | F8 후보와 Ctrl/Shift 삭제 선택 분리, enabled, 위/아래, 선택/전체 삭제와 drag source 단일 행 이동; PREPARED/PROGRAM/pending/unknown 변경 차단 |
|
|
| FarPoint 대체 | Web table로 표현하되 원본 클릭·더블클릭·정렬·이동·저장, 탭 dragover 교환과 UC6/EList opaque 행 drag 의미 유지 |
|
|
|
|
상세 이벤트 대조는 [`OPERATOR_UI_PARITY.md`](OPERATOR_UI_PARITY.md)를 따른다.
|
|
|
|
### 이벤트·drag·중복확인 구현 증적
|
|
|
|
줄 단위 원본 근거는
|
|
[`LEGACY_DESIGNER_EVENT_PARITY_AUDIT.md`](LEGACY_DESIGNER_EVENT_PARITY_AUDIT.md)에 있다.
|
|
186개 구독/171개 고유 핸들러 수에는 선언만 있고 구독되지 않은 메서드를 넣지 않았다.
|
|
|
|
- playlist drag는 opaque source/target `rowId`와 before/after만 Web에서 보내며, C#이 실제
|
|
drag source 한 행만 이동한다. Ctrl/Shift 집합은 삭제 선택으로 유지하고 체크박스 dragstart는 거부한다.
|
|
- 시장 탭은 dragover 대상 진입 시 source/target identity와 예상 인덱스를 보낸다. C# 현재
|
|
순서가 예상값과 일치할 때만 교환하므로 같은 전달의 재처리는 no-op이다.
|
|
- UC6의 `FpSpread2.AllowDragDrop`은 ThemeA/EList 편집 행의 opaque `rowId` 재정렬로
|
|
이관했다. Web이 DB identity나 play index를 정하지 않는다.
|
|
- ThemeA `중복확인`은 이름 하나만 strict intent로 받고 C#이 현재 KRX/NXT provider에서
|
|
exact title parameterized read를 수행한다. 불명 결과는 `Indeterminate`이고 write나
|
|
fallback이 없다. edit 자기 행을 제외하지 않는 원본 규칙도 유지한다.
|
|
|
|
### 2026-07-15 실제 마우스/CDP UI 검증
|
|
|
|
설치한 현재 Release package의 실제 WebView 화면에서 다음 운영자 입력을 확인했다.
|
|
|
|
- `삼성` 검색 결과는 **63개**였고 `삼성출판사`를 선택했다. 컷 3개를 선택한 뒤 한 번의
|
|
drop으로 playlist에 정확히 3행을 추가했다.
|
|
- 당시 package에서는 playlist 여러 행을 한 블록으로 재정렬했고, enabled 체크박스에서
|
|
시작한 drag는 행 이동을 만들지 않았다. 이후 원본 `AllowRowMove` 재감사에서 블록 이동은
|
|
근거 없는 확장으로 판정되어 현재 코드는 drag source 한 행만 이동하도록 교정됐다. 따라서
|
|
이 항목의 과거 block-drag 실측은 현재 단일 행 drag의 package 실측으로 재사용하지 않는다.
|
|
- 시장 탭은 마우스 버튼을 놓기 전 dragover 대상 진입 시 순서가 바뀌었다.
|
|
- EList 편집기에서 추천행 **5개**의 순서를 drag로 변경했다.
|
|
- ThemeA 목록 **500건**을 불러온 상태에서 `중복확인` exact-title read가 성공했다.
|
|
|
|
이 과정에서 playlist 행 drop이 조상 `playlist-drop-zone`으로 버블링해 아직 선택된 컷을
|
|
추가로 append하던 문제가 발견됐다. drop zone은 이제 exact `legacy-selected-cuts`
|
|
`text/plain` token만 허용하고 playlist row custom MIME와 외부 text drop은 무시한다.
|
|
따라서 행 재정렬은 `reorder-playlist-rows`만 만들고 `drop-selected-cuts`를 만들지 않는다.
|
|
|
|
또한 Chromium은 체크박스를 눌러 시작한 경우에도 `dragstart.target`을 가장 가까운 draggable
|
|
조상 행으로 보고할 수 있어 단순 `event.target.closest("input")` 검사만으로는 부족했다.
|
|
pointerdown 때 checkbox origin의 행 ID를 기억하고 이어지는 row dragstart를 거부하며,
|
|
pointerup/pointercancel/dragend에서 상태를 지우도록 수정했다. thin-client 회귀 테스트는
|
|
이 Chromium target 형태, drag source 한 행만 전송, row drop의 ancestor 무시, 외부 text 거부와 exact
|
|
selected-cut token의 단일 처리를 실제 DOM event 순서로 고정한다.
|
|
|
|
### Development Live 시작 구성 증적
|
|
|
|
공유 `.slnLaunch`와 package launch profile은 LegacyParityApp을 시작 대상으로 고정한다.
|
|
[`DEVELOPMENT_LIVE_VISUAL_STUDIO.md`](DEVELOPMENT_LIVE_VISUAL_STUDIO.md)의 strict local
|
|
authorization은 `%LOCALAPPDATA%` 아래 Git 제외 파일에 정확한 다섯 속성, 최대 4096바이트,
|
|
canonical JSON, exact authorization 문자열과 독립 승인 native/Interop SHA-256을 요구한다.
|
|
reparse, 알 수 없는/중복 속성, 파일 및 환경 설정 오류는 fail closed하며 authorization은
|
|
process scope에서 마지막에 설정된다. 이 부트스트랩은 기존 trusted Live 이중 게이트,
|
|
scene allowlist, asset 검사와 timeout/OutcomeUnknown 정책을 대체하지 않는다.
|
|
|
|
실제 signed Release MSIX에 `--development-live`를 전달해도 compile-time Debug gate 때문에
|
|
승인 파일을 적용하지 않고 `DryRun`으로 실행되는 것을 확인했다. 이 Release DryRun 회차에는
|
|
Tornado TCP 연결이 없었고 Network Monitoring 내용도 변하지 않았다.
|
|
|
|
## 송출 흐름과 장면
|
|
|
|
| 항목 | 결과 |
|
|
|---|---|
|
|
| 원클릭 TAKE IN | idle에서 보이는 `TAKE IN`/F8 한 번으로 `PrepareAndTakeInAsync`가 page load 1회, PREPARE 1회, TAKE IN 1회를 같은 게이트에서 수행 |
|
|
| native PREPARE | 엔지니어링 진단용 control/intent는 유지하되 운영자 UI에서는 `hidden` |
|
|
| 실패 경계 | PREPARE 후 TAKE IN 실패/unknown 시 prepared state 보존, 자동 재시도 없음 |
|
|
| 장면 기준선 | 원본 builder **35/35** inventory와 mutation/runtime 자동 기준선 통과 |
|
|
| active alias | **45개** alias의 대응 `.t2s`가 승인된 읽기 전용 Cuts에 존재 |
|
|
| PageN | 5·6·12개 단위, 최대 20페이지, 경계·마지막 부분 페이지·21페이지 거부 테스트 |
|
|
| NEXT | 같은 scene의 Page NEXT와 다음 enabled playlist 행 NEXT를 원본 조건으로 구분 |
|
|
|
|
## 실제 DB 검증
|
|
|
|
| 검증 | 결과 |
|
|
|---|---|
|
|
| Oracle/MariaDB read-only | **PASS** — 필수 scene selector 33/33, 전체 query 58건 |
|
|
| GraphE write | **PASS** — `INPUT_PIE`, `INPUT_GROW`, `INPUT_SELL`, `INPUT_PROFIT` 각 create, fresh readback, delete, absence |
|
|
| PList/AList write | **PASS** — named playlist 정의·항목 create/save, fresh readback, delete, absence |
|
|
| ThemeA KRX write | **PASS** — create, preview/readback, delete, absence |
|
|
| ThemeA NXT write | **PASS** — create, preview/readback, delete, absence |
|
|
| EList write | **PASS** — expert create, preview/readback, delete, absence |
|
|
| ThemeA 중복확인 read | **PASS** — 500건 목록 상태에서 현재 market의 exact title 조회; DB write 없음 |
|
|
|
|
개발 DB write는 총 9개 충돌 격리 시나리오다. production service/executor를 사용했으며
|
|
인증정보나 DB 원문을 출력하지 않았다. write 결과가 불명확한 경우에는 재시도와 cleanup을
|
|
하지 않는 구현·테스트 경계를 유지한다.
|
|
|
|
## 외부자산 판정
|
|
|
|
| 자산 | 상태 | 판정 |
|
|
|---|---|---|
|
|
| 45 active alias `.t2s` | 존재 | alias 준비 완료 |
|
|
| `s5006` `Video\큐브배경.vrv` | 1개 없음 | 외부자산 미제공; 코드 실패 아님 |
|
|
| `s6001` 국가별 영상 | 13개 없음 | 외부자산 미제공; 코드 실패 아님 |
|
|
| sibling `배경\기본.vrv` | 없음 | 외부자산 미제공; F2/F3/default background는 fail closed |
|
|
|
|
누락 자산은 Git 또는 MSIX에 임의로 넣지 않는다. 제공되면 같은 trusted-root,
|
|
0-byte, reparse, root-escape 검사를 통과한 뒤 해당 scene만 다시 검증한다.
|
|
|
|
## 2026-07-15 Tornado2 Live 연결 실측
|
|
|
|
아래 시각은 개발 장비 로컬 시간(KST)이다. strict local authorization을 통과한 제한된 Live
|
|
회차에서 **14:28:28 HELLO request 1회와 success 1회**, **14:43:10 BYE 1회**를 Network
|
|
Monitoring에서 확인했다. 이 회차의 scene 명령, PREPARE, TAKE 계열 명령과 DB write는
|
|
각각 **0건**이다.
|
|
|
|
종료 후 보관한 Network Monitoring 원문은 **300,007자**, SHA-256
|
|
`45858322F60C135858002EB6243D0474F51F1965E23D2332D397C3A3B5DB8049`다. 이 증적은 현재
|
|
코드의 Live CONNECT/handshake/DISCONNECT 경로만 확인한다. scene load/mutation,
|
|
PREPARE, TAKE IN, NEXT/Page NEXT, TAKE OUT 또는 PGM 화면 출력을 검증했다는 뜻이 아니다.
|
|
|
|
별도의 Release DryRun 회차에서는 `--development-live`가 무시됐고 TCP 연결이 생성되지
|
|
않았으며 Network Monitoring 최종 내용도 변하지 않았다. 이는 Debug-only bootstrap 경계를
|
|
확인한 결과이지 Release Live 송출 결과가 아니다.
|
|
|
|
## 현재 package와 범위 회귀 기록
|
|
|
|
| 항목 | 2026-07-15 확인 결과 |
|
|
|---|---|
|
|
| signed Release x64 MSIX | **15,213,188 bytes**, SHA-256 `357E17426C45FF516592EE0177D0F95502A98AF084759348ABC191BA5ED21FD5` |
|
|
| 설치·실행 | 설치된 package-context 앱 실행 확인 |
|
|
| Release `--development-live` | Debug-only gate에 따라 무시되고 `DryRun`; TCP 연결과 Network Monitoring 변경 없음 |
|
|
| 실제 마우스/CDP UI 범위 | 삼성 63건 검색→삼성출판사→3컷 단일 drop, playlist multi-row reorder, checkbox drag 차단, tab dragover 교환, EList 5행 reorder, EList 수량 입력칸 origin drag 차단, ThemeA 500건과 중복확인 read 확인 |
|
|
| 제한된 Live Network 범위 | HELLO request/success 각 1회와 BYE 1회; scene/PREPARE/TAKE/DB write 0 |
|
|
| .NET Debug/Release x64 | 각 **2,446/2,446**, 실패·건너뜀 0, 경고·오류 0 |
|
|
| Web Node 회귀 | **438/438**, 실패·취소·건너뜀·TODO 0 |
|
|
| Visual Studio 2026 build | VS 18.7.3 / MSBuild 18.7.8, Debug·Release x64 모두 경고 0 / 오류 0 |
|
|
|
|
playlist drop MIME 경계, checkbox-origin drag와 EList input/button-origin drag 회귀는
|
|
thin-client DOM event 테스트로도 고정했다. 설치된 최종 Release package에서 실제 마우스로
|
|
EList 수량 입력칸에서 시작한 drag가 순서를 바꾸지 않고, 같은 행의 비입력 영역에서 시작한
|
|
drag만 5행 순서를 바꾸는 것도 확인했다. .NET Debug/Release 합계 4,892회와 Web 438회를
|
|
모두 통과했지만,
|
|
scene PREPARE/TAKE/PGM을 실행하지 않은 이 Live 연결 회차를 전체 방송 송출 PASS로 확대하지
|
|
않는다.
|
|
|
|
### 코드 대조 Slice 1~9 합본 추가 검증
|
|
|
|
이후 원본 이벤트를 다시 코드 단위로 대조해 F8 후보·PROGRAM·DEL 다중선택·Shift anchor를
|
|
분리하고, 런타임 컷 50행, 종목/컷 키보드, UC1 tree, s8010 이동평균 재샘플링, K3D raw 인자와
|
|
OnCutOut/OnStopAll callback 게이트를 합쳤다. 이 합본의 검증 결과는 다음과 같다.
|
|
|
|
| 항목 | 추가 검증 결과 |
|
|
|---|---|
|
|
| .NET Debug x64 | **2,584/2,584** 통과, 실패·건너뜀 0 |
|
|
| .NET Release x64 | **2,584/2,584** 통과, 실패·건너뜀 0 |
|
|
| Web Node | **456/456** 통과, 실패·취소·건너뜀·TODO 0 |
|
|
| 솔루션 Debug/Release x64 | NuGet x64 복원 후 각각 경고 0 / 오류 0 |
|
|
| Visual Studio 2026 MSBuild | VS **18.7.4**의 x64 MSBuild로 Debug/Release 솔루션 빌드 모두 성공 |
|
|
| 최신 unsigned Release MSIX | **15,228,096 bytes**, SHA-256 `3D7FC0C0837756C860AC660DBCEA30BF543D261FE0EEEAE1CDA294FA95CC3BF1` |
|
|
| 패키지 감사 | 75항목, `.t2s`·실설정·라이선스·인증서·K3D vendor 파일 0 |
|
|
| package-context DryRun | 최신 Release layout 실행·응답 확인, 인자 없음, 앱 소유 TCP 0, 중립 종료창 `매일경제TV`/`예`/`아니요` 확인 후 정상 종료 |
|
|
|
|
이 unsigned MSIX는 개발 package-context 실행 검증용이며 위 signed 배포 패키지를 대체하지
|
|
않는다. 이 추가 회차에서도 scene/PREPARE/TAKE/NEXT/DB write와 Tornado 연결은 실행하지 않았다.
|
|
|
|
## 판정 경계
|
|
|
|
- 35/35 자동 장면 동등성은 모든 장면의 실제 PGM 출력 완료를 뜻하지 않는다.
|
|
- 33/33 DB selector 통과는 외부 영상/배경 자산 준비를 뜻하지 않는다.
|
|
- 개발 DB 9개 write 시나리오 통과는 운영 DB에 쓰기를 허용하거나 수행했다는 뜻이 아니다.
|
|
- 현재 signed Release MSIX의 설치·DryRun 실행, 실제 마우스/CDP UI, .NET Debug/Release
|
|
각 2,446개와 Web 438개 회귀를 확인했다.
|
|
- Live 증적은 HELLO/BYE만 확인한 연결 회차다. scene/PREPARE/TAKE/DB write가 0이므로
|
|
PGM 송출 또는 원클릭 TAKE IN 전체 통합 성공으로 판정하지 않는다.
|
|
- 원본 저장소, 실제 Cuts, 라이선스와 인증정보는 계속 읽기 전용 또는 Git 외부로 유지한다.
|