docs(ads): Yandex 광고 제거 요구사항과 검증을 기록한다

This commit is contained in:
Yu Sung
2026-10-13 16:01:15 +09:00
parent 9478565a04
commit 8f51b2a57a
3 changed files with 531 additions and 0 deletions
@@ -0,0 +1,134 @@
# Yandex 광고 잔여 참조 제거 PRD
## 문서 정보
| 항목 | 내용 |
|---|---|
| 문서 상태 | 코드 구현 완료, 수동 QA 대기 |
| 작성일 / 최종 수정일 | 2026-10-13 |
| 대상 제품 | SodaLive iOS 운영·개발 타깃 |
| 작성자·결정권자 | 에이전트 작성 / 사용자 승인 |
| 관련 API Contract | 신규 작성 없음, 기존 캔 충전 계약 유지 |
| 관련 구현 계획 | [plan-task.md](plan-task.md) |
| 관련 review | [Phase 1 리뷰](reviews/phase1-yandex-reference-removal.md) |
## 1. Overview
사용자가 Yandex SDK 의존성과 광고 ID 상수를 제거한 상태에서, 앱에 남은 초기화·배너·보상형 광고 코드와 프로젝트 참조를 제거한다. 캔 충전과 광고 유입 측정 설정은 유지한다. 문서 작성 후 사용자 승인을 받아 코드 제거를 수행했으며, 전체 수동 QA와 구현 완료 판정은 구분한다.
## 2. Problem Statement
아래는 구현 전 확인한 문제 상태다. 구현 후 결과는 §14와 계획의 Progress에 기록한다.
- `Podfile`, `Podfile.lock`, `Pods/Manifest.lock`에서 Yandex와 전용 하위 의존성은 제거됐고, 두 Constants 파일의 `YANDEX_*` 선언도 제거됐다.
- 앱에는 SDK import, 초기화, 삭제된 상수 참조 12곳, 배너 호출 11곳과 채팅 광고 사전 로딩이 남아 있다.
- 채팅 광고 표시 함수의 호출부는 없지만 잔여 채팅이 1회 이하일 때 사전 로딩하는 경로는 남아 있다.
- 이 상태는 제거 작업의 중간 상태다. 이번 문서 작성 단계에서 앱 빌드 실패를 실제 실행으로 확인한 것은 아니다.
## 3. Goals
### 3.1 제품 목표
- 앱 코드와 활성 프로젝트 설정에서 Yandex 의존 참조를 없앤다.
- 운영·개발 두 스킴의 빌드를 검증하고, 기존 캔 충전 동작을 보존한다.
### 3.2 UX 목표
- 11개 화면의 광고와 광고 전용 여백을 제거하되 콘텐츠·스크롤·이동 동작은 유지한다.
- 광고를 다른 UI로 대체하거나 주변 디자인을 개편하지 않는다.
## 4. Non-Goals
- 두 Info.plist 전체를 수정하지 않는다. 특히 `SKAdNetworkItems`, `NSAdvertisingAttributionReportEndpoint`는 명시적인 보존 대상이다.
- ATT/IDFA, 추적 권한 문구, AppsFlyer·Meta·Firebase 및 기타 SDK를 변경하지 않는다.
- 사용자가 완료한 Pod 의존성·상수 제거를 되돌리거나 재수행하지 않는다. `pod install`, 패키지 업데이트, 캐시 삭제는 계획에 포함하지 않는다.
- `Pods/**`, `generated/**`, 빌드 산출물을 직접 정리하지 않는다. 미사용 Yandex 리소스 스크립트·목록 10개는 현재 활성 복사 단계에서 참조되지 않으므로 제외한다.
- 현재 `objectVersion = 77`, 기존 작업물, 과거 광고 문서, 서버의 광고 보상 API와 운영 콘솔은 변경하지 않는다. worktree·브랜치 생성 및 커밋도 수행하지 않는다.
## 5. Target Users and Permissions
기존 라이브·커뮤니티·시리즈·알림·채팅 이용자에게 적용한다. 로그인, 권한, 구매 자격과 서버의 오류 정책은 변경하지 않는다.
## 6. 핵심 사용자 흐름
1. 사용자가 기존 화면에 진입하면 광고 없이 기존 콘텐츠를 탐색한다.
2. 채팅 쿼터가 부족하면 기존 10캔·20캔 구매 버튼을 사용한다.
3. 기존 구매 응답에 따라 쿼터와 캔 잔액을 갱신한다. 광고 사전 로딩·표시·광고 보상 구매 경로는 실행하지 않는다.
## 7. 정보 구조와 라우팅
신규 화면이나 라우팅 변경은 없다. 기존 View 파일에서 광고 소비 코드만 제거한다. 정확한 대상 파일은 계획의 `P1-T1`~`P1-T3`에 기록한다.
## 8. 기능 요구사항
| ID | 상태 | 요구사항 | 수용 기준 | Goal 연결 |
|---|---|---|---|---|
| YAN-001 | 확정 | 배너 호출 11곳 제거 | 각 호출과 광고에만 붙은 modifier·빈 조건문을 제거하고 다른 콘텐츠는 유지 | P1-T1 |
| YAN-002 | 확정 | 보상형 광고 소비 코드 제거 | `showRewardedAdForChatQuota`, `prepareRewardedAdIfNeeded` 및 호출부 제거, 쿼터 갱신 유지 | P1-T2 |
| YAN-003 | 확정 | 광고 전용 선언 제거 | `ChatRoomQuotaChargeType.ad`, `quotaAdAction`, `rewardedAdLoadFailed`만 제거 | P1-T2 |
| YAN-004 | 확정 | SDK 연결과 공용 광고 코드 제거 | AppDelegate의 Yandex import·초기화·전용 주석 제거, 공용 파일 삭제, 두 타깃 프로젝트 참조 제거 | P1-T3 |
| YAN-005 | 확정 | 기존 충전·설정 보존 | 캔 구매 요청·UI와 두 plist, 마케팅 코드, Project Format 불변 | P1-T2, P1-GATE |
요구사항의 확정은 대화에서 합의한 범위를 뜻하며, 구현 착수 승인을 뜻하지 않는다. 문서 승인 전 코드 변경은 금지한다.
## 9. 반응형 기능 범위
기존 iOS 화면 지원 범위를 유지한다. 신규 크기 대응은 추가하지 않고 기존 지원 기기에서 광고 삭제 후 레이아웃을 확인한다.
## 10. UI/UX Expectations
- `LiveView`, `CharacterView`의 광고 전용 음수 padding과 라이브 상세·알림 설정의 광고 전용 frame/padding은 광고와 함께 제거한다.
- `SeriesMainByGenreView`의 광고만 감싼 조건문은 남기지 않는다. 다른 콘텐츠를 감싼 컨테이너나 공용 간격은 임의 변경하지 않는다.
- `ChatQuotaNoticeItemView`의 10캔/15채팅, 20캔/40채팅 버튼과 `quotaChatCount`를 유지한다. 화면 접근성·오류 안내·로딩 동작의 추가 변경은 없다.
## 11. API 계약
`TalkApi.purchaseChatQuota`의 `POST /api/chat/rooms/{roomId}/quota/purchase`와 Repository는 유지한다. 기존 `ChatQuotaPurchaseRequest`의 `container = "ios"`, `chargeType = "CAN"`, `canOption = "CAN_10" | "CAN_20"` 직렬화와 optional 선언을 변경하지 않는다. 광고 전용 enum case와 그 호출 경로만 제거하며, DTO나 구매 함수를 재설계하지 않는다.
신규 API 계약, 서버 변경, 별도 `api-contract.md`는 필요하지 않다.
## 12. 보안과 데이터 취급
인증·결제·잔액 저장 로직은 변경하지 않는다. 문서·검증 로그에 토큰이나 SDK 키를 복사하지 않는다. 수동 충전 QA에는 승인된 테스트 계정과 재화를 사용하며, 실제 운영 계정에서 비용을 발생시키는 검증은 별도 동의 없이 수행하지 않는다.
## 13. 성능과 품질 요구사항
- 저장소에 확인된 테스트 번들 타깃이 없으므로 이번 삭제만을 위한 테스트 인프라는 만들지 않는다. 정적 부재 검사, 보존 파일 대조, 두 스킴 빌드와 수동 QA를 사용한다.
- `rg` 결과는 종료 코드 1만 부재 성공으로 해석한다. 0은 잔존, 2는 검사 오류다.
- 미실행 빌드·수동 QA는 통과로 기록하지 않는다. 계정·기기 등 환경이 없으면 차단 사유와 미검증 범위를 남긴다.
## 14. 성공 기준
- [x] 앱 소스·활성 프로젝트·의존성 명세에 Yandex 참조가 없고 광고 전용 메서드·문구·enum case가 없다.
- [x] 두 plist와 기존 캔 구매 계약, 마케팅 흐름, 사용자 선행 변경이 보존된다.
- [x] `SodaLive`, `SodaLive-dev` Debug 빌드가 성공한다.
- [ ] 11개 화면의 콘텐츠·스크롤·이동과 광고 전용 빈 공간 제거, 두 캔 구매 경로를 확인한다.
- [x] 실제 검증 결과 및 구현 후 리뷰를 계획 문서에 연결한다. 미검증 항목은 명시한다.
2026-10-13: 코드 리뷰 APPROVE, 두 기기용 Debug 빌드와 개발용 시뮬레이터 Debug 빌드 성공. 실제 DTO 직렬화 3개 시나리오 통과, 보존 파일 13개의 SHA-256 일치. 전용 시뮬레이터에서 홈 화면과 ATT 팝업 표시를 확인했지만, 11개 수정 화면 전체와 실서버 캔 구매는 검증하지 않았다. 이 수동 QA 항목은 [blocked]로 남긴다.
## 15. Open Questions
추가 인터뷰가 필요한 요구사항 미결정은 없다. 2026-10-13 사용자가 문서를 승인하고 문서대로 진행하도록 요청했다. 테스트 계정·기기 접근 가능 여부는 구현 후 수동 검증의 환경 조건으로 기록한다.
## 16. 요구사항 추적표
| 요구사항 | API Contract | Phase / Goal | 자동 검증 | 수동 검증 |
|---|---|---|---|---|
| YAN-001 | 해당 없음 | 1 / P1-T1, P1-GATE | 배너 호출 부재·두 빌드 | 11개 화면 레이아웃·탐색 |
| YAN-002~003 | 기존 계약 유지, §11 | 1 / P1-T2, P1-GATE | 광고 경로 부재·구매 코드 대조 | 두 캔 옵션 성공·기존 실패 처리 |
| YAN-004~005 | 기존 계약 유지, §11 | 1 / P1-T3, P1-GATE | SDK·프로젝트 참조 부재·보존 파일 대조·두 빌드 | 앱 시작·충전·마케팅 변경 없음 |
## 17. Decision Log
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 |
|---|---|---|---|---|---|
| 2026-10-13 | DEC-001 | 확정 | SDK·상수 제거는 사용자 선행 작업으로 취급 | 사용자 보고와 현재 파일 확인 | 전체 범위 |
| 2026-10-13 | DEC-002 | 확정 | 두 SKAdNetwork 관련 키를 제거 대상에서 제외 | 사용자 직접 지시 | YAN-005 |
| 2026-10-13 | DEC-003 | 확정 | 문서만 작성 후 승인 대기, worktree 미사용 | 사용자 직접 지시 | 전체 실행 |
| 2026-10-13 | DEC-004 | 제안 | 두 plist 전체 및 미사용 Pods 생성물은 수정하지 않음 | 최소 변경·생성물 직접 수정 금지, 문서 승인 시 적용 | YAN-005 |
| 2026-10-13 | DEC-005 | 확정 | 문서 승인에 따라 구현 착수, DEC-004 보존 방안 승인 | 사용자 “승인”, “문서대로 진행한다” | 전체 실행 |
## 18. 변경 관리
범위 변경이나 추가 미결정이 생기면 이 문서의 Decision Log와 요구사항을 먼저 보강하고 `plan-task.md`에 반영한다. 기존 완료 기록은 덮어쓰지 않는다. 이전 배치·부분 제거 문서는 완료 이력으로 남기고, 이번 전체 잔여 참조 제거는 이 문서 쌍에서 이어서 관리한다.