Files
MBN_STOCK_WEBVIEW/docs/PLAYOUT.md

14 KiB

Tornado/K3D x64 송출 운영 가이드

안전 기준

기본 모드는 DryRun입니다. DryRun은 COM 객체를 만들거나 Tornado 출력에 명령을 보내지 않고 WebView 메시지, 큐, 상태 및 오류 표시 흐름만 검증합니다. 현재 방송 PROGRAM(PGM)에 연결된 Tornado 프로세스는 항상 안전하지 않은 대상으로 취급합니다. 프로세스 이름이나 실행 여부만으로 테스트 대상이라고 판단하지 않습니다.

이 저장소의 작업과 자동 검증은 실제 PGM 출력 또는 라이브 TAKE IN을 허가하지 않습니다. Test 검증은 PGM과 분리된 전용 테스트 인스턴스, 테스트 출력 채널 및 허용 목록에 든 테스트 씬을 모두 확인한 뒤에만 수행합니다. Live는 운영 책임자의 명시적인 회차별 허가 없이는 사용하지 않습니다.

확인된 x64 COM 등록

현재 개발 장비에서 확인할 등록 기준은 다음과 같습니다.

항목 기대값
레지스트리 뷰 HKLM\SOFTWARE\ClassesRegistry64; 관련 HKCU override 없음
TypeLib GUID {2B7F2D64-3A8D-401C-BE73-5C0747BA342C}
TypeLib 버전/대상 1.0 / 0\win64
KAEngine CLSID {D756CDBE-AA31-42B2-9CC7-018753CA61BF}
ProgID K3DAsyncEngine.KAEngine.1
KAEventHandler CLSID / ProgID {39828C77-EFF0-4E59-979B-8673C028C718} / K3DAsyncEngine.KAEventHandler.1
ThreadingModel Apartment
DLL PE 대상 TypeLib, KAEngine, KAEventHandler 모두 AMD64

Inspect-K3DRegistration.ps1은 64비트 HKLM 등록에서 GUID, 버전과 win64 TypeLib을 확인합니다. KAEngine과 KAEventHandler 각각의 CLSID→ProgID 및 ProgID→CLSID 양방향 매핑, Apartment 모델, InprocServer32 존재와 AMD64 PE 헤더도 검사합니다. HKCU 64비트 Software\Classes에 같은 TypeLib GUID, CLSID 또는 ProgID override가 하나라도 있으면 fail-closed합니다. 레지스트리와 파일을 읽기만 하며 COM을 활성화하거나 등록을 변경하지 않습니다.

MBN_STOCK_WEBVIEW.PlayoutSmoke --probe는 런타임과 같은 검사기를 통해 KAEngine과 KAEventHandler 등록을 함께 확인합니다. 이 probe도 COM 객체를 생성하지 않습니다.

powershell -NoProfile -ExecutionPolicy Bypass `
  -File .\scripts\Inspect-K3DRegistration.ps1

검사가 실패하면 x86 등록으로 대체하거나 DLL을 앱 폴더에 복사하지 않습니다. 벤더가 제공한 x64 설치 프로그램과 라이선스 절차로 장비 상태를 복구한 뒤 다시 검사합니다.

런타임 참조 방식

앱은 빌드 시점의 Interop.K3DAsyncEngineLib.dll을 참조하지 않습니다. HKLM 64비트 등록과 HKCU override 부재를 검증한 뒤 고정된 KAEngine/KAEventHandler CLSID로만 런타임 late binding하고, COM 객체와 호출 세부 사항은 IPlayoutEngine 구현 안에 격리합니다. 따라서 obj 폴더에 남은 Interop DLL 또는 특정 개발 장비의 벤더 설치 경로가 빌드 입력이 되지 않습니다.

타입 정보를 조사해야 할 때만 Generate-K3DInterop.ps1을 선택적으로 사용합니다. 생성 전 Inspect와 같은 HKLM 양방향 매핑·두 COM 서버 AMD64·HKCU override 부재 검사를 통과해야 합니다. 그 뒤 알려진 Windows SDK의 x64 TlbImp.exe 위치를 선택하거나 명시적으로 받은 x64 경로를 검증하고 /machine:X64로 생성합니다. 입력 TypeLib과 도구 및 결과물 모두 AMD64인지 확인하며, 결과는 Git에서 제외된 다음 위치에만 씁니다.

artifacts\K3DInterop\Interop.K3DAsyncEngineLib.dll

실행 전 계획만 확인:

powershell -NoProfile -ExecutionPolicy Bypass `
  -File .\scripts\Generate-K3DInterop.ps1 -WhatIf

진단용 Interop 생성:

powershell -NoProfile -ExecutionPolicy Bypass `
  -File .\scripts\Generate-K3DInterop.ps1

SDK가 기본 위치에 없다면 x64 SDK의 TlbImp.exe 절대 경로를 -TlbImpPath에 지정합니다. 생성물은 진단용일 뿐 프로젝트 참조나 MSIX 콘텐츠로 추가하지 않습니다. 이 스크립트도 COM 활성화와 등록 변경은 하지 않습니다.

로컬 설정

런타임 설정 기본 경로는 다음과 같습니다.

%LOCALAPPDATA%\MBN_STOCK_WEBVIEW\Config\playout.local.json

playout.example.json을 구조 참고용으로 사용합니다. 예시는 DryRun, 외부 씬 루트와 출력 채널 미지정, 빈 씬 허용 목록, 라이브 신뢰 플래그 해제 상태이므로 실제 출력에 사용할 수 없습니다. 테스트 장비의 호스트, 채널, 창 제목 패턴, 외부 씬 루트와 허용할 씬 이름은 로컬 파일에만 기록하고 Git, 로그 또는 지원 첨부파일에 넣지 않습니다.

속성 의미
mode Disabled, DryRun, Test, Live 중 하나
host, port 테스트 또는 운영 승인을 받은 KTAP endpoint
tcpMode, clientPort KTAPConnect의 전송 모드와 로컬 client port 인자. Test/Live는 유실 방지를 위해 tcpMode: 1만 허용
sceneDirectory Test/Live에서 사용하는 외부 .t2s 루트의 절대 경로. null은 안전한 미설정 상태
outputChannel 확인된 전용 출력 채널. null은 안전한 미설정 상태
layoutIndex 씬 플레이어 layout 위치
testProcessWindowTitlePattern 전용 테스트 인스턴스만 식별하는 창 제목 패턴
testSceneAllowlist Test에서 허용한 테스트 scene name(code) 목록. 경로나 확장자는 넣지 않음
trustedLiveOutputEnabled 운영자가 로컬 파일에서만 설정하는 라이브 1차 게이트
queueCapacity 직렬 STA 명령 큐의 최대 대기 항목 수
*TimeoutMilliseconds 연결, 작업 및 해제 제한 시간
processPollIntervalMilliseconds Tornado2 접두사 프로세스 감시 주기
reconnect* 재연결 지연, 최대 횟수 및 활성화 여부

JSON보다 다음 환경 변수가 우선합니다.

MBN_STOCK_PLAYOUT_MODE
MBN_STOCK_PLAYOUT_HOST
MBN_STOCK_PLAYOUT_PORT
MBN_STOCK_PLAYOUT_TCP_MODE
MBN_STOCK_PLAYOUT_CLIENT_PORT
MBN_STOCK_PLAYOUT_SCENE_DIRECTORY
MBN_STOCK_PLAYOUT_OUTPUT_CHANNEL
MBN_STOCK_PLAYOUT_LAYOUT_INDEX
MBN_STOCK_PLAYOUT_TEST_WINDOW_TITLE_PATTERN
MBN_STOCK_PLAYOUT_QUEUE_CAPACITY
MBN_STOCK_PLAYOUT_CONNECT_TIMEOUT_MS
MBN_STOCK_PLAYOUT_OPERATION_TIMEOUT_MS
MBN_STOCK_PLAYOUT_DISCONNECT_TIMEOUT_MS
MBN_STOCK_PLAYOUT_PROCESS_POLL_INTERVAL_MS
MBN_STOCK_PLAYOUT_RECONNECT_DELAY_MS
MBN_STOCK_PLAYOUT_MAXIMUM_RECONNECT_ATTEMPTS
MBN_STOCK_PLAYOUT_RECONNECT_ENABLED

testSceneAllowlisttrustedLiveOutputEnabled는 환경 변수로 변경할 수 없으며 로컬 설정 파일에서만 관리합니다. SceneDirectory는 Test/Live에서 존재하는 비-reparse 외부 디렉터리여야 하며, 엔진은 상대 .t2s 파일을 정규화해 이 루트 밖으로 나가는 경로를 거부합니다. scene file의 basename과 scene name 및 Test allowlist 항목도 서로 일치해야 합니다. 설정 파일은 실행 계정만 읽을 수 있도록 ACL을 제한합니다. 라이선스 키나 인증정보를 이 파일에 기록하지 않습니다.

모드와 안전 게이트

Disabled는 모든 송출 명령을 거부하는 운영 롤백 모드입니다. DryRun은 COM 없이 WebView 동작을 성공 결과로 모의합니다. TestLive만 등록된 COM을 사용할 수 있습니다.

Test 전환 전 다음 조건을 모두 사람이 확인합니다.

  1. Tornado 인스턴스가 현재 PGM과 물리적·논리적으로 분리되어 있고 Test의 host가 로컬 loopback IP literal(127.0.0.1 또는 ::1)입니다. localhost를 포함한 호스트 이름은 허용하지 않습니다.
  2. testProcessWindowTitlePattern이 전용 테스트 인스턴스 하나만 식별합니다.
  3. outputChannel이 라우터/엔진에서 테스트 출력임을 확인했습니다.
  4. sceneDirectory가 승인된 테스트 자산 루트이고 사용할 scene name이 testSceneAllowlist에 있으며 운영 씬이 아닙니다.
  5. 같은 플레이리스트로 DryRunPREPARE, TAKE IN, NEXT, TAKE OUT 메시지와 화면 상태를 먼저 확인했습니다.

프로세스 감시는 이름이 Tornado2로 시작하는 모든 프로세스를 대소문자 구분 없이 찾습니다. 이는 가용성 신호일 뿐 송출 권한이 아닙니다. Test에서는 Tornado2 프로세스가 정확히 하나이고 그 창 제목이 테스트 규칙에만 일치해야 하며, PGM/PROGRAM 창이 하나라도 있거나 여러 인스턴스가 모호하면 COM을 활성화하지 않습니다. 즉 현재 방송 PGM이 실행 중인 장비에서는 Test 연결을 거부합니다.

Test에서 로컬 프로세스/창 제목 검사를 원격 KTAP endpoint의 신원 증명으로 사용하지 않습니다. 따라서 Test 모드는 loopback endpoint만 허용하며, 원격 host는 아래의 Live 이중 승인을 모두 통과한 경우에만 사용할 수 있습니다.

Live에는 별도의 이중 승인이 필요합니다.

  1. 로컬 JSON의 trustedLiveOutputEnabled를 명시적으로 true로 설정합니다.
  2. 그 회차에만 프로세스 환경 변수 MBN_STOCK_PLAYOUT_AUTHORIZE_LIVE_OUTPUT을 정확히 I_AUTHORIZE_LIVE_PROGRAM_OUTPUT_FOR_THIS_LAUNCH로 설정합니다.

둘 중 하나라도 없으면 라이브 출력을 거부해야 합니다. 이 값은 사용자/시스템 영구 환경 변수로 저장하지 않으며 앱 종료 후 제거합니다. 현재 작업에는 이 승인이 주어지지 않았으므로 Live 및 실제 PGM TAKE IN 검증을 수행하지 않습니다.

안전한 스모크 절차

먼저 modeDryRun이고 라이브 환경 변수가 없는지 확인합니다.

Remove-Item Env:MBN_STOCK_PLAYOUT_AUTHORIZE_LIVE_OUTPUT -ErrorAction SilentlyContinue
powershell -NoProfile -ExecutionPolicy Bypass `
  -File .\scripts\Inspect-K3DRegistration.ps1
dotnet run --project .\tools\MBN_STOCK_WEBVIEW.PlayoutSmoke `
  -c Debug -p:Platform=x64 -- --probe
dotnet run --project .\tools\MBN_STOCK_WEBVIEW.PlayoutSmoke `
  -c Debug -p:Platform=x64 -- --dry-run
dotnet test .\MBN_STOCK_WEBVIEW.sln -c Debug -p:Platform=x64
dotnet test .\MBN_STOCK_WEBVIEW.sln -c Release -p:Platform=x64

PlayoutSmoke --probe의 기본 출력은 등록 준비 여부·issue 이름, Tornado2 프로세스 수와 PROGRAM 감지 여부만 제공합니다. 벤더 DLL 전체 경로, 프로세스 ID/이름 및 창 제목은 출력하거나 로그에 남기지 않습니다. 정확한 로컬 등록 경로가 필요한 관리자는 Inspect-K3DRegistration.ps1 결과를 해당 장비에서만 확인하고 지원 첨부파일에 포함하지 않습니다.

앱을 실행한 뒤 다음을 확인합니다.

  1. 시작 상태가 DRY RUN으로 보이고 앱이 COM 또는 Tornado 없이 종료되지 않습니다.
  2. WebView의 PREPARE, TAKE IN, NEXT, TAKE OUT이 native bridge를 통과해 명확한 결과를 표시합니다.
  3. 잘못된 설정 또는 엔진 부재가 앱 종료가 아니라 연결 상태와 안전한 오류 메시지로 표시됩니다.
  4. x64 MSIX를 설치해도 같은 dry-run 흐름이 동작합니다.

실제 COM 스모크는 별도 테스트 인스턴스와 테스트 씬이 준비된 때에만 진행합니다. 위 안전 게이트를 독립적으로 재확인하고 modeTest로 바꾼 뒤 테스트 모니터에서 PREPARE → TAKE IN → NEXT → TAKE OUT 결과를 관찰합니다. PGM/운영 출력에 변화가 보이면 즉시 앱을 종료하고 롤백합니다. 명령 timeout 뒤 결과가 불명확하면 명령을 자동 또는 수동으로 반복하지 말고 테스트 출력 상태를 먼저 확인합니다.

패키지 스모크에서는 벤더 x64 COM이 장비에 정식 등록되어 있어야 합니다. MSIX에 벤더 DLL을 복사해 활성화 오류를 우회하지 않습니다. 패키지 컨텍스트에서 COM 활성화가 막히면 DryRun 또는 Disabled를 유지하고 HRESULT와 등록 검사 결과만 보고합니다.

장애 및 롤백

가장 빠른 롤백은 로컬 설정을 다음처럼 바꾸고 앱을 재시작하는 것입니다.

{
  "mode": "Disabled"
}

그 다음 회차별 라이브 환경 변수를 제거하고 테스트/운영 라우팅 상태를 사람이 확인합니다. 필요하면 조직 배포 절차로 직전 서명 MSIX로 되돌립니다. COM 등록 해제, 벤더 설치 폴더 삭제 또는 DLL 교체는 앱 롤백 절차가 아니므로 수행하지 않습니다. 진단용 artifacts\K3DInterop을 삭제해도 런타임에는 영향이 없습니다.

연결 장애나 Tornado 재시작은 화면의 Disconnected, Reconnecting, Faulted 또는 OutcomeUnknown 상태로 판단합니다. 재연결 횟수를 모두 소진하거나 결과가 불명확한 송출 명령이 있으면 자동 재송출하지 않고 Disabled로 전환한 뒤 운영자가 테스트 출력 상태를 확인합니다.

저장소 반입 금지

다음 항목은 Git과 MSIX에 넣지 않습니다.

  • 벤더 COM DLL 및 생성한 Interop DLL
  • Tornado/K3D 라이선스 파일, 키 또는 인증서
  • 실제 .t2s 씬, 이미지, 영상 및 방송 자산
  • 운영 호스트, 채널, 창 제목 및 로컬 허용 목록이 든 설정
  • 실제 출력 캡처나 비밀정보가 포함된 진단 로그

벤더 바이너리와 자산은 승인된 설치·배포 위치에서 관리하고, 앱 저장소에는 COM 중립 인터페이스와 안전한 설정 예시만 유지합니다.