diff --git a/docs/20260914_크리에이터_채널_공유/plan-task.md b/docs/20260914_크리에이터_채널_공유/plan-task.md new file mode 100644 index 00000000..0c561c77 --- /dev/null +++ b/docs/20260914_크리에이터_채널_공유/plan-task.md @@ -0,0 +1,335 @@ +# 크리에이터 채널 공유 구현 계획 + +| 문서 항목 | 내용 | +|---|---| +| 상태 | 구현 완료, 수동 검증 대기 | +| 작성일 | `2026-09-14` | +| 요구사항 기준 | `docs/20260914_크리에이터_채널_공유/prd.md` | +| API 기준 | 해당 없음 | +| 현재 Phase | Phase 1: 채널 공유 진입점과 공유 시트 연결 | +| 현재 활성 Goal | P1-GATE 수동 검증 | + +## 목표 + +내 채널과 다른 사람 채널에서 모두 기존 채널 공유 메시지와 OneLink URL을 iOS 공유 시트로 공유할 수 있게 한다. + +## 현재 상태 + +| Phase | 상태 | 완료 Task | 활성/다음 Goal | 차단 또는 남은 조건 | +|---:|---|---:|---|---| +| 1 | 수동 검증 대기 | `4/4` | `P1-GATE` | 실제 채널 진입 후 공유 시트 표시 수동 확인 필요 | + +- 동시에 하나의 미완료 goal만 운용한다. +- 완료된 Task와 검증 기록은 되돌리거나 삭제하지 않는다. +- 구현은 완료했으며, 사용자 요청에 따라 visual QA 없이 수동 테스트로 최종 확인한다. + +## 범위 + +### 포함 + +- 내 채널 title bar 우측 상단 공유 버튼 추가 계획 +- 다른 사람 채널 더보기 overlay 최상단 `채널 공유` 항목 추가 계획 +- 기존 `UserProfileViewModel.shareChannel`과 동일한 OneLink/메시지/`ActivityViewController` 공유 동작 연결 계획 +- 공유 실패 popup, 빌드, 수동 검증 기준 + +### 제외 + +- 새 공유 문구 또는 새 딥링크 계약 생성 +- 새 API 추가 +- 공유 URL 생성 로직의 공용 helper 분리 +- 커밋 생성 + +## 기술적 제약 + +- 기술 스택: Swift, SwiftUI, 기존 `ActivityViewController`, 기존 OneLink URL 생성 함수 +- 아키텍처: `CreatorChannelView`는 화면 상태와 공유 시트 표시 상태를 소유하고, title bar와 더보기 overlay는 action closure로 공유 동작을 호출한다. +- 데이터·보안: 공유 메시지에는 nickname과 OneLink URL만 포함하고 token·개인정보를 포함하지 않는다. +- 의존성: 신규 dependency를 추가하지 않는다. +- 계약: `af_dp=voiceon://`, `deep_link_value=channel`, `deep_link_sub5={creatorId}`를 기존 공유와 동일하게 사용한다. +- 검증: 테스트 타깃이 확인되지 않으므로 focused build와 수동 검증을 완료 증거로 사용한다. + +## 주요 대상 파일 + +### 수정 + +- `SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift` +- `SodaLive/Sources/V2/CreatorChannel/CreatorChannelViewModel.swift` +- `SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift` +- `SodaLive/Sources/Report/ProfileReportMenuView.swift` +- `SodaLive/Sources/I18n/I18n.swift` + +### 확인 + +- `SodaLive/Sources/Explorer/Profile/UserProfileView.swift` +- `SodaLive/Sources/Explorer/Profile/UserProfileViewModel.swift` +- `SodaLive/Sources/Common/ActivityViewController.swift` +- `docs/agent-guides/build-test-verification.md` + +## Phase 1: 채널 공유 진입점과 공유 시트 연결 + +**Phase 결과:** 내 채널 공유 버튼과 다른 사람 채널 더보기 공유 항목에서 동일한 채널 공유 시트를 열 수 있다. + +**선행조건:** `docs/20260914_크리에이터_채널_공유/prd.md`의 요구사항 확정. + +**Phase 완료 조건:** `P1-T1`~`P1-T4`와 `P1-GATE` 완료, 검증 기록 누적. + +### 구현 항목 + +#### Task 1.1 title bar 공유 진입점 정의 + +**Goal 실행 `P1-T1`:** 내 채널 title bar에 직접 공유 버튼을 표시할 수 있도록 `CreatorChannelTitleBar` contract를 확장한다. + +- **시작 조건:** `CCSHARE-001` 확정. +- **완료 증거:** title bar가 내 채널과 다른 사람 채널 action 구성을 분리하고 `ic_audio_content_share` 버튼을 표시할 수 있음. +- **범위 밖:** 공유 URL 생성과 `ActivityViewController` 표시. + +**Files:** + +- Modify: `SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift` +- Modify: `SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift` +- Test: 테스트 타깃 없음. 빌드와 수동 검증으로 대체. + +**TDD 예외 사유:** 현재 `SodaLive.xcodeproj/project.pbxproj` 기준으로 테스트 번들 타깃이 확인되지 않아 UI contract 변경은 focused build와 수동 검증으로 판정한다. + +**대체 검증 방법:** 구현 후 아래 명령과 수동 확인을 수행한다. + +```bash +rg "ic_audio_content_share|onTapShare|showsCreatorActions|CreatorChannelTitleBar" SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift +xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build +``` + +Expected: + +- `CreatorChannelTitleBar`에서 공유 action과 `ic_audio_content_share` 사용이 확인된다. +- `CreatorChannelView`가 내 채널 여부에 따라 공유 버튼 또는 더보기 버튼 구성을 전달한다. +- 빌드 exit code가 0이다. + +- [x] title bar contract에 공유 action을 추가한다. +- [x] 내 채널일 때 공유 버튼이 보이는 조건을 연결한다. +- [x] 다른 사람 채널일 때 기존 더보기 버튼이 유지되는지 확인한다. +- [x] `ic_audio_content_share` asset 이름을 그대로 사용한다. + +#### Task 1.2 공유 메시지와 공유 시트 상태 연결 + +**Goal 실행 `P1-T2`:** 기존 `UserProfileViewModel.shareChannel`과 동일한 공유 메시지·OneLink 생성·`ActivityViewController` 표시 흐름을 `CreatorChannelView`에 연결한다. + +- **시작 조건:** `P1-T1` 완료, `CCSHARE-002`, `CCSHARE-006`, `CCSHARE-007` 확정. +- **완료 증거:** 공유 action이 `creatorId`, `nickname`으로 기존 OneLink 파라미터를 만들고 공유 시트를 표시한다. +- **범위 밖:** 공유 helper 분리와 새 공유 문구 추가. + +**Files:** + +- Modify: `SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift` +- Modify: `SodaLive/Sources/V2/CreatorChannel/CreatorChannelViewModel.swift` +- Check: `SodaLive/Sources/Explorer/Profile/UserProfileViewModel.swift` +- Check: `SodaLive/Sources/Common/ActivityViewController.swift` +- Test: 테스트 타깃 없음. 빌드와 수동 검증으로 대체. + +**TDD 예외 사유:** 공유 시트는 iOS system UI이고 현재 테스트 타깃이 없어 자동 UI test를 작성하지 않는다. + +**대체 검증 방법:** 구현 후 아래 명령과 수동 확인을 수행한다. + +```bash +rg "af_dp|deep_link_value|deep_link_sub5|shareChannel|shareMessage|isShowShareView|ActivityViewController" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift SodaLive/Sources/V2/CreatorChannel/CreatorChannelViewModel.swift SodaLive/Sources/Explorer/Profile/UserProfileViewModel.swift +xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build +``` + +Expected: + +- V2 크리에이터 채널 공유 로직이 기존 `UserProfileViewModel.shareChannel`과 같은 파라미터를 사용한다. +- `ActivityViewController`가 `shareMessage`를 받아 표시된다. +- OneLink 생성 실패 시 `I18n.MemberChannel.shareLinkCreateFailed` popup 흐름이 있다. +- 빌드 exit code가 0이다. + +- [x] `CreatorChannelViewModel` 또는 `CreatorChannelView`에 공유 메시지 상태를 추가한다. +- [x] `af_dp`, `deep_link_value`, `deep_link_sub5` 값을 기존 채널 공유와 동일하게 구성한다. +- [x] 성공 시 `I18n.MemberChannel.shareChannelMessage(nickname)`과 URL을 줄바꿈으로 합친다. +- [x] 실패 시 기존 실패 문구 popup을 표시한다. +- [x] `CreatorChannelView`에 `ActivityViewController` presentation을 연결한다. + +#### Task 1.3 더보기 메뉴 최상단 공유 항목 추가 + +**Goal 실행 `P1-T3`:** 다른 사람 채널 더보기 overlay 최상단에 `채널 공유` 항목을 추가하고, 탭 시 공유 action을 실행한다. + +- **시작 조건:** `P1-T2` 완료, `CCSHARE-003`~`CCSHARE-005` 확정. +- **완료 증거:** 다른 사람 채널 더보기 메뉴 순서가 `채널 공유`, 차단/차단 해제, 사용자 신고, 프로필 신고 순서다. +- **범위 밖:** 기존 차단/신고 API 동작 변경. + +**Files:** + +- Modify: `SodaLive/Sources/Report/ProfileReportMenuView.swift` +- Modify: `SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift` +- Modify: `SodaLive/Sources/I18n/I18n.swift` +- Test: 테스트 타깃 없음. 빌드와 수동 검증으로 대체. + +**TDD 예외 사유:** 기존 overlay menu는 SwiftUI view이고 현재 테스트 타깃이 없어 자동 UI test를 작성하지 않는다. + +**대체 검증 방법:** 구현 후 아래 명령과 수동 확인을 수행한다. + +```bash +rg "channelShare|shareChannel|ProfileReportMenuView|userBlockAction|userReportAction|profileReportAction" SodaLive/Sources/Report/ProfileReportMenuView.swift SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift SodaLive/Sources/I18n/I18n.swift +xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build +``` + +Expected: + +- `ProfileReportMenuView`에 공유 항목과 공유 action이 있고 기존 차단/신고 action이 유지된다. +- `채널 공유` I18n 문구가 ko/en/ja에 제공된다. +- 빌드 exit code가 0이다. + +- [x] `ProfileReportMenuView`에 공유 action closure를 추가한다. +- [x] 공유 row를 기존 차단/신고 row보다 위에 배치한다. +- [x] 공유 row 탭 시 overlay를 닫고 공유 action을 호출한다. +- [x] 기존 차단/차단 해제, 사용자 신고, 프로필 신고 row와 action을 변경하지 않는다. +- [x] `I18n`에 공유 메뉴 문구를 추가한다. + +#### Task 1.4 회귀 정리와 문서 기록 + +**Goal 실행 `P1-T4`:** 구현 결과가 PRD 범위를 벗어나지 않는지 확인하고 검증 기록을 누적한다. + +- **시작 조건:** `P1-T1`~`P1-T3` 완료. +- **완료 증거:** PRD 요구사항 추적표와 실제 코드 변경 범위가 일치하고, 검증 명령 결과가 Progress에 기록됨. +- **범위 밖:** 발견된 범위 밖 문제의 임의 수정. + +**Files:** + +- Modify: `docs/20260914_크리에이터_채널_공유/plan-task.md` +- Check: `docs/20260914_크리에이터_채널_공유/prd.md` +- Test: 문서 대조와 빌드 결과 기록. + +**대체 검증 방법:** 아래 명령과 수동 확인 결과를 Progress에 기록한다. + +```bash +rg "CCSHARE-001|CCSHARE-002|CCSHARE-003|CCSHARE-004|CCSHARE-005|CCSHARE-006|CCSHARE-007" docs/20260914_크리에이터_채널_공유/prd.md docs/20260914_크리에이터_채널_공유/plan-task.md +xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build +``` + +Expected: + +- 모든 요구사항 ID가 PRD와 계획에 남아 있다. +- 빌드 exit code가 0이다. +- 수동 검증 항목의 실제 결과가 Progress에 기록되어 있다. + +- [x] PRD 요구사항과 구현 Task 연결을 대조한다. +- [x] 검증 명령의 실제 결과를 Progress에 누적한다. +- [x] 범위 밖 발견 사항이 있으면 `발견된 문제` 표에 기록한다. + +### 완료 조건 + +- [x] `P1-T1`, `P1-T2`, `P1-T3`, `P1-T4`의 체크박스와 완료 증거가 모두 충족됐다. +- [x] 기존 차단/신고 메뉴와 팔로우/알림 title bar 동작이 회귀하지 않았다. +- [x] 문서와 구현의 차이가 없다. + +### 검증 방법 + +#### Phase 1 Gate + +**Goal 실행 `P1-GATE`:** 채널 공유 사용자 흐름과 공통 품질 기준을 최종 판정한다. + +- **시작 조건:** Phase 1의 모든 활성 Task goal 완료. +- **완료 증거:** 아래 자동·수동 검증 통과와 Progress 기록. +- **범위 밖:** Gate 통과를 위한 test 삭제·완화와 관련 없는 기능 수정. + +```bash +rg "ic_audio_content_share|ActivityViewController|deep_link_value|deep_link_sub5|ProfileReportMenuView" SodaLive/Sources/V2/CreatorChannel SodaLive/Sources/Report/ProfileReportMenuView.swift +xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build +``` + +**Expected:** `rg` 결과에서 공유 버튼, 공유 시트, OneLink 파라미터, 더보기 메뉴 연결이 확인되고 빌드 exit code가 0이다. + +수동 검증: + +- [ ] 내 채널 진입 후 우측 상단 공유 버튼을 탭하면 iOS 공유 시트가 표시된다. +- [ ] 다른 사람 채널 진입 후 더보기 메뉴 최상단 `채널 공유`를 탭하면 iOS 공유 시트가 표시된다. +- [ ] 공유 메시지는 기존 채널 공유 메시지와 OneLink URL을 포함한다. +- [ ] 다른 사람 채널 더보기 메뉴의 기존 차단/신고 항목이 그대로 동작한다. +- [ ] OneLink 생성 실패를 유도할 수 있는 debug 조건이 있으면 실패 popup 문구를 확인하고, 없으면 코드 대조로 실패 경로를 확인한다. + +## 실행 순서와 의존성 + +| 순서 | Goal | 선행조건 | 병행 가능 | 차단 시 다음 행동 | +|---:|---|---|---|---| +| 1 | `P1-T1` | PRD 확정 | 아니요 | title bar contract 재검토 | +| 2 | `P1-T2` | `P1-T1` | 아니요 | 기존 `UserProfileViewModel.shareChannel` 대조 | +| 3 | `P1-T3` | `P1-T2` | 아니요 | `ProfileReportMenuView` contract 재검토 | +| 4 | `P1-T4` | `P1-T1`~`P1-T3` | 아니요 | PRD/계획 불일치 보정 | +| 5 | `P1-GATE` | Phase 1 Task 전체 | 아니요 | 실패 소유 Task의 회귀 수정 goal 생성 | + +```text +P1-T1 → P1-T2 → P1-T3 → P1-T4 → P1-GATE +``` + +## 변경 금지 항목 + +- 새 API, 새 dependency, 새 딥링크 계약을 추가하지 않는다. +- 공유 문구를 기존 채널 공유와 다르게 새로 만들지 않는다. +- 기존 차단/신고 action을 삭제하거나 의미를 바꾸지 않는다. +- `Pods/**`, `generated/**`, `build/**`를 수정하지 않는다. +- test를 삭제·skip·완화하거나 타입 오류를 우회해 Gate를 통과시키지 않는다. + +## 의사결정 및 중단 규칙 + +- PRD와 구현 중 발견한 기존 코드가 충돌하면 PRD Decision Log에 정정 행을 먼저 추가한다. +- 공유 URL 파라미터 변경이 필요하면 구현을 멈추고 사용자 결정을 받는다. +- title bar layout에서 버튼이 겹치면 새 디자인을 추정하지 말고 최소 대안과 영향을 보고한다. +- 범위 밖 회귀를 발견하면 임의 수정하지 않고 `발견된 문제`에 기록한다. + +## Progress + +기존 기록을 삭제하거나 덮어쓰지 않고 실제 실행 결과를 차수별로 누적한다. + +### 문서 작성 1차 실행 — 2026-09-14 + +- 상태: 완료 +- 무엇을: 신규 PRD와 plan-task 문서를 작성했다. +- 왜: 사용자 요청에 따라 구현 전 요구사항과 실행 계획을 확정하기 위해서다. +- 어떻게: + - `codegraph_explore` — `UserProfileViewModel.shareChannel`, `ActivityViewController`, `CreatorChannelTitleBar`, `ProfileReportMenuView`, `CreatorChannelViewModel` 현재 구현 확인. + - `read` — `docs/sample/sample-prd.md`, `docs/sample/sample-plan-task.md`, `docs/agent-guides/documentation-policy.md`, `docs/agent-guides/build-test-verification.md` 확인. +- 남은 항목: 코드 구현과 구현 검증은 사용자 후속 승인 전까지 진행하지 않는다. +- 다음 행동: 사용자가 구현을 요청하면 `P1-T1`부터 실행한다. + +### 구현 및 검증 1차 실행 — 2026-09-15 + +- 상태: 구현 완료, 수동 검증 대기 +- 무엇을: 내 채널 title bar 공유 버튼, 다른 사람 채널 더보기 최상단 `채널 공유`, 기존 OneLink 기반 `ActivityViewController` 공유 시트 연결을 구현했다. +- 왜: `CCSHARE-001`~`CCSHARE-007` 확정 요구사항을 현재 브랜치에서 충족하기 위해서다. +- 어떻게: + - `codegraph_explore` — `CreatorChannelViewModel.shareChannel`, `CreatorChannelTitleBar`, `ProfileReportMenuView`, `CreatorChannelView`, 기존 `UserProfileViewModel.shareChannel` 대조. + - `rg "ic_audio_content_share|ActivityViewController|deep_link_value|deep_link_sub5|ProfileReportMenuView|channelShare|shareLinkCreateFailed" "SodaLive/Sources/V2/CreatorChannel" "SodaLive/Sources/Report/ProfileReportMenuView.swift" "SodaLive/Sources/I18n/I18n.swift" "SodaLive/Sources/Explorer/Profile/UserProfileViewModel.swift"` — 공유 버튼, 공유 시트, OneLink 파라미터, 실패 popup, I18n 연결 확인. + - `git diff --check` — 통과. + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` — `BUILD SUCCEEDED`. + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug -destination "platform=iOS Simulator,id=E9FC7721-AA96-440F-8349-2DC4B85F40F5" -derivedDataPath "/var/folders/yh/8xsbvpsj5wg2qnxzxdp11_gm0000gn/T/opencode/sodalive-share-derived" CODE_SIGNING_ALLOWED=NO build` — simulator build 성공. + - `xcrun simctl install` / `xcrun simctl launch` — `kr.co.vividnext.sodalive.debug2` 설치 및 실행 성공, launch pid `46360`. + - 리뷰 검증 — reviewer/oracle `VERDICT: APPROVE`, blocker 없음. +- 남은 항목: `simctl ui` tap option과 `cliclick`이 없어 실제 채널 진입 후 공유 시트 표시는 사용자 수동 테스트로 확인한다. +- 다음 행동: 내 채널 공유 버튼, 다른 사람 채널 더보기 공유, 기존 차단/신고 항목을 실기기 또는 simulator에서 수동 확인한다. + +## Decision Log + +| 날짜 | ID | 상태 | 결정 | 근거 | 영향 Goal/문서 | +|---|---|---|---|---|---| +| 2026-09-14 | `DEC-001` | 확정 | 공유 기능 문서는 신규 `docs/20260914_크리에이터_채널_공유/` 아래에 작성한다. | 사용자 선택 B | 전체 | +| 2026-09-14 | `DEC-002` | 확정 | 다른 사람 채널 더보기 메뉴의 `채널 공유` 항목은 최상단에 배치한다. | 사용자 선택 A | `P1-T3` | +| 2026-09-14 | `DEC-003` | 확정 | 공유 방식은 기존 `UserProfileView`와 동일한 `ActivityViewController`와 OneLink 파라미터를 재사용한다. | 사용자 요구사항과 코드 확인 | `P1-T2`, `P1-GATE` | + +## 발견된 문제 + +| ID | 심각도 | 상태 | 발견 내용 | 영향 Goal | 처리 계획 | +|---|---|---|---|---|---| +| `ISSUE-001` | Low | 수동 확인 필요 | 현재 환경에서 자동 탭 도구가 없어 실제 공유 시트 표시까지 자동 검증하지 못함 | `P1-GATE` | 사용자 수동 테스트로 내 채널/다른 사람 채널 공유 시트 표시 확인 | + +## 최종 보고 형식 + +```markdown +구현 결과: Phase 1 크리에이터 채널 공유 흐름 완료 + +- 변경: 내 채널 title bar 공유 버튼, 다른 사람 채널 더보기 메뉴 최상단 공유 항목, 기존 OneLink 기반 공유 시트 연결 +- 결정: DEC-001 신규 문서 분리, DEC-002 공유 항목 최상단 배치, DEC-003 기존 공유 방식 재사용 +- 검증: + - `rg "ic_audio_content_share|ActivityViewController|deep_link_value|deep_link_sub5|ProfileReportMenuView" SodaLive/Sources/V2/CreatorChannel SodaLive/Sources/Report/ProfileReportMenuView.swift` — 공유 연결 코드 확인 결과 + - `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` — 빌드 성공 또는 실패와 핵심 오류 + - 수동 검증 — 내 채널 공유 버튼, 다른 사람 채널 더보기 공유, 기존 차단/신고 회귀 여부 +- 남은 항목: 구현 시 발견한 외부 의존 또는 후속 범위, 없으면 없음 +- 문서: `docs/20260914_크리에이터_채널_공유/prd.md`, `docs/20260914_크리에이터_채널_공유/plan-task.md` +``` diff --git a/docs/20260914_크리에이터_채널_공유/prd.md b/docs/20260914_크리에이터_채널_공유/prd.md new file mode 100644 index 00000000..b61bab1c --- /dev/null +++ b/docs/20260914_크리에이터_채널_공유/prd.md @@ -0,0 +1,222 @@ +# PRD: 크리에이터 채널 공유 + +## 문서 정보 + +| 항목 | 내용 | +|---|---| +| 문서 상태 | 구현 완료, 수동 검증 대기 | +| 작성일 | `2026-09-14` | +| 최종 수정일 | `2026-09-15` | +| 대상 제품 | 크리에이터 채널 공유 | +| 작성자·결정권자 | 제품 요구사항: 사용자, 문서 작성: Sisyphus | +| 관련 API Contract | 해당 없음 | +| 관련 구현 계획 | `docs/20260914_크리에이터_채널_공유/plan-task.md` | +| 관련 review | 없음 | + +### 요구사항 상태 + +| 상태 | 의미 | 구현 처리 | +|---|---|---| +| 확정 | 제품·기술 결정이 완료되어 구현 기준으로 사용 | `plan-task.md`의 Task와 완료 증거로 추적 | +| 제외 | 현재 릴리스에서 구현하지 않기로 결정 | Decision Log에 제외 이유 기록 | + +## 1. Overview + +크리에이터 채널 사용자는 채널을 외부 앱으로 공유할 수 있어야 한다. 내 채널에서는 우측 상단에 공유 버튼을 바로 노출하고, 다른 사람 채널에서는 우측 상단 더보기 메뉴 안에서 채널 공유를 선택한다. + +공유 동작은 기존 `UserProfileView`의 채널 공유와 동일하게 OneLink 메시지를 만든 뒤 `ActivityViewController`로 시스템 공유 시트를 표시한다. + +## 2. Problem Statement + +- 현재 신규 `CreatorChannelView`에는 채널 공유 진입점이 없다. +- 기존 레거시 `UserProfileView`에는 채널 공유 동작이 있으나, 신규 크리에이터 채널 title bar와 더보기 overlay에는 연결되어 있지 않다. +- 사용자는 자신의 채널을 홍보하거나 다른 사람의 채널을 추천하려면 앱 밖으로 공유할 수 있어야 한다. + +문제를 해결했다는 판단은 내 채널과 다른 사람 채널에서 모두 기존 채널 공유 메시지와 딥링크가 포함된 iOS 공유 시트가 열리는 것으로 한다. + +## 3. Goals + +### 3.1 제품 목표 + +- 내 크리에이터 채널 우측 상단에 공유 버튼을 직접 표시한다. +- 다른 사람 크리에이터 채널 더보기 메뉴 최상단에 `채널 공유` 항목을 표시한다. +- 공유 결과는 기존 `UserProfileView` 채널 공유와 동일한 메시지·딥링크 형식을 사용한다. + +### 3.2 UX 목표 + +- 내 채널 사용자는 더보기 단계를 거치지 않고 바로 공유할 수 있다. +- 다른 사람 채널 사용자는 기존 더보기 메뉴 안에서 공유, 차단, 신고 동작을 한 곳에서 선택할 수 있다. +- 공유 버튼에는 `ic_audio_content_share` asset을 사용한다. + +## 4. Non-Goals + +- 새 공유 문구를 만들지 않는다. +- 새 딥링크 계약이나 새 API를 만들지 않는다. +- 공유 URL 생성 로직을 범용 helper로 리팩터링하지 않는다. +- `Pods/**`, `generated/**`, `build/**`는 수정하지 않는다. +- 이 문서 작업에서는 코드 구현을 진행하지 않는다. + +## 5. Target Users and Permissions + +| 사용자 | 목표 | 주요 작업 | 사용 환경 | +|---|---|---|---| +| 내 채널 소유자 | 내 채널 홍보 | title bar 공유 버튼 탭 | iOS 앱 | +| 다른 사람 채널 방문자 | 채널 추천 | 더보기 메뉴에서 채널 공유 선택 | iOS 앱 | + +권한 정책: + +- 인증 여부와 무관하게 기존 `UserProfileView.shareChannel` 동작과 동일한 조건을 따른다. +- 내 채널 여부는 기존 `CreatorChannelView`의 `isOwnCreatorChannel` 판단을 따른다. +- 공유 대상 `creatorId`는 `CreatorChannelHomeResponse.creator.creatorId`를 사용한다. + +## 6. 핵심 사용자 흐름 + +1. 사용자가 내 크리에이터 채널에 진입한다. +2. 우측 상단 `ic_audio_content_share` 버튼을 탭한다. +3. 앱이 기존 채널 공유 메시지와 OneLink URL을 생성한다. +4. iOS `ActivityViewController` 공유 시트가 표시된다. + +다른 사람 채널 흐름: + +1. 사용자가 다른 사람 크리에이터 채널에 진입한다. +2. 우측 상단 더보기 버튼을 탭한다. +3. overlay 메뉴 최상단의 `채널 공유` 항목을 탭한다. +4. 앱이 기존 채널 공유 메시지와 OneLink URL을 생성한다. +5. iOS `ActivityViewController` 공유 시트가 표시된다. + +## 7. 정보 구조와 라우팅 + +```text +CreatorChannelView(creatorId:) + titleBar + my channel: share button + other channel: more button + more overlay + channel share + block/report actions + ActivityViewController +``` + +별도 route나 신규 `AppStep`은 추가하지 않는다. + +## 8. 기능 요구사항 + +### 8.1 내 채널 공유 버튼 + +| ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 | +|---|---|---|---|---| +| `CCSHARE-001` | 확정 | 내 채널 title bar 우측 상단에 공유 버튼을 직접 표시한다. | `isOwnCreatorChannel == true`일 때 `ic_audio_content_share` 버튼이 보이고 더보기 버튼은 공유 진입에 필요하지 않다. | `P1-T1` | +| `CCSHARE-002` | 확정 | 공유 버튼 탭 시 기존 채널 공유 방식으로 iOS 공유 시트를 표시한다. | 공유 메시지에 `I18n.MemberChannel.shareChannelMessage(nickname)` 결과와 OneLink URL이 포함된다. | `P1-T2` | + +### 8.2 다른 사람 채널 더보기 공유 + +| ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 | +|---|---|---|---|---| +| `CCSHARE-003` | 확정 | 다른 사람 채널 title bar는 기존 더보기 버튼을 유지한다. | `isOwnCreatorChannel == false`일 때 더보기 버튼을 탭하면 overlay 메뉴가 열린다. | `P1-T3` | +| `CCSHARE-004` | 확정 | 더보기 overlay 메뉴 최상단에 `채널 공유` 항목을 추가한다. | 메뉴 순서는 `채널 공유`가 기존 차단/신고 항목보다 위다. | `P1-T3` | +| `CCSHARE-005` | 확정 | `채널 공유` 항목 탭 시 overlay를 닫고 공유 시트를 표시한다. | 공유 시트가 표시되며 기존 차단/신고 흐름은 변경되지 않는다. | `P1-T3` | + +### 8.3 공유 링크와 메시지 + +| ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 | +|---|---|---|---|---| +| `CCSHARE-006` | 확정 | 공유 링크 생성은 기존 `UserProfileViewModel.shareChannel`과 동일한 OneLink 파라미터를 사용한다. | `af_dp=voiceon://`, `deep_link_value=channel`, `deep_link_sub5={creatorId}`가 사용된다. | `P1-T2` | +| `CCSHARE-007` | 확정 | 공유 실패 시 기존 채널 공유 실패 처리와 동일한 사용자 피드백을 사용한다. | OneLink 생성 실패 시 `I18n.MemberChannel.shareLinkCreateFailed` 기반 popup이 표시된다. | `P1-T2` | + +## 9. 반응형 기능 범위 + +| 기능 | iPhone | iPad | 비고 | +|---|---:|---:|---| +| 내 채널 공유 버튼 | 전체 | 전체 | 기존 title bar layout 범위 안에서 표시 | +| 다른 사람 채널 더보기 공유 | 전체 | 전체 | 기존 overlay 메뉴 패턴 유지 | +| ActivityViewController | 전체 | 전체 | 기존 `ActivityViewController` wrapper 사용 | + +## 10. UI/UX Expectations + +### 10.1 디자인과 component 원칙 + +- 공유 버튼 asset은 `ic_audio_content_share`로 고정한다. +- 신규 공용 component를 만들기보다 기존 `CreatorChannelTitleBar`, `ProfileReportMenuView`, `ActivityViewController` 패턴을 우선 재사용한다. +- 더보기 메뉴의 신규 항목 텍스트는 `채널 공유` 의미의 I18n 항목으로 제공한다. + +### 10.2 화면 상태 + +- 홈 API 응답을 받기 전에는 공유 대상 creator 정보가 없으므로 공유 action은 실행하지 않는다. +- 공유 시트 표시 중 기존 loading overlay를 새로 추가하지 않는다. +- OneLink 생성 실패 시 기존 popup 피드백을 표시한다. + +### 10.3 접근성 + +- 공유 버튼에는 채널 공유 의미의 accessibility label을 제공한다. +- 더보기 메뉴의 `채널 공유` 항목은 탭 가능한 충분한 영역을 유지한다. + +## 11. API 계약 + +신규 API 계약은 없다. + +공유 링크 생성 파라미터: + +| Key | Value | +|---|---| +| `af_dp` | `voiceon://` | +| `deep_link_value` | `channel` | +| `deep_link_sub5` | `{creatorId}` | + +## 12. 보안과 데이터 취급 + +- 공유 메시지에는 기존 채널 공유와 동일하게 공개 가능한 채널 nickname과 OneLink URL만 포함한다. +- 토큰, 인증 헤더, 개인정보를 공유 메시지나 로그에 포함하지 않는다. +- 새 네트워크 요청을 추가하지 않는다. + +## 13. 성능과 품질 요구사항 + +- 공유 버튼 또는 메뉴 항목 탭 한 번으로 iOS 공유 시트가 표시되어야 한다. +- 기존 팔로우/알림/차단/신고 title bar 및 더보기 흐름을 회귀시키지 않는다. +- 테스트 타깃이 없는 현재 저장소 상태를 고려해, 구현 시 focused 빌드와 수동 검증을 완료 증거로 기록한다. + +## 14. 성공 기준 + +### 14.1 기능 수용 기준 + +- [ ] 내 채널 title bar에서 `ic_audio_content_share` 버튼을 탭하면 공유 시트가 열린다. (`CCSHARE-001`, `CCSHARE-002`) +- [ ] 다른 사람 채널 더보기 메뉴 최상단 `채널 공유`를 탭하면 공유 시트가 열린다. (`CCSHARE-003`~`CCSHARE-005`) +- [x] 공유 메시지와 OneLink 파라미터가 기존 `UserProfileViewModel.shareChannel` 기준과 일치한다. (`CCSHARE-006`) +- [x] OneLink 생성 실패 시 기존 실패 popup과 동일한 피드백이 표시된다. (`CCSHARE-007`) + +### 14.2 UI/UX 수용 기준 + +- [x] 내 채널 공유 버튼은 우측 상단 title bar에 직접 노출된다. +- [x] 다른 사람 채널 메뉴에서 `채널 공유`는 최상단에 표시된다. +- [x] 기존 차단/신고 메뉴 항목과 동작은 유지된다. + +### 14.3 추적성 완료 기준 + +- [x] 모든 확정 요구사항이 `plan-task.md`의 Task와 연결된다. +- [x] 구현 전 코드 변경 범위가 `SodaLive/Sources/V2/CreatorChannel/**`, `SodaLive/Sources/Report/ProfileReportMenuView.swift`, `SodaLive/Sources/I18n/I18n.swift` 중심인지 확인한다. + +## 15. Open Questions + +| ID | 상태 | 결정 필요 사항 | 현재 권고 | 결정 주체 | 결정 기한/시점 | 영향 Goal | +|---|---|---|---|---|---|---| +| 없음 | 확정 | 추가 미결정 사항 없음 | 기존 공유 방식 재사용 | 사용자 | 2026-09-14 | 전체 | + +## 16. 요구사항 추적표 + +| 요구사항 범위 | API Contract | 계획 Phase | Goal | 자동 검증 | 수동 검증 | +|---|---|---:|---|---|---| +| `CCSHARE-001~002` | 해당 없음 | 1 | `P1-T1`, `P1-T2` | 빌드 | 내 채널 공유 버튼 탭 | +| `CCSHARE-003~005` | 해당 없음 | 1 | `P1-T3` | 빌드 | 다른 사람 채널 더보기 공유 탭 | +| `CCSHARE-006~007` | 해당 없음 | 1 | `P1-T2`, `P1-GATE` | 코드 대조, 빌드 | 공유 메시지와 실패 popup 확인 | + +## 17. Decision Log + +| 날짜 | ID | 상태 | 결정 | 근거 | 영향 요구사항·계약·Goal | +|---|---|---|---|---|---| +| 2026-09-14 | `DEC-001` | 확정 | 기존 문서에 누적하지 않고 신규 문서 `docs/20260914_크리에이터_채널_공유/`를 만든다. | 사용자 선택 B | 전체 | +| 2026-09-14 | `DEC-002` | 확정 | 다른 사람 채널 더보기 메뉴의 `채널 공유` 항목은 최상단에 배치한다. | 사용자 선택 A | `CCSHARE-004`, `P1-T3` | +| 2026-09-14 | `DEC-003` | 확정 | 공유 구현은 기존 `UserProfileView`의 `ActivityViewController` 방식과 OneLink 파라미터를 재사용한다. | 사용자 요구사항, 기존 코드 확인 | `CCSHARE-002`, `CCSHARE-006` | + +## 18. 변경 관리 + +- 공유 문구, 딥링크 파라미터, 메뉴 순서가 바뀌면 Decision Log에 정정 행을 추가한 뒤 요구사항과 `plan-task.md`를 갱신한다. +- 구현 중 테스트 타깃 또는 빌드 명령이 달라지면 `docs/agent-guides/build-test-verification.md` 확인 후 검증 기록에 실제 명령을 남긴다.