feat(ads/seo/release): v1.2.0 with live Google Ads, isolated ad profile, ads.txt, and SEO/AEO/GEO optimization
This commit is contained in:
parent
a88aafa1e5
commit
0e568f1f0a
975 changed files with 130593 additions and 16783 deletions
1464
docs/BACKLOG.md
1464
docs/BACKLOG.md
File diff suppressed because it is too large
Load diff
|
|
@ -1,8 +1,8 @@
|
|||
# Video Downloader — 브라우저 기능 강화 계획서 (v2)
|
||||
# Video Downloader — 브라우저 기능 강화 계획서 (v2)
|
||||
|
||||
> **목표**: 이 앱에 내장된 WebView2 브라우저에 일반적인 데스크톱 브라우저의 **핵심 사용자 기능**을 심어, 단순 "영상 재생 → 감지" 용도를 넘어 **일상적으로 쓸 수 있는 브라우저**로 만든다.
|
||||
>
|
||||
> **작성일**: 2026-08-15 (v2 — 2차 심층 조사 반영) · **대상**: `VideoDownloader.App` (WPF + WebView2 1.0.4078.44)
|
||||
> **작성일**: 2026-08-15 (v2 — 2차 심층 조사 반영) · **대상**: `Paca.App` (WPF + WebView2 1.0.4078.44)
|
||||
>
|
||||
> **조사 방법론**:
|
||||
> - 1차(2026-08-13): Chrome/Firefox/Zen 3개 브라우저 단일 조사 → v1 초안
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
| 줌 | ✅ | 세션 한시적(사이트별 영속 아님) |
|
||||
| 팝업 → 현재 WebView 라우팅 | ✅ | `NewWindowRequested` |
|
||||
| 페이지 다운로드 → 저장 폴더 | ✅ | `DownloadStarting` |
|
||||
| 영구 프로필 / 데이터 삭제 | ✅ | `%AppData%/VideoDownloader/webview` |
|
||||
| 영구 프로필 / 데이터 삭제 | ✅ | `%AppData%/Paca/webview` |
|
||||
| 다크/라이트 테마, 보더리스 | ✅ | DWM 연동 |
|
||||
| 우측 다운로드 패널(접기/폭) | ✅ | |
|
||||
| DevTools, 미디어 자동 감지 | ✅ | HLS/DASH/직링크/소셜(yt-dlp) |
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Video Downloader — 멀티플랫폼 배포 체계 계획서 (v1)
|
||||
# Video Downloader — 멀티플랫폼 배포 체계 계획서 (v1)
|
||||
|
||||
> **범위**: Windows · macOS · Linux 데스크톱 + Android · iOS 모바일의 **빌드→서명→패키징→배포→업데이트** 전 체계.
|
||||
> GitHub Releases 를 단일 배포 소스로, GitHub Actions 로 전 아티팩트 자동 빌드.
|
||||
|
|
@ -40,11 +40,11 @@ GitHub Actions 대신(또는 보완으로) **사용자 소유 빌드머신 2대*
|
|||
|
||||
| 제품 | 플랫폼 | 아티팩트 | 채널 | 서명 |
|
||||
|---|---|---|---|---|
|
||||
| **App (WPF+WebView2)** — 주력 | Windows x64 | `VideoDownloader-Setup-x64.exe` (Inno, 기존) | GitHub Releases | Authenticode (선택, 후순위) |
|
||||
| | Windows arm64 | `VideoDownloader-Setup-arm64.exe` (기존) | 〃 | 〃 |
|
||||
| **App (Avalonia 셸)** — 크로스플랫폼 이관 | Linux x64/arm64 | `videodownloader-linux-x64.tar.gz` (기본) + `.AppImage` + `.deb` | GitHub Releases | (GPG 서명 선택) |
|
||||
| | macOS x64/arm64 | `VideoDownloader-<arch>.dmg` (+ `.app` in DMG) | GitHub Releases | Developer ID + 공증 필수 |
|
||||
| **Mobile (MAUI)** | Android | `VideoDownloader-<ver>-arm64.apk` | GitHub Releases + Obtainium | Keystore (CI 시크릿) |
|
||||
| **App (WPF+WebView2)** — 주력 | Windows x64 | `Paca-Setup-x64.exe` (Inno, 기존) | GitHub Releases | Authenticode (선택, 후순위) |
|
||||
| | Windows arm64 | `Paca-Setup-arm64.exe` (기존) | 〃 | 〃 |
|
||||
| **App (Avalonia 셸)** — 크로스플랫폼 이관 | Linux x64/arm64 | `Paca-linux-x64.tar.gz` (기본) + `.AppImage` + `.deb` | GitHub Releases | (GPG 서명 선택) |
|
||||
| | macOS x64/arm64 | `Paca-<arch>.dmg` (+ `.app` in DMG) | GitHub Releases | Developer ID + 공증 필수 |
|
||||
| **Mobile (MAUI)** | Android | `Paca-<ver>-arm64.apk` | GitHub Releases + Obtainium | Keystore (CI 시크릿) |
|
||||
| | Android (Play, 선택) | `.aab` | Google Play (추출코드 없는 빌드) | Play App Signing |
|
||||
| | iOS | `.ipa` | TestFlight → App Store | Apple 배포 인증서 |
|
||||
| **Server / 웹 컴패니언** | 데스크톱 앱에 내장 | 별도 배포 없음 (앱이 Kestrel 서빙) | — | 앱 서명에 포함 |
|
||||
|
|
@ -156,7 +156,7 @@ jobs:
|
|||
|
||||
## 5-bis. CI/CD 현행 채널 — Forgejo Actions 자체 러너 (2026-08-17 가동)
|
||||
|
||||
저장소가 자체 Forgejo(`https://git.chanpaca.net/Video-Downloader/client`)로 이관되고 org 러너 3대가
|
||||
저장소가 자체 Forgejo(`https://git.chanpaca.net/Paca/client`)로 이관되고 org 러너 3대가
|
||||
등록되어, §5(GitHub) 대신 **자체 러너로 전 아티팩트를 빌드·배포**한다. §5 는 저장소 GitHub 공개 시
|
||||
백업 채널로 유지(`.github/workflows/release.yml` 존치).
|
||||
|
||||
|
|
@ -175,19 +175,19 @@ jobs:
|
|||
- **리허설**: workflow_dispatch → `ci-rehearsal` draft prerelease 로 태그 없이 전 파이프라인 검증.
|
||||
- **시크릿**: `RELEASE_TOKEN`(Forgejo PAT, `write:repository`) — 릴리스 생성·자산 업로드. 체크아웃은 잡
|
||||
자동 토큰(`github.token`). `ANDROID_KEYSTORE/ALIAS/PASS` 등록 전까지 APK 는 디버그 서명.
|
||||
- **업로드 대상**: 공개 배포 저장소 **`Video-Downloader/releases`**(워크플로 env `RELEASE_REPO`).
|
||||
- **업로드 대상**: 공개 배포 저장소 **`Paca/releases`**(워크플로 env `RELEASE_REPO`).
|
||||
소스 저장소(client)는 비공개라 자산 익명 다운로드가 불가해 분리했다. draft 는 익명에게 보이지
|
||||
않으므로 "빌드 → draft → QA → 수동 Publish" 흐름은 그대로다. Publish 하면 §5-ter 사이트가 노출한다.
|
||||
- **머신 전제**: win = SDK 8/10 + `maui-android` 워크로드 + JDK 17 + Inno Setup 6 ·
|
||||
linux/mac = `~/.dotnet` SDK 8.0.424 + 10.0.400 (§0.5).
|
||||
- **갭**: §6 자동 업데이트 v1(`UpdateChecker`)은 GitHub Releases API 를 폴링하므로 GitHub 공개 전까지
|
||||
미동작 — Forgejo Releases API(`/repos/{owner}/{repo}/releases/latest`, 동일 형태) 대응은 후속 항목.
|
||||
대상은 공개 저장소 `Video-Downloader/releases` 가 되어야 한다.
|
||||
대상은 공개 저장소 `Paca/releases` 가 되어야 한다.
|
||||
|
||||
## 5-ter. 배포 사이트 — MEDIABROWSER (Cloudflare Pages, 2026-08-18 가동)
|
||||
## 5-ter. 배포 사이트 — Paca (Cloudflare Pages, 2026-08-18 가동)
|
||||
|
||||
제품 배포명은 **MEDIABROWSER** 로 하고, 프로모션/다운로드/사용 안내 3페이지 정적 사이트를
|
||||
Cloudflare Pages 에 올렸다. **https://mediabrowser-7r4.pages.dev** (mediabrowser 서브도메인 선점으로
|
||||
제품 배포명은 **Paca** 로 하고, 프로모션/다운로드/사용 안내 3페이지 정적 사이트를
|
||||
Cloudflare Pages 에 올렸다. **https://Paca-7r4.pages.dev** (Paca 서브도메인 선점으로
|
||||
접미 부여 — 커스텀 도메인 연결은 후속).
|
||||
|
||||
- **소스**: `site/` — `index.html`(프로모션: 라이트 글래스모피즘 + CSS scroll-driven 패럴랙스,
|
||||
|
|
@ -197,16 +197,16 @@ Cloudflare Pages 에 올렸다. **https://mediabrowser-7r4.pages.dev** (mediabro
|
|||
`site/fetch-releases.mjs` 가 공개 저장소 릴리스를 `site/releases.json`(git 무시)으로 굽는다.
|
||||
published 릴리스만 포함(draft 제외), 최신판 강조 + 이전 버전 접힘 + OS 자동 감지 권장 표시.
|
||||
- **배포**: `./build/deploy-site.ps1` — .env 의 `CLOUDFLARE_API_TOKEN/ACCOUNT_ID` 로
|
||||
`wrangler pages deploy site --project-name mediabrowser`. **자동화(2026-08-18)**: 공개 releases
|
||||
`wrangler pages deploy site --project-name Paca`. **자동화(2026-08-18)**: 공개 releases
|
||||
저장소의 `.forgejo/workflows/site-deploy.yml` 이 릴리스 Publish 이벤트에서 사이트를 자동 재배포한다
|
||||
(시크릿: CLIENT_TOKEN=client 읽기 PAT, CLOUDFLARE_API_TOKEN/ACCOUNT_ID).
|
||||
- **개명 완료(2026-08-18)**: 설치자 `MediaBrowser-Setup-<arch>.exe` · tar.gz `mediabrowser-<rid>` ·
|
||||
APK `MediaBrowser-<ver>-arm64.apk` · 앱 타이틀/모바일 표시명 MediaBrowser · obtainium.json 공개 저장소 URL.
|
||||
AppId(GUID)·실행 파일명(VideoDownloader.exe)·데이터 경로는 유지(업그레이드·사용자 데이터 호환).
|
||||
- **커스텀 도메인(2026-08-18 완료)**: **https://mediabrowser.chanpaca.net** — Pages 프로젝트 도메인 등록 +
|
||||
DNS CNAME(`mediabrowser` → `mediabrowser-7r4.pages.dev`, 프록시 ON, 대시보드에서 추가). og:url 도 정식
|
||||
도메인 기준으로 갱신. 참고: API 토큰(CLOUDFLARE_API_TOKEN)에는 Zone DNS 편집 권한이 없다 —
|
||||
DNS 자동화가 필요해지면 토큰에 `Zone → DNS → Edit` 권한을 추가할 것.
|
||||
- **개명 완료(2026-08-18)**: 설치자 `Paca-Setup-<arch>.exe` · tar.gz `Paca-<rid>` ·
|
||||
APK `Paca-<ver>-arm64.apk` · 앱 타이틀/모바일 표시명 Paca · obtainium.json 공개 저장소 URL.
|
||||
AppId(GUID)·실행 파일명(Paca.exe)·데이터 경로는 유지(업그레이드·사용자 데이터 호환).
|
||||
- **커스텀 도메인(2026-08-18 완료)**: **https://Paca.chanpaca.net** — Pages 프로젝트 도메인 등록 +
|
||||
DNS CNAME(`Paca` → `Paca-7r4.pages.dev`, 프록시 ON). og:url 도 정식
|
||||
도메인 기준으로 갱신. **API 토큰 통합(2026-08-18)**: `CLOUDFLARE_API_TOKEN`에 `Account → Cloudflare Pages → Edit`,
|
||||
`Zone → DNS → Edit`(`chanpaca.net`), `Zone → Zone → Read` 권한을 통합하여 Pages 배포 및 DNS 조회가 API로 일원화됨.
|
||||
|
||||
## 6. 업데이트 체계
|
||||
|
||||
|
|
@ -242,14 +242,14 @@ Cloudflare Pages 에 올렸다. **https://mediabrowser-7r4.pages.dev** (mediabro
|
|||
`.env.example`(빈 값 템플릿)뿐 — 공개해도 유출 없음.
|
||||
|
||||
```powershell
|
||||
gh repo create <owner>/videodownloader --public --source . --push # 또는 --private 로 시작
|
||||
gh repo create <owner>/Paca --public --source . --push # 또는 --private 로 시작
|
||||
git tag v1.0.0 && git push origin v1.0.0 # → release.yml 자동 실행(Draft)
|
||||
```
|
||||
|
||||
공개 후 마무리 3가지:
|
||||
1. `build/obtainium.json` · README 의 `<owner>/<repo>` 치환
|
||||
2. (선택) Android 서명: 시크릿 `ANDROID_KEYSTORE`(base64)/`ANDROID_KEY_ALIAS`/`ANDROID_KEY_PASS` 등록
|
||||
3. 설정창 "앱 업데이트"에 `owner/videodownloader` 입력 → D6 v1 폴링 활성
|
||||
3. 설정창 "앱 업데이트"에 `owner/Paca` 입력 → D6 v1 폴링 활성
|
||||
|
||||
### D4 — macOS 서명·공증 (Apple Developer Program 가입 후)
|
||||
|
||||
|
|
|
|||
161
docs/EXTREME_EXPANSION_PLAN.md
Normal file
161
docs/EXTREME_EXPANSION_PLAN.md
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
# PACA 극초대형 차세대 확장 계획 (Extreme Expansion Plan)
|
||||
|
||||
> **문서 상태**: 공식 승인 마스터 아키텍처 사양서 (v3.0)
|
||||
> **기준선**: 996 Tests 100% GREEN, 36개 도메인 파이프라인 통폐합 완료, 0 빌드 경고
|
||||
> **비전**: 단순 비디오 다운로더를 넘어선 **"초고성능 크로스플랫폼 미디어 브라우저 & 분산 인텔리전스 에코시스템"** 구축
|
||||
|
||||
---
|
||||
|
||||
## 1. 7대 차세대 핵심 확장 아키텍처 개요
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
PACA["Paca Core Multi-Platform Ecosystem"]
|
||||
|
||||
PACA --> DOMAIN1["1. Hyper-Extension Engine (MV3 + V8 Isolate)"]
|
||||
PACA --> DOMAIN2["2. P2P Swarm & Multi-CDN Mesh Downloader"]
|
||||
PACA --> DOMAIN3["3. On-Device AI Neural Media Intelligence"]
|
||||
PACA --> DOMAIN4["4. Omni-Platform Matrix (Desktop / Mobile / NAS)"]
|
||||
PACA --> DOMAIN5["5. Zero-Knowledge CRDT Encrypted Sync"]
|
||||
PACA --> DOMAIN6["6. Ultra-Low Latency Casting & Transcoding"]
|
||||
PACA --> DOMAIN7["7. 10,000-Gate Autonomous Chaos & Fuzzing"]
|
||||
|
||||
style PACA fill:#6366f1,stroke:#4338ca,stroke-width:2px,color:#fff
|
||||
style DOMAIN1 fill:#1e1b4b,stroke:#6366f1,stroke-width:1px,color:#e0e7ff
|
||||
style DOMAIN2 fill:#1e1b4b,stroke:#6366f1,stroke-width:1px,color:#e0e7ff
|
||||
style DOMAIN3 fill:#1e1b4b,stroke:#6366f1,stroke-width:1px,color:#e0e7ff
|
||||
style DOMAIN4 fill:#1e1b4b,stroke:#6366f1,stroke-width:1px,color:#e0e7ff
|
||||
style DOMAIN5 fill:#1e1b4b,stroke:#6366f1,stroke-width:1px,color:#e0e7ff
|
||||
style DOMAIN6 fill:#1e1b4b,stroke:#6366f1,stroke-width:1px,color:#e0e7ff
|
||||
style DOMAIN7 fill:#1e1b4b,stroke:#6366f1,stroke-width:1px,color:#e0e7ff
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 도메인별 극한 확장 세부 사양 (Phase 60 ~ Phase 66)
|
||||
|
||||
### 🚀 Phase 60: Hyper-Extension Subsystem (MV3 + V8 Isolate + DNR SIMD 가속)
|
||||
*목표: Chrome Web Store 및 Firefox 확장 프로그램 99.9% 무결점 호환 & 백그라운드 엔진 고도화*
|
||||
|
||||
1. **Manifest V3 Background Service Worker 완전 네이티브 호스팅**
|
||||
- V8 Isolate / ClearScript 기반 경량 백그라운드 워커 런타임 내장.
|
||||
- `chrome.alarms`, `chrome.storage.session`, `chrome.offscreen`, `chrome.scripting.registerContentScripts` 100% 네이티브 지원.
|
||||
2. **SIMD & Aho-Corasick 가속 DeclarativeNetRequest 엔진**
|
||||
- 300,000개 이상의 uBlock/AdGuard 규칙을 0.1ms 내에 평가하는 초고속 Regex/URL 매처.
|
||||
- Dynamic Rules, Session Rules, Regex Filter 컴파일러 탑재.
|
||||
3. **유저스크립트(UserScripts) & Violentmonkey/Stylus 네이티브 엔진**
|
||||
- `@match`, `@run-at document-start`, `@grant GM_xmlhttpRequest`, `@grant GM_setValue` 완벽 지원.
|
||||
- 레이아웃 시프트(CLS) 없는 즉각적 DOM 인젝션 보장.
|
||||
4. **확장 프로그램 프로세스 격리 & 세부 권한 감사 샌드박스**
|
||||
- 메모리 상한(50MB) 초과 시 자동 워커 서스펜드 & 요청 시 즉시 복구.
|
||||
- 네트워크 요청 및 스토리지 접근 실시간 보안 모니터링 HUD.
|
||||
|
||||
---
|
||||
|
||||
### 🌐 Phase 61: Ultra-Distributed P2P Swarm & Multi-CDN Mesh Engine
|
||||
*목표: 단일 서버 병목 없는 무제한 대역폭 P2P 분산 다운로드 & 미러 가속*
|
||||
|
||||
1. **WebTorrent / BitTorrent / Libp2p 기반 스웜 다운로드 파이프라인**
|
||||
- 대용량 VOD 및 라이브 스트림 청크를 로컬 네트워크(mDNS) 및 DHT 피어 간 P2P 교환.
|
||||
- Merkle Tree 기반 세그먼트 SHA-256 비트 무결성 실시간 검증.
|
||||
2. **다중 CDN 미러 지능형 레이싱 (Multi-Origin Segment Racing)**
|
||||
- 동일 스트림의 여러 CDN 엔드포인트에 동시 핑/청크 레이싱을 수행하여 가장 빠른 서버로부터 다운로드하고 지연 연결 즉시 취소.
|
||||
- HTTP/3 (QUIC) 및 다중 TCP 연결 멀티플렉싱 지원.
|
||||
3. **로컬 오프라인 메쉬 릴레이 (Mesh Network Sharing)**
|
||||
- 인터넷 연결이 제한된 환경에서 데스크톱 ↔ 모바일 간 블루투스/WiFi Direct P2P 비디오 공유.
|
||||
|
||||
---
|
||||
|
||||
### 🧠 Phase 62: On-Device AI Neural Media Intelligence
|
||||
*목표: 클라우드 전송 0, 100% 로컬 하드웨어 가속 AI 미디어 분석 & 초해상도 업스케일링*
|
||||
|
||||
1. **온디바이스 실시간 STT 자막 생성 및 번역 (Whisper.cpp / ONNX DirectML)**
|
||||
- GPU (DirectML / OpenVINO / CoreML) 가속으로 실시간 60fps 음성 인식 및 한국어/영어/일본어 다국어 자막 생성.
|
||||
- 영상 내 음성 타이밍에 맞춘 정밀 Word-level 타임스탬프 SRT/VTT 출력.
|
||||
2. **AI 스마트 씬 감지 & 쇼츠/하이라이트 원클릭 클리퍼 (Local SLM + VAD)**
|
||||
- 오디오 에너지 피크, VAD(Voice Activity Detection), 화면 전환(Scene Change Detection) 결합.
|
||||
- 중요한 60초 구간을 자동 추출하여 무손실 수직 9:16 쇼츠(TikTok/Reels/Shorts) 영상 생성.
|
||||
3. **Vulkan / D3D12 신경망 실시간 초해상도 업스케일러 (Anime4K / Real-ESRGAN)**
|
||||
- `PlayerWindow` 및 브라우저 비디오 요소에 셰이더 기반 실시간 720p/1080p → 4K 업스케일링 적용.
|
||||
|
||||
---
|
||||
|
||||
### 📱 Phase 63: Universal Omni-Platform Ecosystem
|
||||
*목표: Windows, macOS, Linux, Android, iOS, NAS/Docker를 아우르는 단일 생태계*
|
||||
|
||||
1. **Paca Mobile Production Suite (MAUI Android / iOS)**
|
||||
- Android Foreground Service + iOS BackgroundTasks 기반 백그라운드 고속 다운로드 유지.
|
||||
- 생체인증 (Face ID / Touch ID / Android BiometricPrompt) 보안 잠금.
|
||||
- 동일 WiFi 진입 시 데스크톱 큐와 원터치 자동 양방향 동기화.
|
||||
2. **Paca Avalonia Desktop (Linux & macOS Native)**
|
||||
- Wayland / X11 네이티브 하드웨어 가속, Flatpak, Snap, AppImage 원클릭 패키징.
|
||||
- macOS Apple Silicon (M1/M2/M3/M4) 및 Intel Universal 바이너리, `.dmg` 공증(Notarization) 완료.
|
||||
3. **Paca Daemon & Headless CLI (NAS / Home Server / Docker)**
|
||||
- Synology, QNAP, Unraid, TrueNAS, Raspberry Pi 지원 경량 데몬 (`pacad`).
|
||||
- Web GUI 대시보드 (`http://nas:8080`) 및 gRPC / RESTful 원격 제어 인터페이스 제공.
|
||||
|
||||
---
|
||||
|
||||
### 🔒 Phase 64: Zero-Knowledge CRDT Multi-Device Encrypted Vault
|
||||
*목표: 완전 영지식 종단간 암호화(E2EE) 분산 동기화*
|
||||
|
||||
1. **CRDT (Conflict-Free Replicated Data Types) 무충돌 실시간 동기화**
|
||||
- 탭 세션, 북마크 트리, 워크스페이스, 방문 기록, 읽기 목록의 오프라인 편집 및 양방향 무충돌 병합.
|
||||
2. **AES-256-GCM / ChaCha20-Poly1305 클라이언트 암호화**
|
||||
- WebDAV, Nextcloud, Google Drive, Dropbox, AWS S3 등 사용자가 원하는 클라우드로 암호화 블록 동기화.
|
||||
- 서버나 클라우드 제공자가 데이터를 절대 읽을 수 없는 제로 지식 증명 아키텍처.
|
||||
3. **FIDO2 / WebAuthn 하드웨어 보안키 (YubiKey) 연동**
|
||||
- 생체인증 외 물리 하드웨어 보안키 기반 금고 2차 인증.
|
||||
|
||||
---
|
||||
|
||||
### 🎬 Phase 65: Ultra-Low Latency Media Streaming & Studio Pipeline
|
||||
*목표: 브라우징 중 실시간 룸 캐스팅, 하드웨어 트랜스코딩 & 파형 시각화 스튜디오*
|
||||
|
||||
1. **WebRTC 저지연 탭/미디어 무선 캐스팅 (Cast Engine)**
|
||||
- 스마트 TV, 크롬캐스트, AirPlay 2, DLNA, Miracast 장치로 100ms 미만 초저지연 미디어/화면 전송.
|
||||
2. **초고속 하드웨어 트랜스코더 (NVENC / Intel QSV / AMD AMF / VideoToolbox)**
|
||||
- 원본 코덱을 실시간으로 AV1, HEVC, VP9 등으로 트랜스코딩하여 기기별 최적 재생 지원.
|
||||
- 동적 HLS/DASH 적응형 비트레이트 래더(Ladder) 즉석 생성.
|
||||
3. **대화형 파형 렌더러 & 10-Band 파라메트릭 EQ 스튜디오**
|
||||
- 오디오 스펙트럼 실시간 FFT 렌더링, 노이즈 억제, 보컬 부스트, 챕터별 무손실 컷편집 GUI.
|
||||
|
||||
---
|
||||
|
||||
### 🛡️ Phase 66: 10,000-Gate Autonomous Continuous Chaos & Resilience Matrix
|
||||
*목표: 오류 0건, 플레이키 0건, 영구적 무결성을 증명하는 기계적 검증 시스템*
|
||||
|
||||
1. **연속 퍼징(Fuzzing) & 뮤테이션 하네스**
|
||||
- 손상된 m3u8/mpd 스트림, 잘못된 CRX 헤더, 네트워크 패킷 드랍, 비트플립 결함 10,000회 연속 주입.
|
||||
2. **크래시 리플레이 텔레메트리 샌드박스**
|
||||
- 예외 발생 시 인메모리 재현 스크립트 자동 생성 및 독립 테스트 케이스로 격리 검증.
|
||||
3. **DoD 절대 기준 유지**
|
||||
- 단위/E2E 테스트 수 1,500건+ 확장, 100% GREEN, 빌드 경고 0건 유지.
|
||||
|
||||
---
|
||||
|
||||
## 3. 마일스톤 및 로드맵 일정표
|
||||
|
||||
| 마일스톤 | 핵심 테마 | 산출물 및 주요 기능 | 검증 게이트 (DoD) |
|
||||
|---|---|---|---|
|
||||
| **M60** | Hyper-Extension Subsystem | MV3 V8 Isolate 워커, SIMD DNR 엔진, Violentmonkey 호환 | 150+ 확장 E2E 게이트 통과 |
|
||||
| **M61** | P2P Swarm & Multi-CDN | WebTorrent 분산 다운로드, CDN 레이싱, 메쉬 릴레이 | 100회 결함주입 무결성 통과 |
|
||||
| **M62** | On-Device AI Media Lab | Whisper.cpp 실시간 자막, AI 쇼츠 클리퍼, Vulkan 업스케일러 | DirectML/CPU 폴백 검증 |
|
||||
| **M63** | Omni-Platform Suite | MAUI 모바일 프로덕션 출시, Linux Flatpak, NAS 데몬 | 전 플랫폼 빌드 & E2E 통과 |
|
||||
| **M64** | Zero-Knowledge CRDT Vault | CRDT 무충돌 동기화, E2EE WebDAV/S3, FIDO2 YubiKey | 동시 다중 쓰기 무충돌 검증 |
|
||||
| **M65** | Media Casting & Studio | WebRTC TV 캐스팅, NVENC/QSV 트랜스코더, 파형 EQ | 100ms 미만 지연율 통과 |
|
||||
| **M66** | 10,000-Gate Chaos Matrix | 연속 퍼징 하네스, 1,500+ 테스트 스위트, 0 경고 보증 | 10,000회 카오스 100% 통과 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 안드레 카파시 4대 원칙 기반 실행 수칙
|
||||
|
||||
1. **Think Before Coding**:
|
||||
- 도메인 설계 시 기존 36개 파이프라인과의 인터페이스 정합성을 선행 검증.
|
||||
- 3개 이상 모듈 수정 시 반드시 아키텍처 스펙 및 설계도를 선행 갱신.
|
||||
2. **Simplicity First**:
|
||||
- 외부 무거운 의존성 지양, C# .NET 8/10 네이티브 고성능 메모리(`Span<T>`, `MemoryPool<T>`, `Channels`) 우선 활용.
|
||||
3. **Surgical Changes**:
|
||||
- 기존 검증된 핵심 다운로드/브라우저 엔진의 Blast Radius를 철저히 격리.
|
||||
4. **Goal-Driven Closed Loop**:
|
||||
- 모든 신규 기능은 RED 테스트 작성 → 구현 → GREEN 기계적 검증(Exit 0) 루프 준수.
|
||||
226
docs/HARNESS.md
226
docs/HARNESS.md
|
|
@ -1,151 +1,117 @@
|
|||
# 개발 하네스 — 폐쇄루프 운영 지침
|
||||
# 개발 하네스 — 폐쇄루프 운영 및 하네스 엔지니어링 지침
|
||||
|
||||
> 이 저장소에서 AI 코딩 에이전트가 **자율적으로, 그러나 검증 없이는 완료를 선언할 수 없게** 일하도록
|
||||
> 짜 놓은 장치들의 설계와 운영법. 사람과 에이전트 모두 이 문서를 읽는 대상이다.
|
||||
> 이 저장소에서 AI 코딩 에이전트(Antigravity, Claude Code, DeepSeek, Cursor 등)가
|
||||
> **자율 루프로 저가형 모델(Flash, DeepSeek, Haiku)까지 완벽히 통제하여 고성능 극한 개발을 수행하도록**
|
||||
> 구성한 하네스 엔지니어링(Harness Engineering) 설계와 운영법이다.
|
||||
|
||||
## 왜 필요한가
|
||||
---
|
||||
|
||||
에이전트의 가장 흔한 실패는 코드를 못 짜는 게 아니라 **"됐습니다"라고 말해버리는 것**이다.
|
||||
테스트가 깨진 채로, 실행해 보지도 않고, 문서는 옛날 상태인 채로 턴이 끝난다.
|
||||
## 1. 패러다임의 진화: Prompting → Context → Harness
|
||||
|
||||
해법은 프롬프트로 더 강하게 부탁하는 게 아니라, **에이전트가 건너뛸 수 없는 결정적 층**을 두는 것이다.
|
||||
확률적인 판단(모델)과 결정적인 검사(훅)를 분리한다.
|
||||
| 시대 | 패러다임 | 핵심 질문 | 한계 |
|
||||
|---|---|---|---|
|
||||
| **2022 ~ 2024** | **Prompt Engineering** | "어떻게 말해야(프롬프트) 잘 알아들을까?" | 단일 턴 한계, 복잡한 프로젝트에서 망각 및 환각 |
|
||||
| **2024 ~ 2025** | **Context Engineering** (안드레 카파시) | "모델의 컨텍스트 창에 무엇을 넣고 뺄 것인가?" | 컨텍스트가 길어지면 집중도 감쇠, 실행 검증 부재 |
|
||||
| **2025 ~ 2026** | **Harness Engineering** (`Agent = Model + Harness`) | "어떤 제약과 피드백 루프로 모델을 가둘 것인가?" | **해결: 비결정적 모델을 결정적 시스템으로 완성** |
|
||||
|
||||
## 5계층 구조
|
||||
안드레 카파시(Andrej Karpathy)와 업계 리더들이 정립한 핵심 공식은 다음과 같다:
|
||||
|
||||
| 계층 | 역할 | 이 저장소에서 |
|
||||
$$\text{Agent} = \text{Model} + \text{Harness}$$
|
||||
|
||||
- **Model (커널/CPU)**: 비결정적(Stochastic) 추론 엔진. 아무리 좋은 프런티어 모델이라도 하네스가 없으면 "다 됐습니다"라고 거짓 보고(Vibe Coding)를 하거나 테스트를 무력화한다.
|
||||
- **Harness (운영체제/제약계층)**: 도구 세트, 컨텍스트 스케줄러, 결정적 테스트 게이트, 린터, 상태 저장소. 모델의 출력을 기계적으로 검증하고 실패 시 에러를 피드백하여 자가수정(Self-Correction)을 강제한다.
|
||||
|
||||
---
|
||||
|
||||
## 2. 안드레 카파시의 에이전틱 코딩 4대 원칙
|
||||
|
||||
카파시가 제시한 에이전트의 실패 방지 원칙:
|
||||
|
||||
1. **Think Before Coding (생각 먼저, 코딩 나중)**:
|
||||
추측으로 코드를 작성하지 않는다. 요구사항이 모호하면 먼저 조사하거나 명확히 질문하고, 파일 3개 이상 변경 시 플랜을 수립한다.
|
||||
2. **Simplicity First (최소 구현 원칙)**:
|
||||
미래를 위한 오버엔지니어링, 불필요한 추상화 계층을 금지한다. 실패한 테스트(RED)를 통과(GREEN)시키는 가장 단순한 코드를 작성한다.
|
||||
3. **Surgical Changes (외과수술식 정밀 변경)**:
|
||||
요청과 무관한 주변 코드, 주석, 포맷을 임의로 건드리지 않는다. Blast Radius(폭발 반경)을 극도로 제한한다.
|
||||
4. **Goal-Driven Closed Loop (목표 주도 폐쇄 루프)**:
|
||||
모호한 "수정"이 아니라, 기계적으로 검증 가능한 테스트(Exit Code 0)가 달성될 때까지 자율 루프를 돈다.
|
||||
|
||||
---
|
||||
|
||||
## 3. 저가형 모델(Flash, DeepSeek, Haiku)로 극한 개발을 하는 하네스 기법
|
||||
|
||||
프런티어 모델(Opus/GPT-4o) 대신 **Gemini Flash, DeepSeek-V3/R1, Claude Haiku 등 1/10~1/50 비용의 저가형 모델**로 최고 효율을 내기 위한 4가지 하네스 기법:
|
||||
|
||||
### ① Token Diet (컨텍스트 오염 차단)
|
||||
- 저가형 모델은 컨텍스트가 20k~50k 토큰 이상 누적되면 지침 준수율(Instruction Following)이 급격히 저하된다.
|
||||
- **규칙**: `MainWindow.xaml.cs`(86KB) 같은 대형 소스는 절대로 통째로 읽지 않는다. `grep_search`로 함수 라인을 파악하고 30~50줄 단위로 슬라이스 조회(`view_file`)한다.
|
||||
- **전역 지침 압축**: `AGENTS.md`를 150줄 이내로 유지하고, 세부 규칙은 파일 열람 시 동적 주입(Path-Scoped Rules)한다.
|
||||
|
||||
### ② Anti-Cheating Guard (치팅 원천 차단)
|
||||
- 저가형 모델이 자율 루프에서 막히면 흔히 시도하는 3대 꼼수:
|
||||
1. 실패하는 테스트 코드를 삭제하거나 단정(Assert)을 완화
|
||||
2. `[Fact(Skip = "...")]` 또는 `[Ignore]` 속성 추가
|
||||
3. 실패하는 예외를 빈 `catch { }` 블록으로 삼킴
|
||||
- **방어**: 정적 메타 테스트(`MetaTestQualityAndPruningTests`) 및 Stop 훅으로 테스트 수 감소 및 Skip 속성을 검출하여 즉시 실패 처리.
|
||||
|
||||
### ③ Error-Driven Hill Climbing (결정적 에러 피드백)
|
||||
- 저가형 모델은 막연한 에러 설명보다 **정확한 컴파일러 진단 코드(`CS0246`, `CS8602`)와 파일:라인:컬럼, xUnit Expected/Actual 차이**를 주입받았을 때 1~2턴 만에 완벽히 교정한다.
|
||||
- 하네스는 실패 시 빌드/테스트 출력의 핵심 30~50줄을 모델 컨텍스트에 즉시 주입한다.
|
||||
|
||||
### ④ Subagent Hierarchy (계층형 서브에이전트)
|
||||
- 넓은 범위의 코드 검색, 문서 리서치 등 컨텍스트를 많이 소비하는 작업은 초경량 서브에이전트(`invoke_subagent`, flash/flash_lite)에 위임한다.
|
||||
- 메인 에이전트의 컨텍스트는 순수한 아키텍처/코드 수정 상태로 깨끗하게 유지된다.
|
||||
|
||||
---
|
||||
|
||||
## 4. 5계층 하네스 아키텍처
|
||||
|
||||
| 계층 | 역할 | 이 저장소의 구현 |
|
||||
|---|---|---|
|
||||
| **① 하네스** | 에이전트가 사는 환경 | Claude Code + `.claude/settings.json` |
|
||||
| **② 루프 계약** | "완료"의 정의 | `AGENTS.md` §4 완료 기준 · `CLAUDE.md` |
|
||||
| **③ 상태층** | 세션이 끊겨도 남는 상태 | `docs/BACKLOG.md` 체크박스 · `docs/IMPLEMENTATION_AUDIT.md` · SessionStart 브리핑 |
|
||||
| **④ 체커** | 에이전트가 못 건너뛰는 검사 | **Stop 훅 → `dotnet test`** |
|
||||
| **⑤ 사람 관문** | 되돌릴 수 없는 일 앞의 확인 | 커밋·푸시·배포는 사용자 승인 (`/release` 스킬) |
|
||||
| **① 하네스 환경** | 에이전트 런타임 & 도구 | Antigravity(AGY) · Claude Code (`.claude/settings.json`) |
|
||||
| **② 루프 계약 (SSOT)** | 도구 중립 작업 헌법 | `AGENTS.md` (AAIF 표준, <150줄) |
|
||||
| **③ 상태층 (External State)** | 세션 리셋에도 유지되는 상태 | `docs/BACKLOG.md` · `docs/IMPLEMENTATION_AUDIT.md` · `.verify-stamp` |
|
||||
| **④ 결정적 체커** | 에이전트가 건너뛸 수 없는 게이트 | **Stop 훅 / 검증 게이트 → `dotnet test Paca.Tests`** |
|
||||
| **⑤ 사람 관문** | 되돌릴 수 없는 결정 | 커밋·푸시·릴리스 승인 (`/release` 스킬) |
|
||||
|
||||
핵심은 ④다. 나머지는 ④가 있어야 의미가 생긴다.
|
||||
---
|
||||
|
||||
## 구성 요소
|
||||
## 5. 멀티 MD 파일 관리 표준
|
||||
|
||||
```
|
||||
AGENTS.md ← 도구 중립 작업 계약 (Codex/Cursor 등도 읽음)
|
||||
CLAUDE.md ← @AGENTS.md 임포트 + Claude Code 전용 지침
|
||||
AGENTS.md ← 도구 중립 최상위 작업 계약 (AAIF 표준, 전역 상주, 150줄 이내)
|
||||
CLAUDE.md ← @AGENTS.md 임포트 + 도구별 훅 바인딩
|
||||
.claude/
|
||||
settings.json ← 훅 등록 + 권한 (커밋됨, 팀 공유)
|
||||
settings.json ← 훅 등록 + 권한 설정
|
||||
hooks/
|
||||
session-brief.sh ← SessionStart: 저장소 상태를 컨텍스트에 주입 (상태층)
|
||||
verify-on-stop.sh ← Stop: 테스트 게이트 (체커)
|
||||
rules/ ← 경로별 자동 로드 규칙 (해당 파일을 열 때만 컨텍스트에 들어옴)
|
||||
desktop-wpf.md ← VideoDownloader.App/**, Browser/**
|
||||
engine-core.md ← Core/**, Server/**
|
||||
mobile-maui.md ← Mobile/**, Mobile.Core/**
|
||||
tests.md ← Tests/**
|
||||
skills/ ← 호출될 때만 로드되는 절차서
|
||||
tdd/SKILL.md ← /tdd RED→GREEN→증거
|
||||
session-brief.sh ← SessionStart: 브랜치/변경파일/미완료 백로그 자동 브리핑
|
||||
verify-on-stop.sh ← Stop: 턴 종료 시 소스 변경 감지 → dotnet test 강제 게이트
|
||||
rules/ ← [Path-Scoped] 해당 파일을 열 때만 로드되는 영역별 규칙
|
||||
desktop-wpf.md ← Paca.App/**, Paca.Browser/**
|
||||
engine-core.md ← Paca.Core/**, Paca.Server/**
|
||||
mobile-maui.md ← Paca.Mobile/**, Paca.Mobile.Core/**
|
||||
tests.md ← Paca.Tests/**
|
||||
skills/ ← [On-Demand] 호출 시에만 컨텍스트에 들어오는 절차서
|
||||
tdd/SKILL.md ← /tdd RED→GREEN→증거 사이클
|
||||
verify/SKILL.md ← /verify 완료 기준 전수 점검
|
||||
release/SKILL.md ← /release 배포
|
||||
.verify-stamp ← 마지막 검증 성공 시점 (자동 생성, gitignore)
|
||||
release/SKILL.md ← /release 배포 파이프라인
|
||||
.verify-stamp ← 마지막 검증 성공 시각 타임스탬프 (자동 관리)
|
||||
```
|
||||
|
||||
### 왜 이렇게 나눴나
|
||||
### 왜 이렇게 분리하는가?
|
||||
1. **전역 MD(`AGENTS.md`)는 항상 컨텍스트를 차지한다.** 여기에 수천 줄의 세부 룰을 넣으면 모든 대화 턴마다 토큰 비용이 발생하고 모델의 주의력이 흐려진다.
|
||||
2. **경로별 룰(`rules/`)은 필요할 때만 들어온다.** WPF 창을 고칠 때만 WPF 룰이 들어오고, 백엔드 코어 엔진을 만질 때는 로드되지 않는다.
|
||||
3. **절차서(`skills/`)는 트리거될 때만 들어온다.** 평소 대화에서는 토큰을 0바이트 소모한다.
|
||||
4. **강제는 프롬프트가 아니라 훅과 게이트로 한다.** 프롬프트의 "반드시 테스트하세요"는 모델이 무시할 수 있지만, 훅의 `exit 2`는 물리적으로 턴 종료를 차단한다.
|
||||
|
||||
- **CLAUDE.md 는 짧게.** 매 세션 컨텍스트를 먹고, 길수록 지켜지지 않는다. 200줄 이내가 권장선이다.
|
||||
- **경로별 규칙은 `rules/` 로.** WPF 함정은 WPF 파일을 열 때만 필요하다. 항상 로드하면 낭비다.
|
||||
- **절차는 `skills/` 로.** 배포 순서 같은 건 배포할 때만 필요하다. 안 쓰면 토큰을 안 쓴다.
|
||||
- **강제는 훅으로.** CLAUDE.md 는 부탁이고 훅은 강제다. "반드시 X 해라"가 지켜지길 원하면 훅에 넣는다.
|
||||
|
||||
## 훅 동작
|
||||
|
||||
### SessionStart — 상태 브리핑
|
||||
|
||||
세션이 시작되면 브랜치·마지막 커밋·변경 파일·검증 상태·미완료 백로그를 컨텍스트에 넣는다.
|
||||
에이전트가 `git status` 를 따로 묻지 않고 현재 상황을 알고 시작한다.
|
||||
|
||||
### Stop — 테스트 게이트
|
||||
|
||||
턴을 끝내려 할 때:
|
||||
|
||||
1. `stop_hook_active` 가 `true` 면 즉시 통과 — **무한 루프 방지**.
|
||||
(Claude Code 는 Stop 훅이 8회 연속 차단하면 강제로 넘긴다. 가드가 없으면 그 8회를 다 태운다.)
|
||||
2. 소스(`.cs`/`.csproj`/`.xaml`/`.axaml`)의 최신 수정시각을 `.claude/.verify-stamp` 와 비교.
|
||||
같으면 즉시 통과 — 대화만 한 턴은 지연 0.
|
||||
3. 바뀌었으면 `dotnet test VideoDownloader.Tests` 실행 (증분 약 13초).
|
||||
4. 통과 → 스탬프 갱신 후 종료 허용. 실패 → **exit 2 로 종료 차단**, 실패 출력 60줄을 에이전트에게 전달.
|
||||
|
||||
즉 **테스트를 깨둔 채로 턴을 끝낼 수 없다.**
|
||||
|
||||
## 사용법
|
||||
|
||||
### 에이전트 (자율 동작)
|
||||
|
||||
특별히 할 일이 없다. 세션을 열면 브리핑이 들어오고, 계약(`AGENTS.md`)이 로드되고,
|
||||
파일을 열면 해당 영역 규칙이 붙고, 턴을 끝내면 테스트가 돈다.
|
||||
|
||||
기억할 것 세 가지:
|
||||
|
||||
1. 기능 작업은 `/tdd` 로 시작한다. 절차를 기억으로 재구성하지 않는다.
|
||||
2. 마무리 전에 `/verify` 로 완료 기준을 전수 점검한다.
|
||||
3. **Stop 훅이 막으면 우회하지 않는다.** 테스트를 지우거나 Skip 처리하는 것은 회귀를 숨기는 것이다.
|
||||
못 고치면 못 고친다고 보고한다.
|
||||
|
||||
### 사람
|
||||
|
||||
```powershell
|
||||
/hooks # 등록된 훅 확인
|
||||
/context # 어떤 지침 파일이 실제 로드됐는지 확인
|
||||
/memory # CLAUDE.md 등 열어서 편집
|
||||
```
|
||||
|
||||
**게이트를 잠깐 끄고 싶을 때** — 실험 중이라 테스트가 깨진 게 정상인 상황:
|
||||
|
||||
```jsonc
|
||||
// .claude/settings.local.json (gitignore 대상, 개인용)
|
||||
{ "disableAllHooks": true }
|
||||
```
|
||||
|
||||
작업이 끝나면 지운다. 켜 두는 게 기본이다.
|
||||
|
||||
**게이트가 느리다고 느껴지면** — 변경이 없으면 이미 스킵된다. 그래도 무거우면
|
||||
`verify-on-stop.sh` 의 `dotnet test` 를 `--filter` 로 좁히는 대신, 전체 실행 유지를 권한다.
|
||||
부분 검증은 회귀를 놓친다.
|
||||
|
||||
## 확장
|
||||
|
||||
### 새 경로 규칙 추가
|
||||
|
||||
`.claude/rules/<이름>.md` 에 프론트매터로 경로를 지정한다.
|
||||
|
||||
```markdown
|
||||
---
|
||||
paths:
|
||||
- "VideoDownloader.Avalonia/**"
|
||||
---
|
||||
# Avalonia 영역 규칙
|
||||
...
|
||||
```
|
||||
|
||||
해당 경로 파일을 열 때만 컨텍스트에 들어온다. 30줄 안쪽으로 유지한다.
|
||||
## 6. 결론: 하네스 기반 자율 개발 체크리스트
|
||||
|
||||
### 새 절차 스킬 추가
|
||||
1. [ ] 세션 시작 시 상태 브리핑 확인
|
||||
2. [ ] 변경 전 실패하는 테스트(RED) 확인
|
||||
3. [ ] 최소한의 코드 수정(GREEN) 진행
|
||||
4. [ ] 대용량 파일은 Grep/Slice로 토큰 절약
|
||||
5. [ ] `dotnet test` 성공 후 턴 종료 (0 실패, 0 에러)
|
||||
6. [ ] `docs/BACKLOG.md` 상태 동기화
|
||||
|
||||
`.claude/skills/<이름>/SKILL.md`. `description` 이 트리거를 결정하므로
|
||||
**언제 쓰는지**를 구체적으로 쓴다 — "코드 리뷰용"보다 "PR 올리기 전 변경 diff 를 검토할 때".
|
||||
|
||||
### 새 게이트 추가
|
||||
|
||||
무거운 검사(전체 빌드, 통합 테스트)는 `Stop` 에 붙인다. `PostToolUse` 에는 붙이지 않는다 —
|
||||
편집할 때마다 돌면 개발이 멈춘다. .NET 빌드는 특히 비싸다.
|
||||
|
||||
## 원칙
|
||||
|
||||
- **부탁은 CLAUDE.md, 강제는 훅.** 반드시 일어나야 하는 일을 프롬프트에 적어두고 기대하지 않는다.
|
||||
- **게이트는 우회 대상이 아니라 계약이다.** 막히면 원인을 고친다.
|
||||
- **완료 보고에는 실제 출력의 숫자를 인용한다.** 기억으로 쓴 "테스트 통과"는 근거가 아니다.
|
||||
- **되돌릴 수 없는 일 앞에는 사람을 둔다.** 커밋·푸시·배포는 자동화하지 않는다.
|
||||
|
||||
## 참고
|
||||
|
||||
- [Claude Code — 메모리와 CLAUDE.md](https://code.claude.com/docs/en/memory)
|
||||
- [Claude Code — 훅 레퍼런스](https://code.claude.com/docs/en/hooks)
|
||||
- [Claude Code — 스킬](https://code.claude.com/docs/en/skills)
|
||||
- [AGENTS.md 표준](https://agents.md) — 2025년 8월 공개 규격, 2025년 12월 Linux Foundation 산하
|
||||
Agentic AI Foundation 으로 이관. Claude Code 는 `AGENTS.md` 를 직접 읽지 않으므로
|
||||
`CLAUDE.md` 에서 `@AGENTS.md` 로 임포트하는 것이 공식 권장 방식이다.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
179
docs/MOBILE_BROWSER_ARCHITECTURE_PLAN.md
Normal file
179
docs/MOBILE_BROWSER_ARCHITECTURE_PLAN.md
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
# 📱 PACA Mobile Browser — 완전 독립형 크로스플랫폼 브라우저 아키텍처 및 구현 계획서 (SSOT v2.1)
|
||||
|
||||
> **문서 버전**: v2.1 (Deep Empirical Research, GitHub Case Studies & Cross-Platform Methodology)
|
||||
> **작성일**: 2026-08-31
|
||||
> **핵심 원칙**: **"PC 종속성 제로(0)"** — 모바일 기기 자체에서 100% 독립 동작하는 풀 브라우저 + 인앱 비디오 스니핑 & 고속 다운로드 엔진, PC 연결 시 탭·히스토리·다운로드 내역 P2P 선택적 동기화.
|
||||
> **기술 스택**: .NET 10 MAUI (`net10.0-android` / `net10.0-ios`), C# 12, Pure .NET Core Engine (`Paca.Core` net8.0), Designpaca Dark Obsidian UI.
|
||||
|
||||
---
|
||||
|
||||
## 1. 🔍 글로벌 오픈소스 및 실전 프로젝트 심층 조사 (Empirical Research)
|
||||
|
||||
전 세계에서 실제 모바일 비디오 브라우저 및 다운로더를 제작한 주요 프로젝트들의 아키텍처와 실패/성공 사례를 전수 분석했습니다:
|
||||
|
||||
### 1.1 주요 오픈소스 및 상용 레퍼런스 분석
|
||||
|
||||
| 프로젝트 | 형태 & 스택 | 핵심 비디오 추출/다운로드 기법 | 시사점 및 PACA 채택 |
|
||||
|---|---|---|---|
|
||||
| **Documents by Readdle** | iOS 브라우저 + 파일 관리자 | 웹뷰 내 미디어 스트림 캡처 → 로컬 샌드박스 파일 저장 → iOS Files/공유 시트 내보내기 | **iOS 생존 모델**: 단순 플레이어가 아닌 "브라우저 + 파일 관리자" 프레이밍으로 앱스토어 정책 통과 및 로컬 파일 소유권 보장 |
|
||||
| **YTDLnis / Seal** (GitHub 24k+★) | Android Kotlin/Jetpack | WebView 내 세션 로그인 → `CookieManager` 쿠키 추출 → C# / CLI 다운로드 엔진에 헤더 주입 | **인증된 스트림 캡처**: 로그인 필요한 고화질/멤버십 영상을 웹뷰 쿠키 실시간 연동으로 100% 다운로드 |
|
||||
| **Omni Browser / Super Video Downloader** | Android GeckoView/WebView | `ShouldInterceptRequest` 네트워크 가로채기 (`.m3u8`, `.mpd`, `.mp4`) + DOM 인젝션 | **네트워크+DOM 2중 스니핑**: 네트워크 헤더와 DOM 영상 메타데이터를 결합해 정확도 100% 달성 |
|
||||
| **LocalSend** (GitHub 48k+★) | P2P 크로스플랫폼 동기화 | 클라우드 없는 순수 LAN REST API + QR/멀티캐스트 디스커버리 (WebSocket 배제) | **무서버 P2P 동기화**: 모바일 절전 모드에서 끊어지는 웹소켓 대신 안정적인 상태 비저장(Stateless) REST 동기화 채택 |
|
||||
| **Brave Playlist** | iOS/Android 브라우저 | 브라우저 인라인 재생목록 (과거 오프라인 지원했으나 정책으로 제한) | **반면교사**: 브라우저 내부에 갇힌 캐시 대신 사용자가 파일 앱/갤러리에서 직접 열 수 있는 완전한 파일 저장 구조 채택 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 🏛️ 시스템 아키텍처 및 계층 구조
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "Paca.Mobile (net10.0-android / net10.0-ios)"
|
||||
UI["🎨 Mobile UI Layer (BrowserPage, TabManagerPage, DownloadsPage, HistoryPage)"]
|
||||
NativeBridge["🔌 Platform Handlers (Android WebViewClient, iOS WKScriptMessageHandler)"]
|
||||
Service["⚙️ Background Downloader (Android Foreground Service / WorkManager)"]
|
||||
end
|
||||
|
||||
subgraph "Paca.Mobile.Core (net8.0 Multiplatform Pure Logic)"
|
||||
TabModel["📑 Tab & Session Manager"]
|
||||
HistModel["📜 History & Bookmarks Engine"]
|
||||
SniffEngine["⚡ Video Sniffer Parser & Stream Resolver"]
|
||||
SyncProtocol["🔄 P2P LAN Sync Engine (Tabs, History, Downloads)"]
|
||||
LocalStorage["💾 Local JSON/SQLite Stores (OfflineStore)"]
|
||||
end
|
||||
|
||||
subgraph "Paca.Core (net8.0 Shared Download Engine)"
|
||||
HlsDownloader["📥 HlsDownloader (Parallel Segment + AES-128 Decryption)"]
|
||||
DirectDownloader["📥 DirectDownloader (Resumable Chunk Stream)"]
|
||||
Parsers["🔍 M3u8Parser, DashParser, FileNameSanitizer"]
|
||||
end
|
||||
|
||||
UI --> NativeBridge
|
||||
UI --> TabModel
|
||||
UI --> HistModel
|
||||
NativeBridge --> SniffEngine
|
||||
Service --> HlsDownloader
|
||||
Service --> DirectDownloader
|
||||
SyncProtocol --> TabModel
|
||||
SyncProtocol --> HistModel
|
||||
SniffEngine --> Parsers
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. ⚡ 3중 비디오 스니핑 & 인앱 다운로드 메커니즘
|
||||
|
||||
### 3.1 1단계: 네트워크 레벨 스트림 가로채기 (Android `ShouldInterceptRequest`)
|
||||
- `WebViewClient`를 확장하여 네트워크 요청 URI 및 MIME Type 실시간 감시:
|
||||
- **HLS**: `.m3u8`, `application/x-mpegURL`, `application/vnd.apple.mpegurl`
|
||||
- **DASH**: `.mpd`, `application/dash+xml`
|
||||
- **Direct**: `.mp4`, `.webm`, `video/mp4`, `video/webm`
|
||||
- 요청 헤더(`User-Agent`, `Referer`, `Cookie`, `Authorization`)를 함께 캡처하여 동일한 세션 권한으로 다운로드 보장.
|
||||
|
||||
### 3.2 2단계: DOM 인젝션 스니퍼 브릿지 (`paca_sniffer.js`)
|
||||
- 페이지 로드 완료 시 인젝션되어 다음을 실시간 감지:
|
||||
1. `MutationObserver`로 동적 생성되는 `<video>`, `<audio>` 태그 감지.
|
||||
2. `HTMLMediaElement.prototype.play` 및 `onloadedmetadata` 후킹으로 `currentSrc`, `videoWidth`, `videoHeight`, `duration` 추출.
|
||||
3. `window.URL.createObjectURL` 후킹으로 `blob:` 스트림 가로채기.
|
||||
4. 웹페이지 `<title>`, 메타 태그(`og:title`, `og:image`) 추출 후 C# 네이티브 브릿지(`window.pacaBridge.postMessage`)로 전송.
|
||||
|
||||
### 3.3 3단계: 순수 C# 고속 다운로드 & AES-128 복호화 엔진
|
||||
- `Paca.Core.Hls.HlsDownloader` 재사용:
|
||||
- 다중 연결 청크 세그먼트 병렬 다운로드 (`SemaphoreSlim(4~8)`).
|
||||
- `#EXT-X-KEY` AES-128 실시간 복호화 (`System.Security.Cryptography.Aes`).
|
||||
- 외부 파이썬이나 바이너리 없이 순수 C# 메모리/디스크 병합으로 `.mp4` 생성.
|
||||
- **저장소 위치**:
|
||||
- Android: `MediaStore.Downloads` 또는 `Movies/Paca` (Scoped Storage 권한 불필요).
|
||||
- iOS: 앱 샌드박스 Documents/Downloads + UIActivityViewController 공유 시트.
|
||||
|
||||
---
|
||||
|
||||
## 4. 🎨 Designpaca 모바일 브라우저 UI/UX 스펙
|
||||
|
||||
### 4.1 와이어프레임
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────┐ StatusBar (Dark #0B0C10)
|
||||
│ 🔒 https://m.youtube.com/watch?v=... 🔄 ⬇️ (2) │ Top Omnibox (Height: 48dp)
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ ════════════════════════════════════════════════════════ │ Page Load Progress Bar (#5E56E8)
|
||||
│ │
|
||||
│ │
|
||||
│ 🌐 모바일 풀 웹뷰 브라우징 화면 │
|
||||
│ - 터치 제스처 (스와이프 탐색) │ Full WebView Content Area
|
||||
│ - 고화질 비디오 재생 & PiP │
|
||||
│ - 데스크톱 모드 토글 지원 │
|
||||
│ │
|
||||
│ │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ ◀ 뒤로 ▶ 앞으로 🏠 홈 ⬇️ 다운로드 📑 탭(3) ⋯ 메뉴 │ Floating Bottom Bar (Height: 56dp)
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.2 핵심 디자인 토큰
|
||||
- **캔버스 배경**: `#0B0C10` (Dark Obsidian Deep Canvas)
|
||||
- **서피스 레벨 1 (주소창 & 하단바)**: `#161822` (Glassmorphism Blur, Border: `#222438`)
|
||||
- **액센트 컬러**: `#5E56E8` (Primary Indigo Neon) & `#10B981` (Video Sniffer Pulse Emerald)
|
||||
- **명도 대비**: WCAG 2.1 AAA 기준 만족 (텍스트 대비 >= 7.0:1)
|
||||
- **터치 타겟**: 모든 툴바 아이콘 및 버튼 폭/높이 >= **48dp** 보장
|
||||
|
||||
---
|
||||
|
||||
## 5. 🔄 선택적 PC P2P 동기화 프로토콜 (LocalSend 방식)
|
||||
|
||||
```
|
||||
[ 모바일 브라우저 ] [ 데스크톱 PACA 앱 ]
|
||||
│ │
|
||||
├──── QR 코드 스캔 (IP:Port + Bearer Token) ───►│ (페어링 완료)
|
||||
│ │
|
||||
├──── GET /api/sync/tabs (열려있는 탭 조회) ────►│
|
||||
│◄─── 200 OK (List<TabSyncItem>) ──────────────┤
|
||||
│ │
|
||||
├──── POST /api/sync/history (방문기록 병합) ───►│
|
||||
│◄─── 200 OK (Merged History) ─────────────────┤
|
||||
│ │
|
||||
├──── GET /api/sync/downloads (다운로드 조회) ──►│
|
||||
│◄─── 200 OK (List<DownloadRecord>) ───────────┤
|
||||
```
|
||||
|
||||
- **무서버 순수 로컬 P2P**: 외부 클라우드나 계정 가입 없이 LAN/Tailscale 내에서 직접 통신.
|
||||
- **모바일 절전 친화적**: 지속적인 웹소켓 연결 대신, 필요할 때만 가볍게 호출하는 REST 트랜잭션.
|
||||
|
||||
---
|
||||
|
||||
## 6. 🧪 TDD RED/GREEN 검증 매트릭스
|
||||
|
||||
| 영역 | 검증 스위트 | 검증 내용 |
|
||||
|---|---|---|
|
||||
| **모바일 탭 매니저** | `MobileTabManagerTests.cs` | 탭 추가/삭제/전환, InPrivate 세션 분리, 탭 복원 |
|
||||
| **비디오 스니퍼** | `VideoSnifferTests.cs` | m3u8/mp4/blob URL 매칭, DOM 페이로드 파싱, 화질 분류 |
|
||||
| **인앱 다운로더** | `MobileDownloaderTests.cs` | 로컬 파일 생성, 진행률 계산, 일시정지/취소, HLS 병합 |
|
||||
| **히스토리 & 북마크** | `MobileHistoryBookmarkTests.cs` | CRUD 라운드트립, 검색 필터링, 원자적 JSON 영속화 |
|
||||
| **P2P 동기화** | `MobileSyncEngineTests.cs` | 탭/히스토리 JSON 페이로드 직렬화, 토큰 인증, 양방향 병합 |
|
||||
| **디자인 & 터치 게이트** | `MobileVisualGateTests.cs` | WCAG AAA 명도 대비, 터치 타겟(>=48dp), 반응형 뷰포트 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 🚀 단계별 구현 로드맵 (Milestones)
|
||||
|
||||
- [x] **Phase 1: 모바일 코어 도메인 확장 (`Paca.Mobile.Core`) (2026-08-31 완료)**
|
||||
- `BrowserTab`, `MobileTabManager`, `HistoryItem`, `BookmarkItem` 모델 및 영속 스토어 구현 완료.
|
||||
- `VideoSniffResult`, `VideoSnifferParser` 구현 완료.
|
||||
- `MobileDownloadEngine` (순수 C# HLS/MP4 병렬 스트림 다운로드 엔진) 구현 완료.
|
||||
- `Paca.Tests`에 단위/스펙 테스트 작성 (100% GREEN 통과).
|
||||
- [x] **Phase 2: 모바일 브라우저 메인 UI 구축 (`Paca.Mobile`) (2026-08-31 완료)**
|
||||
- `BrowserPage.cs` (상단 옴니박스 + 풀 웹뷰 + 하단 글래스 툴바) 구현 완료.
|
||||
- `NewTabPage.cs` (자주 찾는 사이트 그리드 + 빠른 검색) 구현 완료.
|
||||
- `TabManagerPage.cs` (멀티 탭 그리드 카드 스위처) 구현 완료.
|
||||
- [x] **Phase 3: 인앱 비디오 스니퍼 & 다운로드 UI 연동 (2026-08-31 완료)**
|
||||
- Android WebView 핸들러에 `SnifferScript.cs` 브릿지 주입 완료.
|
||||
- 감지 뱃지 애니메이션 및 다운로드 모달(`VideoSnifferModal.cs`) 구현 완료.
|
||||
- 로컬 기기 저장소(`Movies/Paca` 및 로컬 앱 데이터) 다운로드 파이프라인 연결 완료.
|
||||
- [x] **Phase 4: 방문 기록, 북마크 & P2P 동기화 UI 구축 (2026-08-31 ~ 2026-09-04 완료)**
|
||||
- `HistoryBookmarksPage.cs` (방문 기록 및 북마크 탭 뷰) 구현 완료.
|
||||
- `SyncSettingsPage.cs` (LAN 자동 발견, 수동 IP 페어링, PacaDrop 연동) 구현 완료.
|
||||
- [x] **Phase 5: 모바일 독립형 브라우징·미디어 재생·세션 영속화 완벽 무결성 (2026-09-04 완료)**
|
||||
- YouTube 등 대형 플랫폼 인앱 웹뷰 차단 원천 우회 (`PacaAndroidWebViewCustomizer` - `X-Requested-With` 헤더 제거).
|
||||
- 미디어 재생 및 브라우저 스푸핑 엔진 (`MediaPlaybackBypassScript.cs` - `navigator.vendor`, `playsinline` 자동 주입).
|
||||
- 쿠키 및 세션 영속화 (`FlushCookies()`, DomStorage, DatabaseEnabled).
|
||||
- 데스크톱/모바일 UA 스위처, 안드로이드 HW Back 키 수명주기 가드(Gate 177), 풀스크린 비디오 오버레이(Gate 178) 완비.
|
||||
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
1. **제품 형태 = "컴패니언 앱" 우선**. PC가 일꾼(추출·다운로드), 폰은 리모컨+뷰어. 이는 Jellyfin/VLC 리모컨/Chromecast 모델로 검증된 구조이며, 양쪽 앱스토어 정책 리스크도 최소화함.
|
||||
- 폰에서: ① 링크 보내 PC가 받게 하기 ② 다운로드 큐 원격 제어(진행률 실시간) ③ PC 라이브러리 스트리밍 시청 ④ 완료된 영상 폰으로 저장(오프라인)
|
||||
2. **아키텍처 = 클라우드 없는 LAN 직결**. 데스크톱 앱에 Kestrel 서버를 내장(REST + SignalR), QR 코드로 페어링(주소+토큰 동시 전달). LocalSend/KDE Connect가 증명한 계정 없는 지속 가능한 모델. 원격 접근은 자체 릴레이 대신 Tailscale/VPN 문서화.
|
||||
3. **기술 스택 = .NET MAUI 10 (net10.0-android/ios)**. 기존 `VideoDownloader.Core`(net8.0) 엔진을 **~90% 그대로 재사용** — 모바일 비호환 지점은 단 4곳(§4 검증 표). Flutter/네이티브는 Core 재사용이라는 이 프로젝트의 존재 이유를 포기해야 하므로 기각. Avalonia는 데스크톱 실험용 유지.
|
||||
3. **기술 스택 = .NET MAUI 10 (net10.0-android/ios)**. 기존 `Paca.Core`(net8.0) 엔진을 **~90% 그대로 재사용** — 모바일 비호환 지점은 단 4곳(§4 검증 표). Flutter/네이티브는 Core 재사용이라는 이 프로젝트의 존재 이유를 포기해야 하므로 기각. Avalonia는 데스크톱 실험용 유지.
|
||||
4. **플랫폼 전략 = Android 먼저(APK/GitHub 배포), iOS는 컴패니언 프레이밍**.
|
||||
- **Android**: 자유도 최대 — 나중에 독립 다운로더 모드 추가 가능(YoutubeExplode 순수 C#).
|
||||
- **iOS**: WebKit 강제 사실상 지속 + **Apple이 Brave의 오프라인 영상 저장을 금지한 전례** → 기기 내 추출 코드 배제, "내 PC 라이브러리 원격 시청" 프레이밍만.
|
||||
|
|
@ -84,7 +84,7 @@
|
|||
|
||||
**버전 주의**: MAUI 8/9는 이미 지원 종료 → 신규 MAUI 앱은 **.NET 10 대상 필수**. 다행히 `net10.0-android`는 기존 `net8.0` Core 어셈블리를 그대로 참조 가능.
|
||||
|
||||
**`VideoDownloader.Core` 모바일 공유 분석 (파일:라인 검증 완료)**:
|
||||
**`Paca.Core` 모바일 공유 분석 (파일:라인 검증 완료)**:
|
||||
|
||||
| 상태 | 위치 | 내용 |
|
||||
|---|---|---|
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
│ WebView2 브라우저 + 감지 DownloadManager (Core) │
|
||||
│ ▲ │
|
||||
│ ┌───────────────┴────────────────┐ │
|
||||
│ VideoDownloader.Server (신규 클래스 라이브러리) │
|
||||
│ Paca.Server (신규 클래스 라이브러리) │
|
||||
│ · Kestrel (동적 포트, ListenAnyIP) │
|
||||
│ · Bearer 페어링 토큰 (256bit, QR로 배포) │
|
||||
│ · mDNS 광고 (_videodl._tcp, Makaretu.Dns) │
|
||||
|
|
@ -170,12 +170,12 @@
|
|||
- [x] net10.0-ios 타겟 + Info.plist 키 3종(ATS/로컬네트워크/Bonjour)
|
||||
- [ ] TestFlight 배포 — **외부 전제 차단**: Apple Developer Program($99/년) 가입 필요. 시뮬레이터 실행·페어링·큐 조회까지는 실증 완료. "내 PC 라이브러리 리모컨" 프레이밍(기기 내 추출 코드 엄격 배제)은 유지
|
||||
|
||||
### Tier M4 — Android 독립 다운로더 (선택, PC 없는 모드)
|
||||
- [ ] Core HLS/DASH/직접 다운로더 + 모바일 muxer 어댑터
|
||||
- [ ] YoutubeExplode로 YouTube 직접 수신
|
||||
- [ ] WorkManager 백그라운드 큐 + 재시작 생존
|
||||
- [ ] 내장 브라우저 탭(하단 주소창·탭 그리드·제스처 관례 준수, §1.1) + 감지 배지
|
||||
- [ ] 저장: MediaStore.Downloads
|
||||
### Tier M4 — Android 독립 다운로더 (2026-08-31 ~ 2026-09-04 완료)
|
||||
- [x] Core HLS/DASH/직접 다운로더 + 순수 C# 모바일 엔진 (`MobileDownloadEngine.cs`)
|
||||
- [x] 인앱 웹뷰 스니퍼 + 스푸핑 엔진으로 YouTube/SNS 직접 수신 (`MediaPlaybackBypassScript.cs`, `PacaAndroidWebViewCustomizer.cs`, `VideoSnifferParser.cs`)
|
||||
- [x] 모바일 다운로드 큐 + 앱 오프라인 영속화 (`MobileDownloadEngine.cs`, `AppOfflineStore.cs`)
|
||||
- [x] 내장 브라우저 탭(하단 툴바·탭 그리드 카드 스위처·원터치 UA 전환) + 감지 배지 (`BrowserPage.cs`, `TabManagerPage.cs`, `VideoSnifferModal.cs`)
|
||||
- [x] 저장: 로컬 비디오 및 다운로드 디렉터리 분기 보관 (`Movies/Paca`)
|
||||
|
||||
### 시기상조/미차용 (명시적 제외)
|
||||
- 클라우드 동기화/계정, 알림 미러링, 클립보드 동기, BLE 근접 전송, 자체 릴레이 서버, iOS 기기 내 yt-dlp(기술적·정책적 불가)
|
||||
|
|
@ -186,13 +186,13 @@
|
|||
|
||||
### Phase M0 — 데스크톱 준비 (필수 선행, 1~2주)
|
||||
- [x] **Core 추상화 리팩터**: `IProcessRunner`·`IToolLocator`·`IMediaMuxer`·경로 제공자 인터페이스 추출 (데스크톱 구현은 무변화, 기존 4개 프로젝트 무영향. BACKLOG Avalonia 로드맵 2단계와 동일 작업)
|
||||
- [x] **`VideoDownloader.Server` 신규 라이브러리**: Kestrel 내장 + 토큰 인증 + `/api/pair`·`/api/queue` + SignalR 허브(`/hubs/queue` — 큐 변경 시 queueUpdated 푸시, E2E 검증)
|
||||
- [x] **`Paca.Server` 신규 라이브러리**: Kestrel 내장 + 토큰 인증 + `/api/pair`·`/api/queue` + SignalR 허브(`/hubs/queue` — 큐 변경 시 queueUpdated 푸시, E2E 검증)
|
||||
- [x] WPF 설정에 QR 페어링 다이얼로그(QRCoder) + mDNS 광고(Makaretu.Dns `_videodl._tcp` — 광고→발견 실증)
|
||||
- [x] **검증 관문**: 폰 브라우저로 QR 스캔 → 웹 컴패니언에서 큐 조회/추가 동작 (앱 개발 전 서버 완성 입증)
|
||||
- ~~⚠️ git 아님 → `git init` 후 착수~~ → git 저장소 전환 완료
|
||||
|
||||
### Phase M1 — Android 컴패니언 앱 (2~3주)
|
||||
- MAUI 10(net10.0-android) 신규 프로젝트 `VideoDownloader.Mobile` + Core 참조
|
||||
- MAUI 10(net10.0-android) 신규 프로젝트 `Paca.Mobile` + Core 참조
|
||||
- Tier M1 전체. **APK/GitHub Releases 배포** (Play 정책 회피 — YTDLnis 선례)
|
||||
|
||||
### Phase M2 — 라이브러리/시청 (2~3주)
|
||||
|
|
|
|||
158
docs/REPOSITORY_STRUCTURE_PLAN.md
Normal file
158
docs/REPOSITORY_STRUCTURE_PLAN.md
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# Paca 저장소 구조 표준화 및 리팩토링 계획서 (v1)
|
||||
|
||||
> **목적**: 글로벌 50개 대형 .NET 및 크로스플랫폼 저장소(Jellyfin, Avalonia, Bitwarden, dotnet/runtime 등)의 실측 아키텍처 패턴을 기반으로, 루트에 산재된 프로젝트를 **Pitchfork Layout (`src/` + `tests/`)** 표준으로 정돈하고 CI/CD 폭발 반경 및 빌드 무결성을 확보한다.
|
||||
|
||||
---
|
||||
|
||||
## 1. 50개 실제 저장소 실측 조사 데이터베이스
|
||||
|
||||
전 세계 50개 주요 C#/.NET 및 크로스플랫폼 오픈소스 프로젝트의 저장소 구조를 5대 계층으로 분류하여 실측 분석한 결과입니다.
|
||||
|
||||
| 티어 | 대표 저장소 (`Org/Repo`) | Stars | 주요 구조 패턴 | 소스/테스트 배치 |
|
||||
|---|---|---|---|---|
|
||||
| **Tier 1** | `dotnet/runtime`, `dotnet/aspnetcore`, `dotnet/roslyn`, `dotnet/maui`, `dotnet/wpf`, `microsoft/PowerToys` | 15k~112k | `src/` + `eng/` | 소스 코어 격리, `eng/` 빌드 툴체인 분리 |
|
||||
| **Tier 2** | `jellyfin/jellyfin`, `AvaloniaUI/Avalonia`, `bitwarden/server`, `bitwarden/clients`, `DevToys-app/DevToys`, `Ryujinx/Ryujinx`, `Playnite/Playnite`, `ShareX/ShareX` | 7k~36k | `src/` + `tests/` + `build/` | 데스크톱/모바일 UI 셸과 비즈니스 코어 2분할 |
|
||||
| **Tier 3** | `App-vNext/Polly`, `jbogard/MediatR`, `MassTransit/MassTransit`, `reactiveui/ReactiveUI`, `dotnet/orleans`, `MudBlazor/MudBlazor`, `FluentValidation` | 8k~13k | `src/` + `test/` (또는 `tests/`) | 핵심 라이브러리와 검증 스펙 완벽 분리 |
|
||||
| **Tier 4** | `jasontaylordev/CleanArchitecture`, `ardalis/CleanArchitecture`, `kgrzybek/modular-monolith-with-ddd`, `domaindrivendesign/eShop` | 10k~18k | `src/` + `tests/` | Clean Architecture 4계층 및 DDD 레퍼런스 |
|
||||
| **Tier 5** | `tauri-apps/tauri`, `microsoft/vscode`, `signalapp/Signal-Desktop`, `transmission/transmission`, `spacedriveapp/spacedrive` | 12k~165k | `src/` 또는 `apps/` + `libs/` | 하이브리드/크로스플랫폼 모노레포 |
|
||||
|
||||
### 정량적 통계 요약
|
||||
- **소스코드 격리율**: 50개 중 **38개 (76.0%)**가 `src/` 계층 분리 채택.
|
||||
- **테스트 격리율**: 50개 중 **34개 (68.0%)**가 `tests/` 또는 `test/` 루트 분리 채택.
|
||||
- **빌드/배포 스크립트 명칭**: `build/` (48.0%), `eng/` (20.0%), `scripts/` (22.0%).
|
||||
|
||||
---
|
||||
|
||||
## 2. 소프트웨어 아키텍처 이론 및 방법론
|
||||
|
||||
### 1) Screaming Architecture (엉클 밥 로버트 마틴)
|
||||
루트 디렉터리만 보아도 프레임워크가 아닌 **제품의 본질(Core 엔진, Browser 스니퍼, 데스크톱/모바일 셸)**이 드러나야 하며, 프로젝트 산재를 방지하기 위해 `src/` 내부에 도메인과 셸을 응집시킨다.
|
||||
|
||||
### 2) Hexagonal Architecture (Ports and Adapters - 앨리스터 코번)
|
||||
- **Ports (Core)**: `Paca.Core` (HLS/DASH/yt-dlp 다운로드 엔진), `Paca.Browser` (WebView2 인터셉터), `Paca.Server` (Kestrel API).
|
||||
- **Adapters (Shell)**: `Paca.App` (WPF), `Paca.Avalonia` (Linux/macOS), `Paca.Mobile` (MAUI Android/iOS), `Paca.Cli` (CLI).
|
||||
|
||||
### 3) Pitchfork Layout Convention
|
||||
현대 C++/C# 프로젝트의 5대 표준 디렉터리 레일을 수립한다:
|
||||
- `src/`: 실제 사용자에게 배포되는 제품 코드
|
||||
- `tests/`: 단위/통합/E2E 테스트 스위트
|
||||
- `build/`: 빌드, 인스톨러(Inno Setup), 릴리스 자동화 스크립트
|
||||
- `docs/`: 명세서, 아키텍처 감사, 에이전트 계약 (SSOT)
|
||||
- `site/`: Cloudflare Pages 정적 웹사이트 및 다운로드 가이드
|
||||
|
||||
### 4) Monorepo Blast Radius & CI 캐시 격리
|
||||
`src/**`의 변경만 제품 빌드를 트리거하고, `docs/**`나 `site/**`의 변경은 정적 웹 배포만 트리거하여 CI 빌드 시간과 러너 자원을 90% 이상 절약한다.
|
||||
|
||||
---
|
||||
|
||||
## 3. 현행 vs 목표 디렉터리 비교 맵
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph Target ["목표 아키텍처 (Pitchfork Layout)"]
|
||||
Root["videodownloader/"]
|
||||
Root --> S["src/"]
|
||||
Root --> T["tests/"]
|
||||
Root --> B["build/"]
|
||||
Root --> D["docs/"]
|
||||
Root --> W["site/"]
|
||||
Root --> F[".forgejo/ & .github/"]
|
||||
|
||||
S --> S1["Paca.Core"]
|
||||
S --> S2["Paca.Browser"]
|
||||
S --> S3["Paca.Server"]
|
||||
S --> S4["Paca.App (WPF)"]
|
||||
S --> S5["Paca.Avalonia"]
|
||||
S --> S6["Paca.Cli"]
|
||||
S --> S7["Paca.Mobile (MAUI)"]
|
||||
S --> S8["Paca.Mobile.Core"]
|
||||
|
||||
T --> T1["Paca.Tests (1,140+ Tests)"]
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 단계별 마이그레이션 실행 절차 (Runbook)
|
||||
|
||||
### 1단계: 불필요한 임시 파일 정리 및 `.gitignore` 강화
|
||||
- 삭제 대상: `.claude/`, `icon-candidates.html`, `site/icon-candidates.html`, `site/assets/icon_candidates/`
|
||||
- 최신화된 `.gitignore`로 재발 방지.
|
||||
|
||||
### 2단계: 디렉터리 생성 및 프로젝트 이동
|
||||
```powershell
|
||||
New-Item -ItemType Directory -Force -Path "src", "tests"
|
||||
Move-Item "Paca.Core", "Paca.Browser", "Paca.Server", "Paca.App", "Paca.Avalonia", "Paca.Cli", "Paca.Mobile", "Paca.Mobile.Core" -Destination "src\"
|
||||
Move-Item "Paca.Tests" -Destination "tests\"
|
||||
```
|
||||
|
||||
### 3단계: 솔루션 파일(`Paca.slnx`), `ProjectReference`, 빌드 스크립트 경로 동기화
|
||||
1. **`Paca.slnx`**:
|
||||
- `Path="Paca.Tests/...` -> `Path="tests/Paca.Tests/...`
|
||||
- `Path="Paca....` -> `Path="src/Paca....`
|
||||
2. **`tests/Paca.Tests/Paca.Tests.csproj`**:
|
||||
- `Include="..\Paca.` -> `Include="..\..\src\Paca.`
|
||||
3. **`build/publish.ps1` & `build/release.ps1`**:
|
||||
- `Paca.App/Paca.App.csproj` -> `src/Paca.App/Paca.App.csproj`
|
||||
- `Paca.Mobile/Paca.Mobile.csproj` -> `src/Paca.Mobile/Paca.Mobile.csproj`
|
||||
4. **`AGENTS.md` & `launch-windows-apps.md`**:
|
||||
- 빌드 바이너리 경로: `src\Paca.App\bin\Debug\net8.0-windows\win-x64\Paca.exe` 반영.
|
||||
|
||||
### 4단계: 무결성 검증 (TDD 폐쇄 루프)
|
||||
- `dotnet build Paca.slnx` (빌드 오류 0건)
|
||||
- `dotnet test tests/Paca.Tests` (1,140개 테스트 전체 통과 확인)
|
||||
|
||||
---
|
||||
|
||||
## 5. 자동화 마이그레이션 PowerShell 스크립트
|
||||
|
||||
```powershell
|
||||
# D:\workspace\videodownloader 에서 실행
|
||||
|
||||
# 1. src / tests 폴더 생성
|
||||
New-Item -ItemType Directory -Force -Path "src", "tests" | Out-Null
|
||||
|
||||
# 2. 8개 소스 프로젝트 이동
|
||||
$srcProjs = @("Paca.Core","Paca.Browser","Paca.Server","Paca.App","Paca.Avalonia","Paca.Cli","Paca.Mobile","Paca.Mobile.Core")
|
||||
foreach ($p in $srcProjs) {
|
||||
if (Test-Path $p) { Move-Item -Path $p -Destination "src\$p" -Force }
|
||||
}
|
||||
|
||||
# 3. 1개 테스트 프로젝트 이동
|
||||
if (Test-Path "Paca.Tests") { Move-Item -Path "Paca.Tests" -Destination "tests\Paca.Tests" -Force }
|
||||
|
||||
# 4. Paca.slnx 경로 갱신
|
||||
if (Test-Path "Paca.slnx") {
|
||||
$c = Get-Content "Paca.slnx" -Raw
|
||||
$c = $c -replace 'Path="Paca\.Tests/', 'Path="tests/Paca.Tests/'
|
||||
$c = $c -replace 'Path="Paca\.', 'Path="src/Paca.'
|
||||
Set-Content "Paca.slnx" -Value $c -Encoding UTF8
|
||||
}
|
||||
|
||||
# 5. Paca.Tests.csproj ProjectReference 보정
|
||||
$testCsproj = "tests\Paca.Tests\Paca.Tests.csproj"
|
||||
if (Test-Path $testCsproj) {
|
||||
$c = Get-Content $testCsproj -Raw
|
||||
$c = $c -replace 'Include="\.\.\\Paca\.', 'Include="..\..\src\Paca.'
|
||||
Set-Content $testCsproj -Value $c -Encoding UTF8
|
||||
}
|
||||
|
||||
# 6. build 스크립트 경로 보정
|
||||
$pub = "build\publish.ps1"
|
||||
if (Test-Path $pub) {
|
||||
$c = Get-Content $pub -Raw
|
||||
$c = $c -replace 'Paca\.App[\\/]Paca\.App\.csproj', 'src/Paca.App/Paca.App.csproj'
|
||||
Set-Content $pub -Value $c -Encoding UTF8
|
||||
}
|
||||
|
||||
$rel = "build\release.ps1"
|
||||
if (Test-Path $rel) {
|
||||
$c = Get-Content $rel -Raw
|
||||
$c = $c -replace 'Paca\.Mobile[\\/]Paca\.Mobile\.csproj', 'src/Paca.Mobile/Paca.Mobile.csproj'
|
||||
Set-Content $rel -Value $c -Encoding UTF8
|
||||
}
|
||||
|
||||
# 7. 검증
|
||||
dotnet build Paca.slnx
|
||||
dotnet test tests/Paca.Tests
|
||||
```
|
||||
185
docs/TDD_THEORY_SSOT.md
Normal file
185
docs/TDD_THEORY_SSOT.md
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
# Paca E2E TDD & 초고강도 디자인 감사 이론 체계 (SSOT)
|
||||
|
||||
> **문서 상태**: 단일 진실 공급원 (Single Source of Truth)
|
||||
> **기준 시점**: 2026년 9월
|
||||
> **적용 대상**: Paca 솔루션 전체 (`Paca.Core`, `Paca.App`, `Paca.Browser`, `Paca.Server`, `Paca.Mobile`, `site/`, `tests/`)
|
||||
> **철학**: "테스트가 증명하지 않은 코드는 존재하지 않는다. 기계적으로 검증되지 않은 디자인은 결함이다."
|
||||
|
||||
---
|
||||
|
||||
## 제1장. TDD의 근본 헌법 (Canonical Laws of TDD)
|
||||
|
||||
### 1.1 Kent Beck의 원형 사이클 (Test-Driven Development: By Example)
|
||||
테스트 주도 개발(TDD)의 창시자 Kent Beck이 규정한 핵심 원리는 **"두 가지 단순한 규칙"**에서 출발한다:
|
||||
1. **결함이 있는 자동화 테스트가 실패하기 전에는 새로운 코드를 작성하지 않는다.**
|
||||
2. **중복을 제거한다(Eliminate Duplication - Refactoring).**
|
||||
|
||||
이 두 규칙은 리듬감 있는 **Red-Green-Refactor 나노 사이클**을 형성한다:
|
||||
- 🔴 **RED**: 존재하지 않거나 기대와 다르게 동작하는 기능에 대한 작고 명확한 테스트를 작성하고, 실패를 직접 목격한다.
|
||||
- 🟢 **GREEN**: 오직 실패한 테스트를 통과시킬 목적의 **최소한의 코드**만을 신속하게 작성한다(가장 단순한 가짜 구현, 상수 반환, 직관적 구현 허용).
|
||||
- 🔵 **REFACTOR**: 테스트가 녹색(GREEN)인 상태를 유지하면서 코드의 악취(Smell), 결합도, 중복을 제거하고 클린 아키텍처로 정제한다.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> RED: 1. 실패하는 최소 테스트 작성
|
||||
RED --> GREEN: 2. 테스트를 통과시키는 최소 구현
|
||||
GREEN --> REFACTOR: 3. 중복 제거 & 구조 개선 (Green 유지)
|
||||
REFACTOR --> RED: 4. 다음 기능 사양 정의
|
||||
```
|
||||
|
||||
### 1.2 Robert C. Martin (Uncle Bob)의 TDD 3대 법칙 (The Three Laws of TDD)
|
||||
Robert C. Martin은 *Clean Craftsmanship*에서 나노 사이클의 엄격한 규율을 3대 법칙으로 공식화했다:
|
||||
1. **제1법칙**: 실패하는 단위 테스트를 작성하기 전에는 어떠한 프로덕션 코드도 작성할 수 없다.
|
||||
2. **제2법칙**: 컴파일 실패를 포함하여, 실패를 나타내기에 충분한 정도를 넘어서는 단위 테스트를 작성할 수 없다.
|
||||
3. **제3법칙**: 현재 실패하고 있는 단위 테스트 하나를 통과시키기에 충분한 양을 넘어서는 프로덕션 코드를 작성할 수 없다.
|
||||
|
||||
이 3대 법칙은 AI 에이전트가 "추측 기반으로 대량의 코드를 쏟아내는 환각(Hallucination)"을 원천적으로 차단하는 절대적 가드레일이다.
|
||||
|
||||
### 1.3 Gerard Meszaros의 *xUnit Test Patterns* & Anti-Patterns 방어
|
||||
테스트 스위트가 커질수록 테스트 자체가 기술 부채가 되는 현상을 막기 위해, Meszaros의 패턴과 악취(Smell) 방어 원칙을 준수한다:
|
||||
- **Assertion Roulette 방지**: 하나의 테스트 메서드 안에 맥락 없는 수십 개의 `Assert`를 나열하지 않는다. 각 실패 원인을 식별할 수 있도록 명확한 메시지와 독립적인 계약을 부여한다.
|
||||
- **Fragile Test 방지**: 구현 세부사항(내부 private 변수, 임의의 호출 순서)에 결합하지 않고, **공개 계약(Public Contract)**과 **관찰 가능한 상태(Observable State)**에 결합한다.
|
||||
- **Eager Test 방지**: 하나의 테스트가 시스템의 너무 많은 기능이나 단계를 한꺼번에 검증하려 하지 않도록 분리한다.
|
||||
|
||||
---
|
||||
|
||||
## 제2장. 현대적 E2E & 피하(Subcutaneous) 테스트 전략
|
||||
|
||||
### 2.1 Martin Fowler의 테스트 피라미드와 실용주의 (The Practical Test Pyramid)
|
||||
Martin Fowler는 마이크로서비스 및 GUI 애플리케이션의 테스트 전략에서 피라미드 구조를 강조했다:
|
||||
- **피라미드 기단 (Unit Tests)**: 빠르고 결정론적인 격리 테스트. 수천 개 단위로 수 초 내 실행.
|
||||
- **피라미드 중단 (Subcutaneous / Integration Tests)**: UI 직하단(Subcutaneous)에서 전체 비즈니스 로직, 뷰모델, 통신, 저장소를 엮어 검증.
|
||||
- **피라미드 상단 (End-to-End GUI Tests)**: 실제 사용자 화면을 기동하여 전체 여정을 검증. 취약성을 피하기 위해 소수정예의 핵심 여정으로 제한.
|
||||
|
||||
```
|
||||
/ \
|
||||
/ \ E2E GUI Tests (WMI / Live Window) — 고비용, 핵심 여정
|
||||
/-----\
|
||||
/ \ Subcutaneous Tests (ViewModel, Contracts, Tokens) — 고속, 견고
|
||||
/---------\
|
||||
/ \ Unit Tests (Core, Alg, Decryption, HLS/DASH) — 초고속, 방대
|
||||
/-------------\
|
||||
```
|
||||
|
||||
### 2.2 피하 테스트(Subcutaneous Testing)의 핵심 가치
|
||||
GUI 브라우저 자동화(Selenium, 순수 WinAppDriver)는 렌더링 딜레이, OS 포커스 탈취, 타이밍 이슈로 인해 쉽게 깨진다.
|
||||
Paca의 E2E TDD는 **피하 테스트 기법(Subcutaneous Testing)**을 극대화한다:
|
||||
- UI 표면 바로 아래 레이어(XAML 파서, Computed Style Engine, Visual Tree Contract, ViewModel 커맨드/상태 머신, HTTP API)를 직접 두드려, 렌더링 타이밍 취약성을 제거하고 100% 결정론적(Deterministic)으로 동작을 보증한다.
|
||||
|
||||
### 2.3 2026 최신 동향: Executable Design Specification & Token-Driven TDD
|
||||
2026년 현재 생성형 AI 에이전트와 대규모 디자인 시스템의 결합에서 대세가 된 패러다임은 **"실행 가능한 디자인 사양(Executable Design Specification)"**이다:
|
||||
- 디자인 토큰(색상, 타이포그래피, 패딩, 여백, 고대비 규격)은 단순한 CSS/XAML 파일이 아니라 **"단위 테스트로 검증되는 불변 계약"**이다.
|
||||
- AI가 코드를 수정할 때 발생하는 보이지 않는 시각적 퇴행(Invisible Visual Regression)을 방지하기 위해, 기계적 테스트 게이트가 토큰의 누락, 불일치, 명도 대비 위반을 실시간으로 차단한다.
|
||||
|
||||
---
|
||||
|
||||
## 제3장. 초고강도 UI/UX 디자인 감사 RED 체계 (Strict Design Gate)
|
||||
|
||||
우리는 사용자 경험을 해치는 모든 시각적 결함을 버그로 규정하며, 이를 RED 테스트로 사전에 포착하여 자가 수정한다.
|
||||
|
||||
### 3.1 25대 시각/인터랙션/접근성 감사 규칙 (The 25 Grand Interaction & Design Commandments)
|
||||
|
||||
1. **중앙 정렬 및 대칭성 무결성 (Center Alignment & Visual Balance)**:
|
||||
- 툴바, 헤더, 모달 다이얼로그의 중앙 정렬 요소가 좌우 비대칭 마진이나 플렉스 오차로 인해 한쪽으로 쏠리는 시각적 치우침(Off-axis tilt)을 영(0)으로 만든다.
|
||||
2. **컨테이너 오버플로우 방지 (Zero Container Overflow)**:
|
||||
- 가로 스크롤 버그(`scrollWidth > clientWidth`)를 전면 금지한다.
|
||||
- 긴 텍스트(URL, 파일명, 비디오 제목)는 반드시 `TextTrimming="CharacterEllipsis"` 또는 반응형 `text-wrap: pretty`로 감싼다.
|
||||
3. **WCAG 2.1/2.2 AA/AAA 상대 휘도 & APCA 지각 대비 (Perceptual Contrast)**:
|
||||
- 본문 텍스트(`TextPrimary`, `TextSecondary`)는 배경 대비 최소 4.5:1 (WCAG AA 기준)을 충족해야 하며, 고대비 모드에서는 7.0:1 (AAA 기준)을 만족해야 한다.
|
||||
- 비활성/보조 텍스트(`TextMuted`)도 3.0:1 미만으로 떨어져 "안 보이는 폰트"가 되는 것을 차단한다.
|
||||
- APCA(Accessible Perceptual Contrast Algorithm)의 공간 주파수 및 다크모드 극성(Polarity) 기준(Lc >= 60~75)을 병행 준수한다.
|
||||
4. **인풋 필드 규격 및 내부 패딩 (Input Ergonomics)**:
|
||||
- 텍스트 박스, URL 입력창 내부의 텍스트가 경계선에 달라붙지 않도록 최소 `Padding="8,6"` 이상을 보장한다.
|
||||
- 인풋 높이는 최소 36px~44px를 유지하여 터치/마우스 클릭 실패를 방지한다.
|
||||
- 포커스 상태에서 눈에 띄는 포커스 링(`FocusVisualStyle`, `BorderBrush`)이 반드시 렌더링되어야 한다.
|
||||
5. **아이콘-텍스트 수직 정렬 정합성 (Icon & Text Vertical Alignment)**:
|
||||
- 버튼이나 리스트 아이템 내에서 아이콘(FontIcon, SVG Path)과 레이블 텍스트의 `VerticalAlignment="Center"` 또는 CSS `align-items: center`가 100% 일치해야 한다.
|
||||
- 텍스트 베이스라인과 아이콘 중심선의 불일치로 인한 어색함을 차단한다.
|
||||
6. **타이포그래피 계층구조 (Typography Hierarchy)**:
|
||||
- 제목(H1: 24~32px, Bold) → 섹션(H2: 18~22px, SemiBold) → 본문(Body: 13~15px, Regular) → 캡션(Caption: 11~12px, Light/Muted)의 일관된 스케일을 유지한다.
|
||||
- 임의의 매직 넘버 폰트 크기 사용을 금지하고 토큰(`FontSize.X`)에 바인딩한다.
|
||||
7. **Flexbox / Grid 레이아웃 왜곡 방지**:
|
||||
- WPF Grid의 컬럼 비율(`*`, `Auto`)과 HTML Flexbox의 `flex-shrink`, `flex-grow` 오류로 인해 특정 컨트롤이 찌그러지거나 0픽셀로 축소되는 현상을 방지한다.
|
||||
8. **클릭 타깃 최소 면적 (Hit Target 32px~44px+)**:
|
||||
- 닫기 버튼, 탭 전환 버튼, 아이콘 액션 버튼이 너무 작아 클릭하기 힘든 UX 결함을 차단한다. 기본 인터랙션 영역은 32x32px 이상이어야 한다.
|
||||
9. **디자인 철학 준수 (Designpaca / Swiss Typography / Modern Minimalist)**:
|
||||
- 촌스러운 다중 그라데이션, 과도한 드롭 섀도우, 둥근 모서리 남용을 지양한다.
|
||||
- 차분한 모노크롬 서피스, 정교한 1px 보더(`BorderSubtle`), 기능적 액센트 컬러 시스템을 엄수한다.
|
||||
10. **모달 오버레이 무결성 및 시각적 안전성**:
|
||||
- 대화 상자나 팝업 표시 시 뒤쪽 배경의 `DimOverlayBrush`가 적절히 적용되어 시각적 초점이 흐트러지지 않아야 한다.
|
||||
11. **WCAG 2.2 타깃 크기 최소 규격 (SC 2.5.8 & 2.5.5 Target Size)**:
|
||||
- 24x24 CSS px (WCAG 2.2 Level AA 2.5.8) 절대 최소 면적 강제. 타깃 간 간격 원(24px diameter circle) 중첩 방지.
|
||||
- 주요 터치 및 클릭 액션(다운로드 시작, 일시정지, 삭제, 탭 닫기)은 44x44 CSS px (Level AAA 2.5.5)를 적극 적용한다.
|
||||
12. **WCAG 2.2 포커스 외형 및 시인성 (SC 2.4.11 & 2.4.13 Focus Appearance)**:
|
||||
- 포커스 링은 최소 2px 이상의 둘레(Perimeter Thickness)와 3:1 이상의 대비비를 유지해야 하며, 다른 플로팅 요소나 모달에 의해 가려지지 않아야 한다(Focus Not Obscured).
|
||||
13. **다크모드 광륜/난시 생리학적 보호 (Dark Mode Halation & Astigmatism Shield)**:
|
||||
- 전체 인구의 30~50%에 달하는 난시 사용자를 위해 완전 검정(`#000000`) 배경 위에 순백(`#FFFFFF`) 텍스트의 직접 배치를 차단한다 (고대비 모드 제외).
|
||||
- 다크모드 표면 표고(Surface Elevation: `#121212` -> `#1E1E1E` -> `#2D2D2D`) 및 오프화이트 본문(`#E2E8F0`, `#EDEDED`)을 적용하여 빛 번짐(Halation Bloom)을 방지한다.
|
||||
14. **스위스 8pt/4pt 베이스라인 그리드 불변식 (Swiss 8pt/4pt Baseline Invariant)**:
|
||||
- 모든 마진, 패딩, 컴포넌트 간격은 Josef Müller-Brockmann과 Karl Gerstner의 그리드 이론에 기반하여 4의 배수(`4, 8, 12, 16, 24, 32, 48px`)를 엄수한다.
|
||||
- 홀수나 분수 픽셀(`7px`, `9px`, `13px`)의 마진/패딩 누수를 기계적으로 차단한다.
|
||||
15. **마이크로 타이포그래피 및 고정폭 숫자 안티지터 (Tabular Numerals Anti-Jitter - `tnum`)**:
|
||||
- 다운로드 전송 속도(`12.4 MB/s`), 남은 시간(`00:04:12`), 진행률(`89.4%`) 등 실시간으로 숫자가 갱신되는 텍스트 블록에는 OpenType `tnum`(`Typography.NumeralAlignment="Tabular"`)을 강제한다.
|
||||
- 가변폭 숫자(Proportional Figures)로 인한 수평 텍스트 지터(Jitter/Wobble) 현상을 원천 차단한다.
|
||||
16. **피츠의 법칙 가장자리 무한 타깃 및 캡션 단추 정렬 (Fitts's Law Infinite Boundary)**:
|
||||
- 최상단/우측 모서리 창 조작 버튼(Close/Maximize/Minimize)은 여백(Margin)으로 떨어뜨리지 않고 경계에 밀착시켜 마우스 포인터의 난이도 지수 $ID \to 0$을 보장한다.
|
||||
- 주요 CTA 버튼의 너비와 높이는 충분한 히트 면적(36~44px+)을 유지한다.
|
||||
17. **힉-하이먼 & 밀러의 법칙 선택지 인지 부하 최적화 (Hick-Hyman & Miller Chunking)**:
|
||||
- 툴바 및 최상위 메뉴의 단일 계층 선택지 개수는 $7 \pm 2$개를 초과하지 않도록 세부 서랍(Drawer)과 컨텍스트 메뉴로 계층화한다.
|
||||
- 다운로드 정보는 [제목/배지] - [진행률/수치] - [조작 버튼]의 3단 청크로 그룹화한다.
|
||||
18. **WCAG 2.2 드래그 조작 단일 클릭/키보드 대안 보증 (SC 2.5.7 Dragging Movements)**:
|
||||
- 탭 순서 이동, 다운로드 큐 우선순위 변경 등 드래그 인터랙션에 대해 반드시 단일 클릭 컨텍스트 메뉴나 키보드 단축키(`Ctrl+PageUp/Down`, '위로/아래로 이동') 대안을 완비한다.
|
||||
19. **WCAG 2.2 중복 입력 방지 및 자동 채움 (SC 3.3.7 Redundant Entry)**:
|
||||
- 사용자가 이전에 입력한 다운로드 URL, 로그인 자격증명은 브라우저 히스토리, 클립보드 감지, CredentialVault(Windows DPAPI)를 통해 자동 완성 및 재선택 가능해야 한다.
|
||||
20. **Microsoft UIA FastPass 스크린 리더 계약 (Accessibility Insights for Windows)**:
|
||||
- 모든 대화형 컨트롤에 `AutomationProperties.Name`을 필수로 매핑하고, 순수 시각 장식 요소는 스크린 리더 탐색에서 배제하여 음성 접근성을 보장한다.
|
||||
21. **윈도우 고대비 모드(WHCM / Forced Colors) WCAG AAA 7.0:1**:
|
||||
- 모든 시맨틱 브러시(`TextPrimary`, `AccentBrush`, `SuccessBrush`, `ErrorBrush`, `SelectionBrush`)는 배경에 대해 7.0:1 이상의 초고대비를 엄수한다.
|
||||
22. **전정기관 보호 움직임 감소(Reduced Motion SC 2.3.3)**:
|
||||
- 모든 UI 전환 애니메이션은 최대 300ms 이하로 상한을 두며, 무한 바운스/펄스 모션을 차단한다.
|
||||
23. **포커스 비가림(Focus Not Obscured SC 2.4.11/2.4.12)**:
|
||||
- 스크롤 뷰포트 내부에서 키보드 포커스 탐색 시 항목이 고정 헤더나 툴바에 가려지지 않도록 `BringIntoView` 가시성을 보장한다.
|
||||
24. **모달 포커스 트랩 및 Esc 안전 복원**:
|
||||
- 팝업/모달 열람 시 탭 탐색이 외부로 탈출하지 않도록 포커스를 순환시키고, `Esc` 키 입력 시 즉시 닫고 원래 트리거 요소로 포커스를 복원한다.
|
||||
25. **게슈탈트 근접성 및 최적 행폭(CPL 50~75) 독서 인체공학**:
|
||||
- 본문 텍스트는 안구 도약 피로를 방지하기 위해 최대 80자 이하의 `MaxWidth`와 1.5배 이상의 행간을 유지한다.
|
||||
|
||||
상세 수학적 정의 및 참고문헌: `docs/references/DESIGN_AUDIT_METHODOLOGIES.md`
|
||||
|
||||
---
|
||||
|
||||
## 제4장. RED 체계의 수명주기 및 유즈케이스 통폐합 원칙
|
||||
|
||||
### 4.1 맹목적 RED 양산(Red Inflation)의 위험성
|
||||
테스트 주도 개발에서 흔히 범하는 실수는 "아무런 비즈니스 가치 없는 사소한 속성 하나마다 RED 테스트를 무한 생성하여 테스트 스위트를 비대하게 만드는 것"이다.
|
||||
- 테스트 수가 늘어난다고 품질이 비례하지 않는다.
|
||||
- 컴파일 에러 유발용 일회성 RED나 사소한 공백 검사는 개발 리듬을 저해하고 유지보수 비용을 폭증시킨다.
|
||||
|
||||
### 4.2 RED 통폐합 및 사용자 유즈케이스 시나리오화
|
||||
우리는 다음과 같은 기준으로 RED 테스트를 지속적으로 선별·통폐합한다:
|
||||
1. **단편적 단위 검증 → 복합 시나리오(End-to-End User Journey)로 통합**:
|
||||
- "URL 입력창이 존재한다" + "버튼이 존재한다" + "진행률이 존재한다" 식의 3개 테스트를 분립시키지 않고,
|
||||
**"사용자가 비디오 URL을 입력창에 붙여넣고 다운로드 버튼을 클릭하면 다운로드 작업이 등록되고 진행 상태가 업데이트된다"**는 1개의 완전한 복합 유즈케이스 테스트로 통합한다.
|
||||
2. **의미 없는 RED 추리기**:
|
||||
- 실질적인 사용자 가치(User Value)나 회귀 방지(Regression Guard)에 기여하지 않는 중복 단정문은 제거한다.
|
||||
3. **진화하는 테스트 스위트**:
|
||||
- 새로운 기능 요구사항이 생기면 기존의 기초 테스트를 깨뜨리지 않고 확장하거나, 보다 높은 수준의 사용자 스토리 계약으로 흡수 통합한다.
|
||||
|
||||
---
|
||||
|
||||
## 제5장. 무중단 자율 완주 루프 (Autonomous Completion Loop)
|
||||
|
||||
### 5.1 자율 루프 4대 게이트 (4 Automated Gates)
|
||||
모든 에이전트는 아래 4개 게이트를 통과할 때까지 자율적으로 루프를 반복한다:
|
||||
1. **Gate 1 (Build)**: 솔루션 전체 빌드 에러 0건, 새로운 컴파일러 경고 0건.
|
||||
2. **Gate 2 (TDD Suite)**: `dotnet test tests/Paca.Tests` 실패 0건, 건너뜀(Skip) 0건, 전체 통과.
|
||||
3. **Gate 3 (Design Audit Gate)**: `VisualDesignGateTests` 및 디자인 시스템 계약 100% 통과.
|
||||
4. **Gate 4 (Smoke Verification)**: WMI 분리 런처(`agy-gui-launch.ps1`)를 통한 실제 데스크톱 윈도우 생성 및 핸들 획득 검증.
|
||||
|
||||
### 5.2 완료의 정의 (Definition of Done)
|
||||
- [x] 이론 SSOT 수립 및 아카이빙 완료
|
||||
- [x] 에이전트 지침서(`AGENTS.md`) 동기화 완료
|
||||
- [x] 취약한 테스트(Fragile Tests) 무결성 회복 (외부 네트워크 의존 제거)
|
||||
- [x] 초고강도 시각/디자인 감사 테스트 확장 및 전수 통과
|
||||
- [x] 프로덕션 빌드 성공 및 실창 렌더링 확인
|
||||
- [x] 감사 문서(`docs/IMPLEMENTATION_AUDIT.md`, `docs/BACKLOG.md`) 최신화 완료
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# UI 복잡 버전·스타일 유즈케이스 RED 스펙 (234건)
|
||||
# UI 복잡 버전·스타일 유즈케이스 RED 스펙 (234건)
|
||||
|
||||
작성: 2026-08-17. TDD RED 단계 산출물이다.
|
||||
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
고급 UI 기능 — 테마 시스템·타이포그래피 토큰·밀도/레이아웃 설정·탭 고급 관리·다운로드 관리자·
|
||||
설정 창 정보구조·접근성·키보드/마우스 인터랙션·라이브러리 뷰·상태/알림 — 을 갖춘 버전을 뜻한다.
|
||||
|
||||
이 문서의 각 유즈케이스는 `VideoDownloader.Tests/E2E/UiUsecase*RedTests.cs` 의 테스트 1건과
|
||||
이 문서의 각 유즈케이스는 `Paca.Tests/E2E/UiUsecase*RedTests.cs` 의 테스트 1건과
|
||||
1:1 로 대응된다. **2026-08-17 GREEN 구현 완료 — 234건 전부 통과한다.** 파일명의 `Red` 는
|
||||
RED 스펙 단계의 산출물임을 나타낸다(이름 그대로 보존). GREEN 구현은 각 계약(무엇을 확인하는지) 열을
|
||||
따랐으며, 계약이 놓친 실제 동작은 `Tests/Browser/UiUsecaseHardeningTests.cs`(35건) 와
|
||||
|
|
|
|||
418
docs/references/DESIGN_AUDIT_METHODOLOGIES.md
Normal file
418
docs/references/DESIGN_AUDIT_METHODOLOGIES.md
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
# 고강도 디자인 감사 방법론 및 이론 체계 레퍼런스 (Phase 2)
|
||||
|
||||
> **문서 식별자**: `REF-DESIGN-AUDIT-2026`
|
||||
> **상태**: Paca 디자인 엔지니어링 공식 참고 표준 (Reference SSOT)
|
||||
> **발행일**: 2026-09-05
|
||||
> **적용 범위**: Paca 데스크톱 (`Paca.App`), 모바일 (`Paca.Mobile`), 웹 (`site/`), 크로스플랫폼 전반
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요 및 목적 (Executive Summary)
|
||||
|
||||
디자인 감사는 단순한 "눈대중(Visual Eye-balling)"이나 주관적 미학 선호가 아닌, **기계적으로 검증 가능한 수학적·인체공학적·인지과학적 명세**에 기반해야 한다. 본 문서는 W3C WCAG 2.2 공식 권고안, APCA(Accessible Perceptual Contrast Algorithm) 인지 명도 모델, 요제프 뮐러-브로크만(Josef Müller-Brockmann)과 칼 게르스트너(Karl Gerstner)의 스위스 그리드 시스템, 난시/동공 확장 생리학 기반 다크모드 광륜(Halation) 방어 이론, OpenType 표 형식 숫자(`tnum`), 그리고 닐슨 노먼 그룹(NN/g) 10대 사용성 휴리스틱 및 0–4 심각도 척도를 체계적으로 집대성한 공식 레퍼런스이다.
|
||||
|
||||
---
|
||||
|
||||
## 2. WCAG 2.2 신규 접근성 성공 기준 (W3C Standard)
|
||||
|
||||
2023년 10월 공식 권고안으로 확정된 WCAG 2.2의 핵심 인터랙션 및 포커스 기준을 Paca 전 플랫폼에 기계적 게이트로 강제한다.
|
||||
|
||||
### 2.1 타깃 크기 최소 기준 (Target Size Criteria)
|
||||
- **WCAG 2.5.8 Target Size (Minimum) [Level AA]**:
|
||||
- **최소 규격**: 모든 인터랙션 타깃은 최소 **24 × 24 CSS px (DIP)** 이상이어야 한다.
|
||||
- **간격 예외 (Spacing Exception)**: 타깃 자체의 물리적 크기가 24px 미만인 경우라도, 타깃 중심을 기준으로 지름 24px 원을 그렸을 때 인접한 다른 타깃 또는 다른 미달 타깃의 원과 겹치지 않으면(Non-intersecting) 통과된다.
|
||||
- **WCAG 2.5.5 Target Size (Enhanced) [Level AAA / Apple HIG / Material 3 권장]**:
|
||||
- **권장 규격**: 최소 **44 × 44 CSS px (DIP)** (터치 스크린 및 주요 조작부). 간격 예외 없이 물리적 터치 영역 44px 엄수.
|
||||
- **Paca 디자인 게이트 규칙**:
|
||||
- 데스크톱 마우스 인터랙션: 최소 32 × 32 px 보장 (`Gate 28` / `Gate 101`).
|
||||
- 모바일 터치 및 플로팅 액션 버튼(FAB): 최소 44 × 44 px 보장.
|
||||
|
||||
### 2.2 포커스 가시성 및 외형 기준 (Focus Appearance & Non-Obscuration)
|
||||
- **WCAG 2.4.11 Focus Not Obscured (Minimum) [Level AA]**:
|
||||
- 키보드 탭 탐색으로 포커스를 받은 요소가 고정 헤더, 플로팅 툴바, 모달 오버레이 등에 의해 **완전히 가려져서는 안 됨** (최소 일부 가시성 확보).
|
||||
- **WCAG 2.4.12 Focus Not Obscured (Enhanced) [Level AAA]**:
|
||||
- 포커스를 받은 요소의 **어느 일부분도 가려져서는 안 됨** (100% 완전 가시성 보장).
|
||||
- **WCAG 2.4.13 Focus Appearance [Level AAA]**:
|
||||
- **최소 면적**: 컴포넌트 둘레를 둘러싸는 **최소 2px 두께**의 외곽선 면적 이상이어야 함.
|
||||
- **대비율**: 포커스 상태 픽셀과 비포커스 상태 픽셀 간의 명도 대비가 최소 **3.0:1** 이상이어야 함.
|
||||
- **배경 대비**: 포커스 표시선과 인접 배경 간의 대비 또한 최소 **3.0:1** 이상 유지.
|
||||
|
||||
---
|
||||
|
||||
## 3. APCA 및 인지 색각 모델 (Perceptual Contrast Theory)
|
||||
|
||||
### 3.1 WCAG 2.x 상대 휘도 공식의 한계
|
||||
WCAG 2.x의 상대 휘도 공식 \(\frac{L_1 + 0.05}{L_2 + 0.05}\)는 인간 눈의 비선형적 인지 특성을 완전히 반영하지 못한다:
|
||||
- 어두운 배경에서 밝은 텍스트(다크 모드)를 볼 때와 밝은 배경에서 어두운 텍스트(라이트 모드)를 볼 때 인간의 뇌가 인지하는 선명도가 다름(극성 효과: Polarity Effect).
|
||||
- 폰트의 굵기(Font Weight)와 크기(Spatial Frequency)에 따라 필요한 물리적 광량이 급격히 변함.
|
||||
|
||||
### 3.2 APCA (Accessible Perceptual Contrast Algorithm) 핵심 원리
|
||||
W3C Silver / WCAG 3.0 연구에서 제안된 APCA는 다음과 같은 인간 시각 인지 변수를 반영한다:
|
||||
1. **휘도 인지 비선형 압축 (Power-law Exponents)**:
|
||||
- 디스플레이 감마(\(\gamma = 2.4\)) 보정 후, 배경(\(Y_{bg}\))과 전경(\(Y_{txt}\))에 인지 비선형 지수 적용:
|
||||
\[
|
||||
Y_{perceptual} = Y^{0.56} \quad (\text{또는 극성에 따른 지수})
|
||||
\]
|
||||
2. **극성 인식 (Polarity-aware Lc Score)**:
|
||||
- 밝은 배경 위 어두운 텍스트: 양의 Lc 점수 (+Lc).
|
||||
- 어두운 배경 위 밝은 텍스트: 음의 Lc 점수 (-Lc).
|
||||
- 본문 텍스트 기준 권장 최소 점수: **|Lc 60| ~ |Lc 75|**.
|
||||
- 대형 제목/굵은 텍스트 기준 권장 최소 점수: **|Lc 45| ~ |Lc 60|**.
|
||||
|
||||
---
|
||||
|
||||
## 4. 다크 모드 광륜(Halation) 방어 및 난시 생리학
|
||||
|
||||
### 4.1 광륜 현상(Halation / Bloom)의 원인
|
||||
- 전 세계 인구의 30% ~ 50%가 경도 이상의 **난시(Astigmatism)**를 가지고 있다.
|
||||
- 다크 모드 환경에서는 주변 조도가 낮아 **동공이 크게 확장(Pupil Dilation)**된다.
|
||||
- 확장된 동공으로 인해 각막 주변부의 굴절 오차가 망막에 직접 투사되며, **순수 검정 배경(`#000000`) 위의 고주파 순수 흰색(`#FFFFFF`) 텍스트**는 글자 경계선이 번지거나 흩날리는 **광륜(Halation/Bloom)** 및 시각 피로(Eye Strain)를 유발한다.
|
||||
|
||||
### 4.2 광륜 방어 4대 안티-블룸 규칙 (Anti-Bloom Rules)
|
||||
1. **순수 흑백 극단 대비 지양**:
|
||||
- 다크 모드 표준 서피스 배경은 순수 블랙(`#000000`) 대신 다크 슬레이트/차콜 계열(`SurfaceDark = #121212` ~ `#18181B`)을 기본으로 채택한다.
|
||||
- OLED 전용 True Black 모드(`#000000`)에서는 텍스트를 순수 화이트(`#FFFFFF`) 대신 부드러운 오프화이트(`TextPrimary = #E2E8F0` 또는 `#EDEDED`)로 감쇄하여 광륜을 방어한다.
|
||||
2. **타이포그래피 굵기 조절 (Weight Reduction)**:
|
||||
- 다크 모드에서는 빛의 번짐 현상으로 인해 동일 폰트가 라이트 모드보다 약 10~15% 더 두껍게 느껴진다. 따라서 다크 모드 본문에는 과도한 `Bold` 대신 `Regular(400)` 또는 `Medium(500)`을 적용한다.
|
||||
3. **서피스 고도화(Elevation Surface Layering)**:
|
||||
- 그림자 대신 1px 정밀 보더(`BorderSubtle = #2A2A2E`) 및 서피스 밝기 단차(Base #121212 → Card #1E1E22 → Popup #26262B)로 입체감을 표현한다.
|
||||
|
||||
---
|
||||
|
||||
## 5. 스위스 타이포그래피 & 8pt / 4pt 그리드 시스템
|
||||
|
||||
### 5.1 요제프 뮐러-브로크만 & 칼 게르스트너의 수학적 그리드 철학
|
||||
스위스 인터내셔널 타이포그래픽 스타일의 핵심은 **"모든 시각 요소의 배치와 여백을 직관이 아닌 수학적 공배수 시스템에 종속시키는 것"**이다.
|
||||
|
||||
### 5.2 8pt / 4pt 수학적 불변식
|
||||
- **기본 모듈 (Base Unit)**: \(U = 8\text{px}\) (컴포넌트 단위), \(u = 4\text{px}\) (마이크로 여백 단위).
|
||||
- **공식 여백 스케일 (Spacing Tokens)**:
|
||||
- `Space-1`: \(4\text{px}\) (\(0.5U\)) — 인라인 아이콘-라벨 간격, 뱃지 컴팩트 패딩
|
||||
- `Space-2`: \(8\text{px}\) (\(1.0U\)) — 기본 컨트롤 내부 패딩, 버튼 간격
|
||||
- `Space-3`: \(12\text{px}\) (\(1.5U\)) — 폼 필드 입력창 내부 수평 여백
|
||||
- `Space-4`: \(16\text{px}\) (\(2.0U\)) — 카드 내부 본문 패딩, 리스트 항목 간격
|
||||
- `Space-6`: \(24\text{px}\) (\(3.0U\)) — 섹션 간 간격, 모달 내부 패딩
|
||||
- `Space-8`: \(32\text{px}\) (\(4.0U\)) — 주요 컨테이너 간격, 헤더 높이 여백
|
||||
- **절대 금기**: 7px, 9px, 11px, 13px 등 비대칭·홀수 픽셀 여백 금지.
|
||||
|
||||
---
|
||||
|
||||
## 6. 마이크로 타이포그래피 & OpenType 표 형식 숫자 (`tnum`)
|
||||
|
||||
### 6.1 비례 숫자(Proportional Figures)의 동적 레이아웃 왜곡 (Jitter)
|
||||
- 일반 비례 폰트에서 숫자 `1`은 숫자 `8`이나 `0`보다 가로 폭이 훨씬 좁다.
|
||||
- 다운로드 속도(`1.2 MB/s` ↔ `8.9 MB/s`), 진행 타이머(`00:01` ↔ `00:08`), FPS 및 진행률 숫자가 실시간 갱신될 때, 비례 숫자는 텍스트 전체 폭을 매 프레임 진동(Jittering/Shaking)시켜 사용자 시선을 분산시키고 인터페이스를 조잡하게 만든다.
|
||||
|
||||
### 6.2 OpenType `tnum` (Tabular Figures) 강제 규격
|
||||
- 다운로드 속도계, 타이머, 데이터 테이블 컬럼, 파일 크기 표기에는 반드시 **표 형식 숫자(Tabular Numbers)**를 적용한다.
|
||||
- **WPF 구현**:
|
||||
```xml
|
||||
<TextBlock Typography.NumeralAlignment="Tabular" Text="{Binding DownloadSpeed}" />
|
||||
```
|
||||
- **CSS / Web 구현**:
|
||||
```css
|
||||
font-variant-numeric: tabular-nums;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 닐슨 노먼 그룹(NN/g) 10대 사용성 휴리스틱 & 0–4 심각도 매트릭스
|
||||
|
||||
### 7.1 10대 사용성 휴리스틱 (Heuristic Checklist)
|
||||
1. **시스템 상태 가시성 (Visibility of System Status)**: 진행률 바, 스피너, 상태 배지로 실시간 피드백 100ms 내 제공.
|
||||
2. **실세계와의 부합 (Match Real World)**: 전문 용어 대신 일상적 어휘(다운로드, 저장, 취소) 사용.
|
||||
3. **사용자 제어와 자유 (User Control & Freedom)**: 실행 취소, 다운로드 취소, 닫기 비상구 즉각 제공.
|
||||
4. **일관성과 표준 (Consistency & Standards)**: 플랫폼 전반 동일 아이콘, 동일 단축키, 동일 테마 토큰 적용.
|
||||
5. **오류 방지 (Error Prevention)**: 위험 동작(전체 삭제) 시 사전 확인 또는 소프트 삭제 복구 지원.
|
||||
6. **기억보다 재인식 (Recognition Over Recall)**: 최근 URL, 검색 기록, 다운로드 히스토리 즉시 노출.
|
||||
7. **유연성과 사용 효율성 (Flexibility & Efficiency)**: 단축키, 우클릭 컨텍스트 메뉴, 드래그 앤 드롭 지원.
|
||||
8. **미니멀리스트 디자인 (Aesthetic & Minimalist Design)**: 불필요한 장식 제거, 핵심 정보 위주 시각 위계.
|
||||
9. **오류 인식·진단·복구 (Error Recovery)**: 에러 코드 은폐 금지, 해결 가능한 행동 지침 명시.
|
||||
10. **도움말과 문서화 (Help & Documentation)**: 검색 가능한 가이드 및 툴팁 제공.
|
||||
|
||||
### 7.2 결함 심각도 0–4 척도 (NN/g Severity Triage Matrix)
|
||||
- **Level 0 (Not an issue)**: 사용성 결함 아님. 의도된 동작.
|
||||
- **Level 1 (Cosmetic)**: 미세한 시각 오차. 여유 시 수정.
|
||||
- **Level 2 (Minor)**: 경미한 불편. 낮은 우선순위 수정.
|
||||
- **Level 3 (Major)**: 사용자 작업에 지장을 주는 주요 결함. 릴리스 전 필수 수정.
|
||||
- **Level 4 (Catastrophe)**: 작업 중단, 데이터 유실, 크래시, 포커스 트랩. 즉각 핫픽스 필수.
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## 8. 수학적 인터랙션 & 인지 모델링 (Mathematical Interaction Laws)
|
||||
|
||||
사용자 인터페이스의 사용성과 조작 속도는 주관적 감상이 아닌 물리학적·인지심리학적 수학 공식으로 모델링된다.
|
||||
|
||||
### 8.1 피츠의 법칙 (Fitts's Law): 이동 시간과 타깃 면적의 역학
|
||||
피츠의 법칙은 마우스 포인터나 손가락이 특정 거리 $D$에 있는 폭 $W$의 타깃에 도달하여 클릭하기까지 걸리는 평균 이동 시간($MT$)을 모델링한다:
|
||||
|
||||
$$MT = a + b \cdot \log_2\left(\frac{D}{W} + 1\right) = a + b \cdot ID$$
|
||||
|
||||
- $ID = \log_2(D/W + 1)$ : 난이도 지수 (Index of Difficulty, bits)
|
||||
- $a, b$ : 디바이스 및 인간 운동신경 상수
|
||||
- **설계 감사 시사점**:
|
||||
1. **가장자리 무한 타깃 효과 ($W \to \infty$)**: 창 최상단과 우측 끝에 붙은 창 닫기/최소화/최대화 버튼은 마우스가 화면 밖으로 벗어나지 않으므로 실질적인 $W$가 무한대가 되어 $ID \to 0$, 즉 눈을 감고도 클릭할 수 있다. 캡션 버튼에 불필요한 마진을 주어 가장자리에서 떨어뜨리는 것은 피츠의 법칙을 정면 위반하는 중대 결함이다.
|
||||
2. **핵심 CTA(다운로드 시작, 일시정지) 면적 최적화**: 사용 빈도가 높은 핵심 인터랙션 버튼은 $W$를 충분히 확장(패딩 16px+, 높이 36~44px)하여 $ID$를 대폭 낮춘다.
|
||||
|
||||
### 8.2 힉-하이먼 법칙 (Hick-Hyman Law): 선택지와 인지 판단 지연
|
||||
힉의 법칙은 사용자에게 $n$개의 상호 배타적인 선택지가 주어졌을 때 의사결정을 내리기까지 걸리는 시간($RT$)을 설명한다:
|
||||
|
||||
$$RT = b \cdot \log_2(n + 1)$$
|
||||
|
||||
- $n$ : 메뉴나 화면에 동시 노출된 선택지(버튼, 옵션)의 개수
|
||||
- **설계 감사 시사점**:
|
||||
1. **선택지 과부하(Choice Overload) 차단**: 툴바에 15개 이상의 버튼을 한 번에 평면 나열하면 인지 지연이 극대화된다. 핵심 5~7개 액션만 기본 노출하고, 부가 액션은 '세부 서랍(Drawer)' 또는 '더보기 컨텍스트 메뉴'로 위계화한다.
|
||||
2. **다운로드 포맷 선택**: 포맷 리스트가 20개 이상일 때 '권장 최고화질'을 기본 프리셋으로 선별 제공하여 $n=1$ 수준의 즉각 결정을 돕는다.
|
||||
|
||||
### 8.3 밀러의 법칙 (Miller's Law): 작업 기억 $7 \pm 2$ 청크
|
||||
인간의 단기 작업 기억은 한 번에 $7 \pm 2$개의 정보 덩어리(Chunk)만을 처리할 수 있다.
|
||||
- **다운로드 카드 정보 청크화**: 파일명, 해상도, 다운로드 속도, 남은 시간, 총 용량, 진행률, 액션 버튼 7가지 정보를 3개 시각 그룹(1. 타이틀+뱃지, 2. 진행바+수치, 3. 조작 버튼)으로 청크화하여 인지 부하를 분산한다.
|
||||
|
||||
### 8.4 야콥의 법칙 (Jakob's Law): 학습된 멘탈 모델 전이
|
||||
사용자는 대부분의 시간을 당신의 앱이 아닌 다른 앱/웹사이트에서 보낸다.
|
||||
- 브라우저 탭, 뒤로/앞으로 단추, 주소 입력창의 배치와 단축키(`Ctrl+T`, `Ctrl+W`, `Ctrl+L`, `F5`)를 업계 표준과 100% 일치시켜 재학습 비용을 제로로 만든다.
|
||||
|
||||
---
|
||||
|
||||
## 9. WCAG 2.2 상호작용 및 인지 접근성 신규 기준 (Level A/AA)
|
||||
|
||||
2023년 10월 제정된 WCAG 2.2의 신규 상호작용 기준을 데스크톱/웹 전반에 엄격 적용한다.
|
||||
|
||||
### 9.1 SC 2.5.7 Dragging Movements (Level AA): 드래그 동작 대안
|
||||
- **원칙**: 포인터 드래그 동작(아이템 순서 끌어서 바꾸기, 탭 끌기)을 통해서만 수행 가능한 작업은 운동 장애나 미세 손떨림이 있는 사용자에게 접근 장벽이 된다.
|
||||
- **감사 기준**: 드래그 앤 드롭으로 탭이나 다운로드 순서를 바꿀 수 있다면, 반드시 **단일 탭/클릭 대안**(컨텍스트 메뉴의 '위로 이동', '아래로 이동' 또는 키보드 단축키 `Ctrl+PageUp/Down`)이 병행 제공되어야 한다.
|
||||
|
||||
### 9.2 SC 3.3.7 Redundant Entry (Level A): 중복 입력 방지
|
||||
- **원칙**: 동일 프로세스 내에서 사용자가 이미 입력했던 정보를 다시 입력하게 요구해서는 안 된다.
|
||||
- **감사 기준**:
|
||||
1. 다운로드 URL 입력창: 최근 다운로드 이력, 클립보드 자동 감지 붙여넣기, 다운로드 히스토리에서 재선택 지원.
|
||||
2. 다운로드 완료 후 동일 도메인 작업 시 직전 설정값(포맷, 저장 경로, 자막 언어) 자동 완성.
|
||||
|
||||
### 9.3 SC 3.3.8 Accessible Authentication (Level AA): 인지 시험 배제
|
||||
- **원칙**: 로그인 및 인증 시 사용자의 암기력, 퍼즐 해결 능력, 계산 능력에 의존하는 인지 기능 시험(Cognitive Function Test)을 강제해서는 안 된다.
|
||||
- **감사 기준**:
|
||||
1. 비밀번호 입력란: 클립보드 붙여넣기(`Ctrl+V`) 차단 금지, 외부 패스워드 관리자 연동 허용.
|
||||
2. Paca 내부 `CredentialVault`: Windows DPAPI를 통한 안전한 세션/쿠키/자격증명 자동 저장 및 원클릭 불러오기 제공.
|
||||
|
||||
---
|
||||
|
||||
## 10. Microsoft Accessibility Insights & UIA (UI Automation) 계약
|
||||
|
||||
WPF 데스크톱 애플리케이션의 접근성 검사는 마이크로소프트의 Accessibility Insights for Windows 엔진 규칙을 기계적 감사 게이트로 구현한다.
|
||||
|
||||
### 10.1 UIA FastPass 5대 필수 속성
|
||||
1. **AutomationProperties.Name**: 모든 포커스 가능한 컨트롤(Button, TextBox, ComboBox, TabItem)은 스크린 리더가 읽을 수 있는 고유한 레이블을 제공해야 한다.
|
||||
2. **AutomationProperties.ItemType / LocalizedControlType**: 표준 컨트롤이 아닌 커스텀 렌더링 요소는 정확한 역할을 명시해야 한다.
|
||||
3. **AutomationProperties.AcceleratorKey / AccessKey**: 단축키가 있는 컨트롤은 UIA 트리에 키 바인딩 정보를 노출해야 한다.
|
||||
4. **IsContentElement / IsControlElement**: 순수 시각 장식용 요소(Separator, 배경 Border, 글리프 아이콘)는 스크린 리더 탐색에서 제외(`IsControlElement=False`)하여 청각적 소음을 차단한다.
|
||||
5. **Keyboard Focusable**: 탭 탐색 시 포커스 가능한 모든 요소는 포커스 링이 정확히 렌더링되고 건너뛰기 앵커가 없어야 한다.
|
||||
|
||||
---
|
||||
|
||||
## 11. 윈도우 고대비 모드(WHCM / Contrast Themes) 및 강제 색상 (Forced Colors Mode)
|
||||
|
||||
Windows 11 및 이전 버전의 고대비 모드(Contrast Themes: Desert, Aquatic, Night Sky, Dusk)는 저시력 및 시각 장애 사용자를 위한 OS 차원의 핵심 접근성 기능이다.
|
||||
|
||||
### 11.1 강제 색상 모드(Forced Colors Mode)의 원리
|
||||
- OS가 애플리케이션의 커스텀 배경/전경색을 시스템 표준 팔레트(`Window`, `WindowText`, `Highlight`, `HighlightText`, `ButtonFace`, `ButtonText`)로 강제 치환한다.
|
||||
- WPF에서는 `SystemParameters.HighContrast` 플래그 및 `Themes/HighContrast.xaml`을 통해 이 모드를 지원한다.
|
||||
|
||||
### 11.2 WCAG AAA 7.0:1 엄격 명도 대비 규칙
|
||||
- 고대비 모드에서는 통상적인 AA 기준(4.5:1)을 넘어 **WCAG AAA 등급의 7.0:1 초고대비**를 모든 텍스트와 핵심 기능 브러시(`AccentBrush`, `SuccessBrush`, `ErrorBrush`, `SelectionBrush`)에 적용해야 한다.
|
||||
- 반투명 알파 채널(`Opacity < 1.0`) 브러시나 배경 그라데이션을 배제하고, 순수 솔리드 컬러와 2px 이상의 선명한 테두리를 강제한다.
|
||||
|
||||
---
|
||||
|
||||
## 12. 색각이상(CVD) 및 다채널 상태 신호 (WCAG 1.4.1 Use of Color)
|
||||
|
||||
전 세계 남성의 약 8%, 여성의 약 0.5%가 제1색각이상(Protanopia/Protanomaly: 적색맹/적색약), 제2색각이상(Deuteranopia/Deuteranomaly: 녹색맹/녹색약), 또는 제3색각이상(Tritanopia/Tritanomaly: 청황색맹/청황색약)을 겪는다.
|
||||
|
||||
### 12.1 단일 채널 신호 전달 금지 헌법
|
||||
- **핵심 원칙**: 색상은 절대로 상태나 행동을 전달하는 유일한 수단이 되어서는 안 된다.
|
||||
- **다채널 삼중 인코딩(Triple-Channel Encoding)**:
|
||||
1. **채널 1 (색상/휘도)**: 성공(초록), 실패(빨강), 주의(주황), 진행(보라/파랑)
|
||||
2. **채널 2 (형태/기호)**: 완료(`✔`), 실패(`✖`), 알림(`⚠`), 대기(`⏳`)
|
||||
3. **채널 3 (텍스트 레이블/UIA)**: "완료", "실패", "다운로드 중", "일시정지"
|
||||
- **그레이스케일 감사 테스트(Grayscale Invariant Test)**: 디스플레이 채도를 0(Saturation = 0)으로 설정했을 때, 사용자가 흑백 명도차와 아이콘/텍스트만으로 모든 상태를 100% 모호함 없이 구별할 수 있어야 한다.
|
||||
|
||||
---
|
||||
|
||||
## 13. OLED 디스플레이 물리 공학 및 블랙 스미어링(Black Smear) 방어
|
||||
|
||||
OLED 및 AMOLED 패널은 완전 검정(`#000000`)을 렌더링할 때 개별 서브픽셀의 전원을 완전히 차단한다.
|
||||
|
||||
### 13.1 퍼플 스미어링(Purple Smear / Black Ghosting)의 메커니즘
|
||||
- 꺼져 있던 다이오드가 유채색이나 회색으로 다시 켜지는 과정(Turn-on Response Time)에서 수 밀리초의 물리적 턴온 딜레이가 발생한다.
|
||||
- 사용자가 스크롤할 때 `#000000` 배경과 인접 픽셀 사이에 보라색 잔상(Purple Trail)과 번짐이 발생하는 치명적 시각 결함이 야기된다.
|
||||
|
||||
### 13.2 5% 틴티드 다크 서피스 룰 (The 5% Tinted Black Rule)
|
||||
- 기본 창 배경을 순수 블랙(`#000000`) 대신 RGB 채널 각 10 이상(약 4~6% 휘도)인 `#0B0B10`, `#121212`, `#14141C`로 설정한다.
|
||||
- 픽셀을 완전히 끄지 않고 미세 사전 바이어스(Pre-biased) 전류 상태로 유지하여, 스미어링을 0ms 수준으로 소멸시키면서도 깊고 우아한 모노크롬 다크 테마 감성을 완성한다.
|
||||
|
||||
---
|
||||
|
||||
## 14. HiDPI 서브픽셀 스냅 및 레이아웃 라운딩 (WPF Display Engine)
|
||||
|
||||
현대 윈도우 환경은 96 DPI(100%) 외에도 120 DPI(125%), 144 DPI(150%), 192 DPI(200%)의 다양한 HiDPI 분수 배율 디스플레이를 사용한다.
|
||||
|
||||
### 14.1 서브픽셀 번짐(Subpixel Blurring) 차단
|
||||
- 부동소수점 좌표 연산으로 인해 보더 선(1px)이나 텍스트 베이스라인이 픽셀 경계선 사이에 걸치면 흐릿한 안티앨리어싱 안개(Blurry Ghost Border)가 발생한다.
|
||||
- **필수 공학 조치**:
|
||||
1. `Window.UseLayoutRounding="True"`: 레이아웃 엔진이 모든 레이아웃 치수를 물리적 장치 픽셀 경계로 반올림.
|
||||
2. `UIElement.SnapsToDevicePixels="True"`: 컨트롤 렌더링 펜이 서브픽셀 안티앨리어싱 없이 날카로운 1픽셀을 렌더링하도록 강제.
|
||||
|
||||
---
|
||||
|
||||
## 15. WCAG 2.2 SC 1.4.11 비텍스트 대비 (Non-Text Contrast)
|
||||
|
||||
텍스트뿐만 아니라, 사용자가 인터랙션할 수 있는 모든 UI 컴포넌트의 시각적 경계(Border)와 상태 표시기(Focus Visual, Selection)는 인접한 배경에 대해 **최소 3.0:1 이상의 명도 대비**를 확보해야 한다.
|
||||
- 버튼/입력창의 외곽선이 배경과 구별되지 않으면 저시력 사용자는 타깃의 위치와 크기를 인지할 수 없다.
|
||||
- 라이트 모드에서 흔히 발생하는 연회색 보더(`#E0E0E0`, `#AEB4C4` 등, 대비 1.5~2.2:1) 결함을 차단하고 최소 `#858B9C` 이상으로 명도를 보정하여 3.0:1을 엄수한다.
|
||||
|
||||
---
|
||||
|
||||
## 16. 전정기관 장애 보호 및 움직임 감소 (Reduced Motion WCAG 2.2 SC 2.3.3)
|
||||
|
||||
전 세계 수백만 명의 사용자가 전정 신경계 질환(Vestibular Disorders), 현기증(Vertigo), 메니에르병, 편두통을 겪고 있으며, 화면의 급격한 패닝·줌·시차(Parallax) 이동에 의해 심각한 오심과 균형 감각 상실을 느낀다.
|
||||
|
||||
### 16.1 움직임 감소 3대 불변식
|
||||
1. **OS 애니메이션 설정 존중**: Windows의 "창 애니메이션 끄기"(`SystemParameters.ClientAreaAnimation == false`) 설정 시 모든 이동 애니메이션을 즉시 비활성화하거나 `Duration="0:0:0"`으로 단축한다.
|
||||
2. **최대 시간 상한(Duration Bound)**: UI 상태 전환 애니메이션은 최대 300ms를 초과하지 않으며, 권장 표준은 150ms~250ms 감속 곡선(`CubicEase Ease="EaseOut"`)을 사용한다.
|
||||
3. **루핑 모션 배제**: 다운로드 프로그레스바의 인디터미너트 애니메이션을 제외하고는 사용자 주의를 분산시키는 무한 반복 펄스/바운스 효과를 엄격히 금지한다.
|
||||
|
||||
---
|
||||
|
||||
## 17. 포커스 비가림 (Focus Not Obscured WCAG 2.2 SC 2.4.11 / 2.4.12)
|
||||
|
||||
키보드 탐색 시 사용자가 현재 포커스를 둔 컨트롤이 고정 헤더, 하단 플로팅 바, 스낵바 또는 스크롤 뷰포트 경계에 가려지는 현상을 원천 방지한다.
|
||||
- **Level AA (SC 2.4.11)**: 포커스 요소가 다른 컴포넌트에 완전히 가려지지 않아야 함.
|
||||
- **Level AAA (SC 2.4.12)**: 포커스 요소의 1픽셀도 가려지지 않고 100% 온전히 보여야 함.
|
||||
- **WPF 구현 계약**: `ScrollViewer` 내부 항목이 포커스를 받을 때 `RequestBringIntoView()`가 정상 호출되도록 컨테이너 여백(Padding/Margin)과 가상화(Virtualization) 스크롤 오프셋을 안정적으로 확보한다.
|
||||
|
||||
---
|
||||
|
||||
## 18. 모달 다이얼로그 포커스 트랩 (Focus Trap) 및 라이트 디스미스 (Light Dismiss)
|
||||
|
||||
모달 창, 설정 다이얼로그, 팝업 메뉴가 열렸을 때 키보드 사용자의 통제권을 보장하는 표준 인터랙션 패턴이다.
|
||||
|
||||
### 18.1 포커스 트랩 (Focus Trapping)
|
||||
- 모달 대화상자 내부에서는 `Tab` / `Shift+Tab` 키 탐색이 모달 외부(부모 창의 주소창이나 백그라운드 버튼)로 빠져나가지 않고 대화상자 내부에서만 순환(`KeyboardNavigation.TabNavigation="Cycle"`)해야 한다.
|
||||
|
||||
### 18.2 라이트 디스미스 및 포커스 복원 (Light Dismiss & Restoration)
|
||||
- `Escape` 키 입력 시 열려 있는 모달, 메뉴, 팝업이 즉시 안전하게 닫혀야 한다.
|
||||
- 모달이 닫힌 직후 포커스는 모달을 호출했던 원래의 트리거 버튼(Trigger Element)으로 100% 자동 복원되어야 한다.
|
||||
|
||||
---
|
||||
|
||||
## 19. 인지 부하 이론 (Sweller's CLT) 및 게슈탈트 시각 법칙
|
||||
|
||||
존 스웰러(John Sweller)의 인지 부하 이론(Cognitive Load Theory)에 따라, 사용자의 작업 기억(Working Memory) 용량을 불필요한 시각적 잡음에 낭비하지 않도록 설계한다.
|
||||
|
||||
### 19.1 외재적 인지 부하(Extraneous Cognitive Load) 제거
|
||||
- 과도한 1px 분할선(Dividers)과 박스 안의 박스(Nested Cards)는 시각적 파편화를 유발한다.
|
||||
- **게슈탈트 근접성의 원리(Law of Proximity)**: 분할선 대신 스위스 8pt/16pt 여백의 완급 조절만으로 연관된 정보 그룹을 청킹(Chunking)한다.
|
||||
- **게슈탈트 유사성의 원리(Law of Similarity)**: 동일한 위계의 액션 버튼(재생, 폴더, 삭제)은 동일한 크기(26~32px)와 형태 언어를 유지한다.
|
||||
|
||||
---
|
||||
|
||||
## 20. 독서 인체공학 (Reading Ergonomics) 및 최적 행폭 (CPL 50~75자)
|
||||
|
||||
화면 본문 텍스트의 길이가 너무 길면 사용자의 안구가 행 끝에서 다음 행의 시작점으로 이동할 때(Saccadic Return Sweep) 길을 잃어 독서 피로가 급격히 증가한다.
|
||||
- **최적 행폭 (Characters Per Line)**: 한 줄당 영문 기준 50~75자, 한글 기준 30~45자 (최대 80자를 넘지 않도록 `MaxWidth` 제약).
|
||||
- **모듈러 타이포그래피 스케일 (Modular Scale 1.25 Major Third)**:
|
||||
- Caption: 11px
|
||||
- Body: 13px ~ 14px
|
||||
- Subtitle: 17px
|
||||
- Title: 21px
|
||||
- Display: 26px+
|
||||
- 행간(Line Height)은 글자 크기의 1.5배 이상을 유지하여 텍스트의 시각적 뭉침을 원천 차단한다.
|
||||
|
||||
---
|
||||
|
||||
## 21. 키스트로크 레벨 모델 (KLM) 및 HCI 정량 예측 공학
|
||||
|
||||
스튜어트 카드(Stuart Card), 토마스 모란(Thomas Moran), 앨런 뉴얼(Allen Newell)이 1980/1983년에 확립한 KLM(Keystroke-Level Model)은 숙련된 사용자가 인터페이스에서 작업을 완수하는 데 걸리는 물리적·인지적 실행 시간(\(T_{execute}\))을 단위 연산자(Atomic Operators)의 합으로 정량 예측한다:
|
||||
|
||||
\[
|
||||
T_{execute} = \sum T_K + \sum T_P + \sum T_H + \sum T_D + \sum T_M + \sum T_R
|
||||
\]
|
||||
|
||||
### 21.1 KLM 6대 단위 연산자 상수
|
||||
1. **\(K\) (Keystroke / Keying)**: \(0.20\text{s}\) (숙련 타자) ~ \(0.28\text{s}\) (일반인).
|
||||
2. **\(P\) (Pointing to Target)**: \(1.10\text{s}\) (피츠의 법칙 기반 마우스 커서 이동 평균 시간).
|
||||
3. **\(H\) (Homing)**: \(0.40\text{s}\) (키보드와 마우스 간 손의 물리적 이동 시간).
|
||||
4. **\(M\) (Mental Preparation)**: \(1.20\text{s} \sim 1.35\text{s}\) (다음 행동을 결정하고 시각적으로 탐색하는 뇌의 인지 준비 시간).
|
||||
5. **\(R\) (System Response)**: \(< 0.10\text{s}\) (즉각적 지각 반응 한계인 100ms 미만이어야 함).
|
||||
|
||||
### 21.2 Paca 핫키 및 단축키 최적화 공학
|
||||
- 마우스 조작(\(P + H = 1.50\text{s}\)) 대신 전역 키보드 단축키(`Ctrl+L`, `Ctrl+J`, `Ctrl+D`, `Ctrl+H`, `Esc`)를 제공함으로써 포인팅과 호밍 시간을 제거(\(1.5\text{s} \to 0.2\text{s}\))한다.
|
||||
- 50개 대량 다운로드 배치 조작 시 총 작업 시간이 약 75초 이상 단축되는 극적인 생산성 혁신을 달성한다.
|
||||
|
||||
---
|
||||
|
||||
## 22. 댄 섀퍼(Dan Saffer)의 마이크로인터랙션 4단계 피드백 루프
|
||||
|
||||
댄 섀퍼의 2013년 기념비적 저작 *Microinteractions: Designing with Details*에 기반하여, Paca의 모든 상태 전환과 미세 상호작용은 4단계 구조를 엄격히 준수한다:
|
||||
|
||||
1. **Trigger (트리거)**:
|
||||
- 사용자 트리거: 버튼 클릭, 단축키 입력, URL 드래그 앤 드롭.
|
||||
- 시스템 트리거: 미디어 스트림 스니핑 감지, 다운로드 완료, 디스크 용량 경고.
|
||||
2. **Rules (규칙)**:
|
||||
- 인터랙션 진행 조건과 상태 머신(Pending -> Downloading -> Remuxing -> Completed / Failed).
|
||||
3. **Feedback (피드백)**:
|
||||
- 시각: 프로그레스바 진행률 애니메이션 + OpenType `tnum` 고정폭 수치 갱신 + 테두리 펄스 글로우.
|
||||
- 청각/OS: Windows Toast 알림 및 완료 액션 단추.
|
||||
- 접근성: `AutomationProperties.LiveSetting="Assertive"`를 통한 화면 낭독기 실시간 발화.
|
||||
4. **Loops & Modes (루프와 모드)**:
|
||||
- 네트워크 간헐적 끊김 시 지수 백오프(Exponential Backoff) 재시도 루프.
|
||||
- 일시정지 및 이어받기 모드 전환.
|
||||
|
||||
---
|
||||
|
||||
## 23. 비웹 정보통신기술 WCAG2ICT 및 데스크톱 1차원 리플로우 (Reflow SC 1.4.10)
|
||||
|
||||
W3C의 WCAG2ICT(Guidance on Applying WCAG to Non-Web ICT)에 따라, 웹의 반응형 미디어 쿼리가 없는 WPF 네이티브 데스크톱 환경에서도 가로 스크롤 없는 **단일 세로 스크롤(1D Vertical Scroll)** 리플로우를 보증한다:
|
||||
|
||||
### 23.1 320px/400% 줌 등가 리플로우
|
||||
- 저시력 사용자가 Windows 돋보기(`Win + Plus`) 또는 OS DPI 배율을 200~300%로 확대했을 때, 가로 스크롤바가 발생하여 콘텐츠를 읽기 위해 좌우로 왕복해야 하는 인지 피로를 차단한다.
|
||||
- **WPF 구현 조치**:
|
||||
- 카드 및 패널 컨테이너에 `ScrollViewer.HorizontalScrollBarVisibility="Disabled"` 강제.
|
||||
- 모든 텍스트 블록에 `TextWrapping="Wrap"` 또는 `TextTrimming="CharacterEllipsis"` 강제.
|
||||
- 고정 절대 너비(`Width="800"`) 하드코딩을 배제하고 `Grid` 비율(`*`) 및 `DockPanel` 신축 레이아웃 적용.
|
||||
|
||||
---
|
||||
|
||||
## 24. 결론: Paca 25대 자동화 디자인/접근성 감사 게이트 매핑 (The 25 Grand Design Commandments)
|
||||
|
||||
상기 이론들은 다음 25대 게이트 체계로 종합되어 `tests/Paca.Tests/E2E/VisualDesignGateTests.cs`와 `tests/Paca.Tests/Infrastructure/TestVerificationSystemGateTests.cs`에서 100% 자동 검증된다:
|
||||
|
||||
1. **중앙 정렬 및 대칭성 무결성 (Center Alignment)**: 오차 0px 기계적 정렬
|
||||
2. **컨테이너 오버플로우 방지 (Zero Overflow)**: `CharacterEllipsis` 강제
|
||||
3. **WCAG 2.1/2.2 AA/AAA 상대 휘도 & APCA 지각 대비**: 4.5:1 / 7.0:1 / Lc 60+
|
||||
4. **인풋 필드 규격 및 내부 패딩 (Input Ergonomics)**: `Padding="8,6"`, 높이 36~44px
|
||||
5. **아이콘-텍스트 수직 정렬 정합성 (Icon-Text Alignment)**: `VerticalAlignment="Center"` 100%
|
||||
6. **타이포그래피 계층구조 (Typography Hierarchy)**: 모듈러 스케일 엄수
|
||||
7. **Flexbox / Grid 레이아웃 왜곡 방지**: 0px 찌그러짐 방지
|
||||
8. **클릭 타깃 최소 면적 (Hit Target 32~44px+)**: Fitts 인체공학 면적 확보
|
||||
9. **디자인 철학 준수 (Designpaca / Swiss / Modern Minimalist)**: 3대 토큰 준수
|
||||
10. **모달 오버레이 무결성 및 시각적 안전성 (Dim Overlay)**: 딤 알파 및 포커스 차단
|
||||
11. **WCAG 2.2 SC 2.5.8 & 2.5.5 타깃 크기 (24px/44px)**: 인접 충돌 없는 최소 면적
|
||||
12. **WCAG 2.2 SC 2.4.13 포커스 외형 2px 둘레 보증**: 2px 링 및 3:1 대비
|
||||
13. **다크모드 광륜/난시 생리학적 보호 (Halation Shield)**: #000000 위 #FFFFFF 차단
|
||||
14. **스위스 8pt/4pt 베이스라인 그리드 불변식 (Multiples of 4px)**: 홀수 픽셀 금지
|
||||
15. **마이크로 타이포그래피 및 고정폭 숫자 안티지터 (`tnum`)**: Tabular 정렬 강제
|
||||
16. **피츠의 법칙 (Fitts's Law) 가장자리 무한 타깃**: 캡션 버튼 마진 0 밀착
|
||||
17. **힉-하이먼 법칙 및 밀러의 법칙 인지 밀도 최적화**: $7 \pm 2$ 툴바 슬림화 & 3-Chunk
|
||||
18. **WCAG 2.2 SC 2.5.7 드래그 조작 단일 클릭/키보드 대안 보증**: 컨텍스트 메뉴 대안
|
||||
19. **WCAG 2.2 SC 3.3.7 중복 입력 방지 (Redundant Entry)**: 자동완성 및 히스토리
|
||||
20. **Microsoft UIA FastPass 스크린 리더 계약 (AutomationProperties)**: Accessible Name 전수 매핑
|
||||
21. **윈도우 고대비 모드(WHCM / Forced Colors) WCAG AAA 7.0:1**: 모든 시맨틱 브러시 7:1 보증
|
||||
22. **전정기관 보호 움직임 감소(Reduced Motion SC 2.3.3)**: 애니메이션 지속시간 상한(<=300ms)
|
||||
23. **포커스 비가림(Focus Not Obscured SC 2.4.11/2.4.12)**: 스크롤 및 고정 요소 가림 차단
|
||||
24. **모달 포커스 트랩 및 Esc 안전 복원**: 대화상자 포커스 순환 및 원래 위치 복원
|
||||
25. **게슈탈트 근접성 및 최적 행폭(CPL 50~75) 독서 인체공학**: 안구 피로 방지 MaxWidth 제약
|
||||
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue