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:
Yun Chan 2026-09-14 00:39:44 +09:00
parent a88aafa1e5
commit 0e568f1f0a
975 changed files with 130593 additions and 16783 deletions

163
AGENTS.md
View file

@ -1,90 +1,115 @@
# AGENTS.md — VideoDownloader 에이전트 작업 계약
# AGENTS.md — Paca 에이전트 작업 계약 (SSOT)
이 파일은 도구 중립 표준(AGENTS.md)이다. Claude Code · Codex · Cursor 등 어떤 코딩 에이전트든
작업 시작 시 이 파일을 읽고, 여기 적힌 명령·규약·완료 기준을 따른다.
Claude Code 는 `CLAUDE.md` 가 이 파일을 `@AGENTS.md` 로 임포트해 함께 읽는다.
> 모든 AI 코딩 에이전트(AGY, Claude Code, DeepSeek, Cursor 등) 공용 표준 계약.
> Claude Code는 `CLAUDE.md`의 `@AGENTS.md`, Cursor는 `.cursorrules`로 본 파일을 참조한다.
> 이론적 토대 및 상세 표준: `docs/TDD_THEORY_SSOT.md` (Paca TDD & 디자인 감사 SSOT).
## 1. 프로젝트 개요
---
브라우저 내장 데스크톱 영상 다운로더 + 모바일 컴패니언. 앱 내 브라우저가 재생 중인 미디어
(HLS/DASH/MP4)를 감지 → 쿠키·Referer 를 물려받아 다운로드 → 내장 서버로 휴대폰에 스트리밍/전송.
## 0. TDD 절대주의 헌법 (The Supreme Law of TDD)
| 프로젝트 | TFM | 역할 |
|---|---|---|
| `VideoDownloader.Core` | net8.0 | 다운로드 엔진 (HLS/DASH 파싱, AES-128, 병렬·이어받기, 감지, ffmpeg 리먹스) |
| `VideoDownloader.Browser` | net8.0-windows | WebView2 탭 컴포넌트 |
| `VideoDownloader.App` | net8.0-windows | 메인 WPF 앱 (브라우저 + 다운로드 UI + 서버 호스팅) |
| `VideoDownloader.Server` | net8.0 | ASP.NET 라이브러리. App 안에서 기동, 모바일/웹에 API 제공 |
| `VideoDownloader.Mobile` | net10.0-android (+ios on macOS) | MAUI 컴패니언 |
| `VideoDownloader.Mobile.Core` | net8.0 | 모바일 공용 로직 (UI 없이 테스트 가능하게 분리) |
| `VideoDownloader.Avalonia` | net8.0 | macOS/Linux 셸 (진행 중) |
| `VideoDownloader.Cli` | net8.0 | 엔진 검증용 개발 도구 |
| `VideoDownloader.Tests` | net8.0-windows | xUnit. Mobile 을 제외한 전 영역 + E2E |
1. **테스트 없는 코드는 존재하지 않는다 (No Production Code Without RED)**:
- 실패하는 자동화 테스트(RED)가 존재하지 않는 한, 단 한 줄의 프로덕션 코드도 추가하거나 수정할 수 없다.
- Robert C. Martin의 TDD 3대 법칙(Three Laws)을 엄수한다: 실패를 증명할 최소 테스트 작성 → 컴파일 에러를 포함한 실패 확인 → 오직 통과만을 위한 최소 구현.
2. **기계적 검증 없는 디자인은 결함이다 (Strict Design Audit in RED)**:
- 모든 UI/UX 요소는 눈대중이 아닌 기계적 테스트 게이트(`VisualDesignGateTests`, `IconGlyphDesignSystemTests`, `UiContractUseCasesMegaPipelineTests`)로 사전에 RED화되고 검증되어야 한다.
3. **RED 체계의 수명주기 관리 (Pruning & Scenario Evolution)**:
- 무의미한 RED 남발(Red Inflation)을 금지한다.
- 사소한 단편 단정문은 과감히 추리거나, 실제 사용자 행동(입력창 타이핑, 버튼 클릭, 옵션 변경, 진행률 표시)이 결합된 **복합 시나리오(End-to-End User Journey)**로 통폐합한다.
## 2. 명령 (이 명령들이 진실이다 — 추측하지 말 것)
---
## 1. 아키텍처 매핑 (Pitchfork Layout: `src/` + `tests/`)
| 프로젝트 | TFM | 위치 | 역할 |
|---|---|---|---|
| `Paca.Core` | net8.0 | `src/Paca.Core` | 다운로드 엔진 (HLS/DASH, AES-128, 병렬/이어받기, ffmpeg) |
| `Paca.Browser` | net8.0-windows | `src/Paca.Browser` | WebView2 탭 컴포넌트, 브라우저 확장 프로그램 가로채기 |
| `Paca.App` | net8.0-windows | `src/Paca.App` | 메인 WPF 데스크톱 앱 (UI + 서버 호스팅, 반응형 테마) |
| `Paca.Server` | net8.0 | `src/Paca.Server` | 내장 ASP.NET Core API 서버 |
| `Paca.Mobile` / `.Mobile.Core` | net10.0-android / net8.0;net10.0 | `src/Paca.Mobile` / `src/Paca.Mobile.Core` | MAUI 컴패니언 앱 및 공용 로직 |
| `Paca.Avalonia` | net8.0 | `src/Paca.Avalonia` | macOS/Linux 셸 |
| `Paca.Cli` | net8.0 | `src/Paca.Cli` | CLI 도구 |
| `Paca.Tests` | net8.0-windows | `tests/Paca.Tests` | xUnit 전체 테스트 (1,886+ 건 전수 무결성) |
---
## 2. 핵심 실행 명령
```powershell
dotnet test VideoDownloader.Tests # 전체 검증. 증분 ~13초, 현재 180/180 통과
dotnet build VideoDownloader.App # 데스크톱 빌드
dotnet run --project VideoDownloader.App # 데스크톱 실행
dotnet build VideoDownloader.Mobile -f net10.0-android # 모바일 (MAUI 워크로드 필요)
./build/publish.ps1 -Config Release -Version 1.0.0 # Windows 설치자 → out/
bash build/remote/build-remote.sh all # macOS/Linux 원격 빌드 → out/remote/
dotnet test tests/Paca.Tests # 전체 검증 (1,886건 전수 PASS)
dotnet test tests/Paca.Tests --filter "FullyQualifiedName~<이름>" # 단건 검증
dotnet build src/Paca.App # 데스크톱 빌드
# GUI 앱 실행 (WMI 세션 분리 — 세션 종료 후 창 유지 필수)
Stop-Process -Name 'Paca' -Force -ErrorAction SilentlyContinue
powershell -NoProfile -Command "Start-Process powershell -ArgumentList '-NoProfile','-WindowStyle','Hidden','-ExecutionPolicy','Bypass','-File','C:\Users\encep\.gemini\agy-gui-launch.ps1','-ExePath','D:\workspace\videodownloader\src\Paca.App\bin\Debug\net8.0-windows\win-x64\Paca.exe','-ProcessName','Paca'"
Start-Sleep -Seconds 120
Get-Content C:\Users\encep\.gemini\agy-gui-launch.log -Tail 3
```
- 솔루션 전체 빌드(`dotnet build VideoDownloader.slnx`)는 MAUI 워크로드가 있어야 통과한다.
워크로드 없이 작업할 땐 프로젝트를 개별 지정한다.
- 단위 테스트 하나만: `dotnet test VideoDownloader.Tests --filter "FullyQualifiedName~HlsMuxerWiring"`
- 환경: Windows 11 · .NET 8/10 SDK 공존 · ffmpeg PATH 필요 · 셸은 PowerShell 7 (Git Bash 도 사용 가능)
---
## 3. 작업 방식 — TDD 폐쇄루프
## 3. 안드레 카파시 4대 원칙 (Karpathy Principles)
이 저장소는 **RED → GREEN → 증거** 사이클로 개발해 왔다. 이 순서를 지킨다.
1. **Think Before Coding**: 모호하면 추측 금지. 코드 위치를 확인하고, 3개 이상 파일 수정 시 플랜 수립.
2. **Simplicity First**: 오버엔지니어링 금지. RED를 GREEN으로 바꾸는 최소한의 코드만 작성.
3. **Surgical Changes**: 요청 외 주변 코드·주석·공백 무단 수정 금지. 폭발 반경(Blast Radius) 최소화.
4. **Goal-Driven Closed Loop**: "다 됐다" 선언 금지. 기계적 검증(Exit 0) 통과 전까지 자율 루프 유지.
1. **RED**: 변경 전에 실패하는 테스트를 먼저 쓴다. 실패를 눈으로 확인한다.
2. **GREEN**: 최소 구현으로 통과시킨다. `dotnet test` 전체가 통과해야 한다.
3. **증거**: UI·플랫폼 동작을 바꿨다면 테스트만으로 부족하다. 실제 앱 실행/에뮬레이터/스크린샷으로
확인하고, 무엇을 어떻게 확인했는지 보고에 적는다.
4. **문서 동기화**: 계획 대비 구현 상태는 `docs/IMPLEMENTATION_AUDIT.md`, 작업 항목은
`docs/BACKLOG.md` 체크박스에 반영한다.
---
## 4. 완료 기준 (Definition of Done)
## 4. 저가형 모델(Flash/DeepSeek/Lite) 하네스 수칙
아래를 모두 만족하기 전에는 "완료"라고 보고하지 않는다.
- **Token Diet**: 80KB+ 대용량 파일 전체 읽기 금지. `grep_search`로 위치 확인 후 라인 슬라이스(`view_file`).
- **Anti-Cheating Guard**: 테스트 삭제, `[Fact(Skip="...")]`, 빈 `catch { }` 엄격 금지 (위반 시 즉시 실패).
- **Error Hill-Climbing**: 컴파일 에러(`CSxxxx`) 및 단정 실패 diff의 파일:라인을 1~2턴 내 정밀 타격.
- **Subagent Hierarchy**: 넓은 범위 탐색/조사는 초경량 서브에이전트(`invoke_subagent`)로 격리.
- [ ] `dotnet test VideoDownloader.Tests` — **실패 0건**. 테스트 수는 줄지 않는다(180 이상).
- [ ] 빌드 **오류 0**. 새로 만든 경고를 남기지 않는다.
(기존 경고: `MainWindow.xaml.cs`·테스트의 CS8602 몇 건, xUnit 분석기 경고 — 늘리지 말 것)
- [ ] 동작을 바꿨으면 그 동작을 검증하는 테스트가 있다.
- [ ] UI/플랫폼 변경이면 실행 증거가 있다.
- [ ] 관련 문서(`docs/`)를 갱신했다.
---
실패한 것을 통과한 것처럼 보고하지 않는다. 막혔으면 막혔다고 쓴다.
## 5. TDD 폐쇄 루프 & 초고강도 디자인 감사 완료 기준 (DoD)
## 5. 코드 규약
### 5.1 25대 디자인/인터랙션/접근성 감사 게이트 (Strict Design & Interaction Gate)
1. **중앙 정렬 및 시각적 치우침 방지**: 헤더, 툴바, 팝업의 중앙 정렬 요소 오차 0px.
2. **컨테이너 오버플로우 방지**: 가로 스크롤 버그(`scrollWidth > clientWidth`) 금지, `TextTrimming="CharacterEllipsis"` 강제.
3. **WCAG 2.1/2.2 AA/AAA & APCA 지각 대비**: 텍스트-배경 대비 AA 4.5:1, 고대비 AAA 7.0:1, APCA Lc 60+ 엄수.
4. **인풋 필드 규격 및 내부 패딩**: 텍스트 박스 패딩 `Padding="8,6"` 이상, 최소 높이 36px~44px 유지.
5. **아이콘-텍스트 수직 정렬**: `VerticalAlignment="Center"` 및 폰트 베이스라인 정합성 100% 일치.
6. **타이포그래피 계층구조**: H1(24~32px) → H2(18~22px) → Body(13~15px) → Caption(11~12px) 토큰 일치.
7. **Flexbox / Grid 레이아웃 왜곡 방지**: 컬럼 비율 깨짐 및 0픽셀 축소 방지.
8. **클릭 타깃 최소 면적**: 기본 인터랙션 요소 최소 32x32px 이상 확보.
9. **디자인 철학 일치**: Designpaca / Swiss Typography / Modern Minimalist 토큰 일치.
10. **모달 오버레이 무결성**: 딤 오버레이 및 포커스 트랩 보장.
11. **WCAG 2.2 타깃 크기 (SC 2.5.8/2.5.5)**: 24x24px 최소 타깃 엄수 및 간격 원 중첩 방지, 중요 액션 44x44px 준수.
12. **WCAG 2.2 포커스 시인성 (SC 2.4.11/2.4.13)**: 포커스 링 최소 2px 둘레 및 3:1 대비비, 가림(Obscured) 방지.
13. **다크모드 광륜/난시 생리학적 보호**: 완전 검정(#000000) 위 순백(#FFFFFF) 직접 배치 금지, 표면 표고 및 오프화이트(#E2E8F0) 강제.
14. **스위스 8pt/4pt 그리드 불변식**: 마진/패딩/간격 4px 단위 배수 엄수 (7px/9px 등 분수/홀수 픽셀 금지).
15. **마이크로 타이포그래피 안티지터**: 속도/시간/카운터 실시간 갱신 요소 OpenType `Typography.NumeralAlignment="Tabular"`(`tnum`) 강제.
16. **피츠의 법칙 (Fitts's Law) 가장자리 무한 타깃**: 창 캡션 단추 모서리 밀착(마진 0), 주 액션 CTA 타깃 면적 최적화.
17. **힉-하이먼 & 밀러의 법칙 인지 밀도**: 툴바 단일 계층 버튼 $7 \pm 2$개 제한, 서랍(Drawer) 위계화 및 3단 카드 청크 분할.
18. **WCAG 2.2 드래그 대안 (SC 2.5.7)**: 드래그 탭/큐 이동에 대한 단일 클릭 컨텍스트 메뉴 및 키보드 단축키 대안 보증.
19. **WCAG 2.2 중복 입력 방지 (SC 3.3.7)**: 히스토리 피커, 클립보드 자동 인식, DPAPI CredentialVault 자동 채움 지원.
20. **Microsoft UIA FastPass 스크린 리더 계약**: 모든 인터랙티브 컨트롤 `AutomationProperties.Name` 매핑 및 장식 요소 배제.
21. **윈도우 고대비 모드(WHCM / Forced Colors) WCAG AAA 7.0:1**: 시맨틱 브러시 7.0: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 제약 및 여백 기반 시각 청킹.
- **C#**: file-scoped namespace, 4스페이스, Allman 중괄호, `_camelCase` private 필드, nullable enable.
세부는 `.editorconfig` 가 강제한다. 공통 빌드 속성은 `Directory.Build.props`.
- **주석·커밋 메시지·문서는 한국어.** 기존 코드가 한국어 주석이므로 섞지 않는다.
- **테스트**: xUnit. 파일은 `VideoDownloader.Tests/<영역>/<대상>Tests.cs`.
영역 = `Browser` · `E2E` · `Infrastructure` · `Mobile` · `Platform` · `Server`.
- 에러를 삼키지 않는다. 근본 원인을 고친다. 빈 `catch`, 가짜 폴백 데이터 금지.
### 5.2 자율 완료 체크리스트 (Definition of Done)
- [ ] `dotnet test tests/Paca.Tests` 실패 0건, 건너뜀 0건 (1,886 전수 통과)
- [ ] 빌드 에러 0건, 신규 컴파일러 경고 0건
- [ ] 초고강도 디자인 감사 게이트(`VisualDesignGateTests`) 100% 통과
- [ ] WMI 분리 런처 기반 GUI 실창 렌더링 검증 완료 (`MainWindowHandle != 0`)
- [ ] 문서 동기화 완료 (`docs/TDD_THEORY_SSOT.md`, `docs/IMPLEMENTATION_AUDIT.md`, `docs/BACKLOG.md`)
## 6. 경계 — 하지 말 것
---
- `.env` 를 커밋하거나 그 값을 출력·로그·문서에 남기지 않는다. 실제 Cloudflare 토큰과
빌드머신 SSH 비밀번호가 들어 있다. 템플릿은 `.env.example` 만 추적한다.
- `out/`, `publish/`, `bin/`, `obj/` 는 산출물이다. 커밋하지 않고, 내용을 소스로 참조하지 않는다.
- `VideoDownloader.App/Assets/*.min.js`(hls/dash/readability)는 서드파티 번들이다. 수정 금지.
- 사용자가 요청하지 않은 커밋·푸시·배포를 하지 않는다.
- 대규모 리팩터링을 임의로 시작하지 않는다. `MainWindow.xaml.cs` 는 86KB 로 비대하지만,
분할은 별도 승인 후 진행한다.
## 6. 절대 금기 (Boundaries)
## 7. 알아둘 함정
- **WebView2**: 탭마다 인스턴스, Environment 는 공유. dispose 순서를 어기면 UI 스레드에서 죽는다.
- **MAUI**: 링커가 안 싣는 타입은 런타임 `FileNotFoundException` 으로만 드러난다
(실제 사례: 모달 NavigationPage → `Xamarin.AndroidX.LocalBroadcastManager` 명시 참조로 해결).
- **ffmpeg**: stderr 를 읽지 않으면 파이프 버퍼가 차서 hang 한다. 취소 시 `Kill(entireProcessTree)`.
- **Avalonia 12.1** 은 .NET 10 SDK 를 요구한다. 8만 있으면 CS0103 으로 실패한다.
- 테스트는 `VD_DATA_DIR` 로 사용자 데이터 경로를 격리한다. 실제 사용자 폴더를 건드리지 않는다.
- `.env` 커밋/노출 절대 금지 (Cloudflare 토큰, SSH 암호 보호).
- `Paca.App/Assets/*.min.js` 서드파티 번들 수정 금지.
- 사용자 승인 없는 임의 커밋/푸시/배포 금지.
- WebView2: dispose 후 이벤트 콜백 방어 (`null` 체크 + `try`).
- 외부 프로세스: `ProcessModels.cs` 헬퍼 필수 (stderr 동시 드레인 + 전체 프로세스 트리 킬).
- 테스트 격리: 사용자 경로 접근 시 `VD_DATA_DIR` 환경변수 필수. 외부 제3자 서비스 장애에 깨지지 않도록 테스트 더블/오프라인 피스처 방어 구축.