releases/IMPLEMENTATION_AUDIT.md

9.6 KiB

구현 감사 보고서 — 계획 ↔ 구현 ↔ 증거 매핑

대상: BROWSER_FEATURES_PLAN.md (v2) + MOBILE_PLAN.md (v1) 전 항목 감사일: 2026-08-15 · 방법: TDD(RED→GREEN) + E2E 검증 요약: 전 솔루션 Release 빌드 0 오류, 단위/E2E 테스트 103/103 GREEN, Android 에뮬레이터·iOS 시뮬레이터·LAN 서버 E2E 완료

감사 중 발견·수정된 회귀: HlsDownloader 3-인자 ctor가 _muxer 미할당(재구성 ② 누락) → 모든 HLS 리먹스 NUL 위험. RED 테스트(HlsMuxerWiringTests)로 재현 후 ctor 할당 수정. DashDownloader는 정상.


1. 브라우저 기능 계획 (BROWSER_FEATURES_PLAN v2)

Phase 0 — 퀵윈

항목 구현 증거
T1-3 페이지 내 검색 (Ctrl+F) ✅ 네이티브 CoreWebView2.Find + 자체 하단 바, 일치 수 X/Y Browser/FindSession.cs · WebView2FindE2ETests(네이티브 Find 3매치)
T1-4 검색엔진 ✅ URL/검색어 판별, 기본 엔진, g /b /d /n /yt 키워드 SearchEngineResolver.cs + 단위테스트
T1-7 사이트별 줌 영속 ✅ 도메인→배율 LRU(300), www 정규화, 클램프 0.1~5.0 SiteZoomStore.cs + 단위테스트
T1-9 강제 새로고침 ✅ Ctrl+Shift+R MainWindow.xaml.cs 단축키
T1-11 전체화면 F11 ✅ 크롬 자동 숨김 MainWindow.xaml.cs

Phase A — 탭 아키텍처

항목 구현 증거
탭 시스템 (T1-1) ✅ 공유 Environment + 탭당 WebView2, 생성/닫기/전환/Ctrl+Tab·1~9/드래그 정렬/Move Browser/Tabs/TabManager.cs · MainWindowSmokeE2ETests(탭 생명주기 E2E)
T1-2 닫은 탭 복원 ✅ Ctrl+Shift+T, 스택 25개 TabManager.ReopenClosedTab + 테스트
NewWindowRequested→새 탭 ✅ deferral 패턴 TabViewService NewTabProvider
T1-8 오디오 표시/뮤트 ✅ 스피커 아이콘 + 클릭 뮤트 탭 템플릿 TabAudio_Click
T1-10 세션 복원 ✅ session.json 저장/복원(옵션) TabSessionStore.cs + 테스트 (VD_DATA_DIR 격리)

Phase B — 탭 보조

항목 구현 증거
T1-5 다운로드 매니저 ✅ 진행률/속도/일시정지/재개/취소/완료 정리 PageDownloadTracker.cs(IDownloadOperation 주입) + 테스트
T1-6 북마크바 ✅ Ctrl+Shift+B 토글, 원클릭 이동 MainWindow.xaml bookmarkbar 행
T2-2 탭 절전 ✅ 유휴 서스펜드 "zzz" TabSuspendService.cs + 테스트
T2-8 탭 검색 ✅ Ctrl+Shift+A, 열린+닫힘 탭 TabSearchFilter.cs + 테스트
T2-12 우클릭 "이 링크 영상 받기" ✅ 커스텀 컨텍스트 메뉴 TabViewService.ContextMenuBuild

Phase C — 차별화

항목 구현 증거
T2-1 명령 팔레트 ✅ Ctrl+K 탭/북마크/기록/액션/웹검색 CommandPalette.cs + 테스트
T2-3 분할 화면 ✅ 2분할 + 스플리터 + Exit MainWindow SplitCol/분할 단축키
T2-4 리더 모드 ✅ Readability.js(Mozilla) 내장 → 스타일 본문, 원본 복원 ReaderMode.cs · ReaderModeE2ETests(실제 추출+복원 E2E)
T2-5 세로 탭 ✅ 토글, 좌측 사이드 스트립 ToggleVerticalTabs
T2-6 Glance ✅ Alt+클릭 플로팅 미리보기 GlanceWindow.cs
T2-7 사이트별 Boost ✅ 강제 다크(invert-hue-rotate, 이미지/영상 보호) 등 BoostStore/BoostCssBuilder + 테스트
T2-9 스크린샷 ✅ Ctrl+Shift+S CapturePreviewAsync
T2-11 탭 그룹 ✅ 6색 그룹, 인접 정렬, 그룹 닫기 TabManagerGroupExtensions + 테스트

Phase D — 시그니처

항목 구현 증거
T2-10 미디어 재생목록 ✅ 감지 미디어 자동 적재, 플라이아웃, 플레이어 창(native+hls.js+dash.js), 자동 다음, JSON 영속 MediaPlaylist.cs · PlayerWindow.cs + 테스트
T3-1 워크스페이스 ✅ 저장/전환 TabManagerWorkspaceExtensions + 테스트
T3-3 컨테이너/InPrivate ✅ IsInPrivateModeEnabled 탭 OpenInPrivateTab
T3-4 빠른 찾기 / ✅ MainWindow 단축키
T3-5 컨텍스트 메뉴 전면 커스터마이징 ✅ WPF 메뉴 + SelectedCommandId TabViewService
T3-7 PiP ✅ 별도 최상위 창 TogglePip
T3-8 Speed Dial ✅ 새 탭 다이얼 그리드 NewTabWithDial
T3-9 읽어주기(TTS) ✅ SpeakText
T3-10 인쇄/소스보기 ✅ Ctrl+P / Ctrl+U MainWindow

T3 중 명시적 미구현 (계획 내 후순위/선택)

  • T3-2 Auto-Archive 캐던스 — 닫힘 스택(25개)+복원이 커버(아카이브 자동화는 미차용)
  • T3-11 권한 UI — PermissionRequested 배선 미삽입 (계획상 선택)
  • T3-12 노트 패널 — 계획 자체가 "후순위" 명시
  • T3-13 컴팩트 모드 — F11 전체화면이 동등 커버
  • T3-14 추적 방지 카운터 — 미차용
  • T3-15 주소창 진행 바/파라미터 제거 복사 — 미차용

재구성 (사용자 지시 "근원부터 뜯어고쳐")

작업 결과
Detection → VideoDownloader.Core.Detection 이동 App 의존성 역전
Core/Platform/ 신설: IProcessRunner/ProcessSpec/DesktopProcessRunner(stdout·stderr 동시 콜백 계약 문서화), IMediaMuxer/DesktopMediaMuxer(-progress 파싱) 모바일/크로스플랫폼 재사용 준비 (MOBILE_PLAN §1.4 추상화 4곳 중 3곳)
VideoDownloader.Browser 라이브러리 (탭/검색/줌/세션) god-class 해체
TabViewService 추출 (탭별 WebView2 배선 전담) MainWindow 코드비하인드 축소

2. 모바일 계획 (MOBILE_PLAN v1)

항목 구현 증거
M0 Core 추상화 ✅ IProcessRunner/IMediaMuxer/경로(CorePaths, VD_DATA_DIR 오버라이드) PlatformAbstractionTests(cmd.exe 통합, FakeProcessRunner)
M0 VideoDownloader.Server ✅ Kestrel, Bearer+쿼리 토큰(상수시간), /api/pair·queue CRUD·library·stream(206 Range)·file·웹 컴패니언 RemoteServerE2ETests(401/pair/queue/library/Range 206/file/웹컴패니언 전 경로)
M0 QR 페어링 다이얼로그 ✅ QRCoder, LAN IP 자동 PairingWindow.cs
M0 검증 관문: 웹 컴패니언 ✅ 제로 설치 페이지(#t= 프래그먼트 페어링, 2초 폴링, video 스트리밍) WebCompanion.cs + E2E
M1 QR 스캔 페어링 + 수동 폴백 ✅ ZXing(실기기) + 수동 IP:포트+토큰 에뮬레이터 E2E에서 수동 페어링으로 실증 (IME 제약)
M1 큐 목록 실시간 + 제어 ✅ 2초 폴링(계획 허용안: "v1은 2초 폴링 가능"), 일시정지/재개/취소 버튼 에뮬 E2E: 라이브 서버 데이터 렌더 실증
M1 링크 붙여넣기 추가 ✅ URL 엔트리 + "PC에서 받기" 페이지 UI + 서버 API E2E (POST 400 검증 포함)
M2 라이브러리 목록 ✅ 파일명/크기 에뮬 E2E: sample.mp4/415,253 bytes 렌더
M2 MediaElement 스트리밍 재생 ✅ Range HTTP → 모달 플레이어 에뮬 E2E: 실제 MP4 프레임 렌더 실증(testsrc 패턴 스크린샷) + 서버 ESTABLISHED
M3 net10.0-ios ✅ macOS 전용 TFM 조건 분기 vd-mac 빌드: Mach-O arm64 .app, Info.plist 검증
M3 iOS 시동 ✅ iPhone 17 시뮬레이터(iOS 26) 설치+실행, 전체 UI 렌더 스크린샷

모바일 E2E에서 발견·수정된 결함 (TDD 외 가치)

  1. 탭 자식 PushAsync 불가(NavigationPage 부재) → 루트 모달 PushModalAsync + NavigationPage 래핑
  2. CollectionView.SelectionChanged Android 비발화 → 템플릿 카드 TapGestureRecognizer
  3. 링커가 Xamarin.AndroidX.LocalBroadcastManager 제거 → Release 크래시 → 명시 참조
  4. iOS NSCameraUsageDescription 누락 → 시작 크래시 → Info.plist 추가 (iOS+MacCatalyst)
  5. 시뮬레이터 카메라 세션이 첫 프레임 블록 → 스캐너를 실기기(Physical)로 게이트

명시적 미구현 (계획 허용/후순위)

  • SignalR 허브 — 계획안 명시 "v1은 2초 폴링으로도 가능" 채택
  • mDNS 광고(_videodl._tcp) — QR 페어링이 주 경로(계획 §6 리스크 대응과 동일 전제)
  • U4 폰 오프라인 저장(GET /file/{id} API는 구현됨, 앱 측 다운로드 탭 미구현 — Tier M2 후반)
  • U5 완료 푸시 알림, 이어보기 위치 동기화(POST /api/position 미구현)
  • M4 Android 독립 다운로더 — 계획상 "선택"
  • iOS TestFlight — 앱 실행/페어링 프레이밍까지만 (감사일 기준)

3. 배포 (DEPLOYMENT_PLAN)

항목 상태
Windows 로컬 빌드 ✅ Release 0 오류
linux-x64 셸(Cli+Avalonia) self-contained ✅ vd-linux 빌드+ELF 검증 → out/remote/linux-x64/
osx-arm64 셸 ✅ vd-mac 빌드+Mach-O 검증 → out/remote/osx-arm64/
Android APK ✅ x86_64 Release 서명 APK(에뮬 설치/실행 실증)
iOS .app ✅ vd-mac iossimulator-arm64 빌드
빌드머신 SSH 키 프로비저닝 ✅ build/remote/install-buildkey.ps1

4. 성공 기준 체크 (계획 §7)

  • dotnet build 전체 0 오류 — 8개 프로젝트(App/Avalonia/Browser/Cli/Core/Mobile/Server/Tests)
  • 기존 미디어 감지·다운로드 회귀 없음 — Detection 이동 후 단위/E2E GREEN
  • 폰 브라우저 웹 컴패니언 큐 조회/추가 (M0) — 서버 E2E
  • Android 앱 큐 실시간 갱신/제어 (M1) — 에뮬 E2E 라이브 데이터
  • 라이브러리 스트리밍 재생(시크 포함) (M2) — 실측 MP4 프레임 + 206 Range
  • iOS 빌드 시동 + 큐 조회 (M3) — iOS 26 시뮬레이터 UI 렌더
  • 폰 저장 오프라인 재생 (M2 후반) — 미구현(위 표)