diff --git a/docs/20261006_선물_UI_추가/plan-task.md b/docs/20261006_선물_UI_추가/plan-task.md index 57be5ab5..b760e2a8 100644 --- a/docs/20261006_선물_UI_추가/plan-task.md +++ b/docs/20261006_선물_UI_추가/plan-task.md @@ -2,12 +2,12 @@ | 문서 항목 | 내용 | |---|---| -| 상태 | 계획 작성 완료 | +| 상태 | Phase 11 코드·정적 Gate 승인, runtime 검증 대기 | | 작성일 | `2026-10-06` | | 요구사항 기준 | `docs/20261006_선물_UI_추가/prd.md` | | API 기준 | `docs/20261006_선물_UI_추가/prd.md` §11 | -| 현재 Phase | Phase 9 공용 주소 검색과 제한적 Figma 정렬 | -| 현재 활성 Goal | `P9-GATE` runtime 검증 대기 | +| 현재 Phase | Phase 11 선물 딥링크·정책 링크·크리에이터 표시 보정 | +| 현재 활성 Goal | `P11-GATE` 인증 runtime 검증 대기 | ## 목표 @@ -26,6 +26,8 @@ | 7 | 대기 | `0/4` | `P7-T1` | Phase 5 필요 | | 8 | 코드·정적 gate 승인, runtime 미완료 | `2/2` | `P8-GATE` 인증 runtime 검증 대기 | 인증 실행 환경과 Figma 접근 부재 | | 9 | 구현·focused 검사 완료 | `2/2` | `P9-GATE` | 최종 build 및 Kakao/화면 runtime 미검증 | +| 10 | 코드·정적 gate 승인, runtime 미완료 | `6/6` | `P10-GATE` runtime 검증 대기 | 인증 실행 환경 부재 | +| 11 | 코드·정적 gate 승인, runtime 미완료 | `3/3` | `P11-GATE` 인증 runtime 검증 대기 | 인증 실행 환경과 화면 캡처 부재 | 완료된 Task와 검증 기록은 삭제하지 않는다. 후속 수정은 새 Task 또는 정정 기록으로 누적한다. @@ -39,6 +41,8 @@ - 보낸 선물 운송장 등록, 신청 취소 확인, 취소 완료 UI. - 받은 선물 배송지 입력, 배송지 입력 완료, 전달 완료, 전달 불가 UI. - `deepLinkValue=GIFT_DETAIL`, `deepLinkId=applicationNo` 딥링크 진입. +- `gift-detail/{applicationNo}` 경로형 딥링크 진입. +- 선물 보내기 화면의 크리에이터 프로필 이미지, 파손 정책 링크, 채널 버튼 UI 보정. ### 제외 @@ -48,6 +52,7 @@ - 약관 본문 API. - 선물 이미지, 첨부파일, 메시지 카드. - 임의 외부 URL 연결. +- Gift 모듈 브랜드 문구 변경. 현재 source가 이미 `소다라이브`이므로 추가 수정하지 않는다. ## 기술적 제약 @@ -927,6 +932,115 @@ git diff --check - [ ] 실제 한글 조합·12/13자·숫자 11/12자 입력을 실행 화면에서 확인한다. - [ ] 휴대폰 `010` 11자리와 운송장 숫자 10~14자리 경계, 15번째 문자 거부를 실행 화면에서 확인한다. +## Phase 11 선물 딥링크·정책 링크·크리에이터 표시 보정 + +**Phase 결과:** 경로형 선물 상세 딥링크가 기존 상세 화면으로 이동하고, 선물 보내기 화면에 대상 크리에이터 이미지와 올바른 파손 정책 링크가 표시되며, 채널의 선물 버튼이 승인된 UI를 사용한다. + +**선행조건:** 승인된 PRD `COMMON-006`, `COMMON-007`, `SEND-008`, `GIFT-004`와 `DEC-010`~`DEC-013`. + +**Phase 완료 조건:** `P11-T1`~`P11-T3`, `P11-GATE` 완료와 검증 기록 누적. + +### Task 11.1 경로형 선물 상세 딥링크 + +**Goal 실행 `P11-T1`:** `voiceon://gift-detail/{applicationNo}`와 `voiceon-test://gift-detail/{applicationNo}`를 기존 `.giftDetail` route로 연결한다. + +- **시작 조건:** `COMMON-006`, `DEC-011` 확정. +- **완료 증거:** production parser harness가 양 scheme의 경로형 URL, splash pending, 기존 query형 회귀를 검증한다. +- **범위 밖:** scheme 설정 변경, 신청번호 형식 추정, 상세 API/UI 변경. + +**Files:** + +- Modify: `SodaLive/Sources/App/AppDeepLinkHandler.swift` +- Modify: `work/tests/AppDeepLinkGiftDetailCheck.swift` +- Verify: `work/tests/check-app-deep-link-gift-detail.sh` + +- [x] **RED:** 양 scheme의 `gift-detail/A-1002609300001`, 누락 신청번호 거부, splash pending, 기존 query형 유지 case를 harness에 추가한다. +- [x] **RED 확인:** `bash work/tests/check-app-deep-link-gift-detail.sh`를 실행해 `gift-detail` route 미지원 assertion 실패를 확인한다. +- [x] **GREEN:** `makeAction`에 `gift-detail` 분기만 추가하고 공백을 제거한 비어 있지 않은 identifier를 `.giftDetail(applicationNo:)`로 반환한다. +- [x] **GREEN 확인:** 같은 focused harness가 기존 case와 신규 case를 모두 통과한다. +- [x] **REFACTOR:** parser 구조와 scheme/query 분기는 유지하고 focused 결과를 Progress에 기록한다. + +### Task 11.2 크리에이터 프로필 이미지와 파손 정책 링크 + +**Goal 실행 `P11-T2`:** 크리에이터 채널의 프로필 URL을 선물 보내기 화면까지 전달하고 파손 면책 `(필수)`에만 별도 정책 URL을 사용한다. + +- **시작 조건:** `SEND-008`, `COMMON-007`, `DEC-012` 확정. +- **완료 증거:** profile/policy source contract, 직접 영향 회귀, 양 스킴 build가 성공한다. +- **범위 밖:** 크리에이터 재조회 API, request DTO/ViewModel 변경, 기존 sender/recipient 약관 URL 변경. + +**Files:** + +- Modify: `SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelHeaderSection.swift` +- Modify: `SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelTalkActionSection.swift` +- Modify: `SodaLive/Sources/App/AppStep.swift` +- Modify: `SodaLive/Sources/ContentView.swift` +- Modify: `SodaLive/Sources/V2/Gift/Send/GiftSendView.swift` +- Modify: `SodaLive/Sources/V2/Gift/Components/GiftAgreementRow.swift` +- Modify: `SodaLive/Sources/V2/Gift/Constants/GiftConstants.swift` +- Create: `work/tests/check-gift-phase11.sh` + +- [x] **RED:** `creator.profileImageUrl`이 header → action → `.giftSend` → `ContentView` → `GiftSendView`로 전달되고, 파손 행만 새 URL을 지정하며 기존 약관/상세 정책 URL은 유지되는 source contract를 작성한다. +- [x] **RED 확인:** `bash work/tests/check-gift-phase11.sh profile`과 `bash work/tests/check-gift-phase11.sh policy`가 각각 누락된 전달값과 정책 URL 때문에 실패하는지 확인한다. +- [x] **GREEN:** `.giftSend`에 `recipientCreatorProfileImageUrl: String`을 추가하고 모든 생성·분해 지점을 갱신한다. `GiftSendView`는 `DownsampledKFImage`로 38pt 원형 이미지를 표시하며 ViewModel/API payload는 변경하지 않는다. +- [x] **GREEN:** `GiftConstants.damagePolicyURL`과 `GiftAgreementRow`의 기본값이 기존 `termsURL`인 선택적 URL 입력을 추가하고, 파손 면책 행에만 새 URL을 전달한다. +- [x] **GREEN 확인:** profile/policy mode와 전체 `bash work/tests/check-gift-phase11.sh`가 성공한다. +- [x] **REFACTOR:** 신청 성공의 guarded replace는 memberId/nickname 비교를 유지하고 아래 직접 영향 회귀를 실행한다. + +```bash +bash work/tests/check-gift-address-search.sh +bash work/tests/check-gift-contact-input.sh +bash work/tests/check-gift-recipient-address.sh +bash work/tests/check-received-gift-detail.sh recipient-form +bash work/tests/check-received-gift-detail.sh received-states +``` + +### Task 11.3 크리에이터 채널 선물 버튼 UI + +**Goal 실행 `P11-T3`:** 기존 선물 버튼의 노출 조건과 action을 유지하면서 `ic_send_gift`, 흰색 배경, 검은색 문구를 적용한다. + +- **시작 조건:** `GIFT-004`, `DEC-010`, 사용자가 추가한 `ic_send_gift.imageset` 존재. +- **완료 증거:** button source contract, asset catalog lint, 양 스킴 build와 가능한 runtime 화면 확인. +- **범위 밖:** Talk/DM 버튼, gift 노출 predicate, icon asset byte 수정. + +**Files:** + +- Modify: `SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelTalkActionSection.swift` +- Modify: `work/tests/check-gift-phase11.sh` +- Verify unchanged: `SodaLive/Resources/Assets.xcassets/v2/ic_send_gift.imageset/Contents.json` +- Verify unchanged: `SodaLive/Resources/Assets.xcassets/v2/ic_send_gift.imageset/ic_send_gift.png` + +- [x] **RED:** 아이콘이 문구 왼쪽에 있고 20pt, 흰색 capsule 배경, 검은색 문구이며 기존 gift predicate/action이 보존되는 button source contract를 추가한다. +- [x] **RED 확인:** `bash work/tests/check-gift-phase11.sh button`에서 기존 text-only outline UI 때문에 실패함을 확인한다. +- [x] **GREEN:** gift label만 `HStack(spacing: SodaSpacing.s6)`로 바꾸고 `ic_send_gift`와 기존 localized 문구를 넣은 뒤 흰색 capsule 배경과 검은색 문구를 적용한다. +- [x] **GREEN 확인:** button mode와 전체 Phase 11 source contract가 성공한다. +- [x] **REFACTOR:** Talk/DM UI와 `shouldShowGiftButton`이 변경되지 않았는지 확인하고 결과를 Progress에 기록한다. + +### Phase 11 Gate + +**Goal 실행 `P11-GATE`:** Phase 11의 네 요구사항과 기존 선물 흐름 회귀를 자동 검증과 runtime 결과로 구분해 판정한다. + +- [x] 아래 focused/회귀 검사와 shell parse가 모두 exit 0이다. +- [x] `SodaLive-dev`, `SodaLive` generic iOS Debug build가 `BUILD SUCCEEDED`다. +- [x] 코드 리뷰 결과를 `docs/20261006_선물_UI_추가/reviews/phase11-gift-links-creator-display.md`에 기록한다. +- [ ] runtime 가능 시 양 scheme 딥링크, 이미지, 정책 URL, 버튼 UI를 확인하고 불가능하면 미검증 항목과 사유를 기록한다. + +```bash +bash work/tests/check-app-deep-link-gift-detail.sh +bash work/tests/check-gift-phase11.sh +bash work/tests/check-gift-address-search.sh +bash work/tests/check-gift-contact-input.sh +bash work/tests/check-gift-recipient-address.sh +bash work/tests/check-received-gift-detail.sh recipient-form +bash work/tests/check-received-gift-detail.sh received-states +bash work/tests/check-gift-decoding-contract.sh +bash -n work/tests/check-gift-phase11.sh +xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug -destination "generic/platform=iOS" CODE_SIGNING_ALLOWED=NO build +xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug -destination "generic/platform=iOS" CODE_SIGNING_ALLOWED=NO build +git diff --check +``` + +**Expected:** 모든 자동 검증 exit 0, 양 스킴 `BUILD SUCCEEDED`. 인증 실행 환경이 없으면 runtime Gate만 미완료로 남긴다. + ## 실행 순서와 의존성 | 순서 | Goal | 선행조건 | 병행 가능 | 차단 시 다음 행동 | @@ -942,9 +1056,15 @@ git diff --check | 9 | `P6-*` | `P5-GATE` | `P7-*`와 가능 | 운송장 독립 진행 | | 10 | `P7-*` | `P5-GATE` | `P6-*`와 가능 | 받은 상세 독립 진행 | | 11 | `P8-*` | `P5-GATE`, `P7-GATE` | 아니요 | 딥링크만 분리 검증 | +| 12 | `P9-*` | `P3-GATE`, `P7-GATE` | 아니요 | 주소 검색만 분리 검증 | +| 13 | `P10-*` | `P3-GATE`, `P6-GATE`, `P7-GATE` | 일부 가능 | 입력 경계별 분리 검증 | +| 14 | `P11-T1` | PRD Phase 11 승인 | `P11-T2`와 가능 | 딥링크만 독립 검증 | +| 15 | `P11-T2` | PRD Phase 11 승인 | `P11-T1`과 가능 | profile/policy mode 분리 검증 | +| 16 | `P11-T3` | `P11-T2` | 아니요 | 공유 action file 순차 수정 | +| 17 | `P11-GATE` | `P11-T1`~`P11-T3` | 아니요 | 실패 소유 Task에 회귀 Task 추가 | ```text -P2 -> P3/P4/P5 -> P6/P7 -> P8 +P2 -> P3/P4/P5 -> P6/P7 -> P8/P9/P10 -> P11 ``` ## 변경 금지 항목 @@ -954,7 +1074,7 @@ P2 -> P3/P4/P5 -> P6/P7 -> P8 - API에 없는 필드, 오류 status/key, 취소일, 남은 일수를 추정하지 않는다. - 개인정보 표시 금지 필드를 UI 편의상 노출하지 않는다. - test를 삭제·skip·완화하거나 타입 오류를 우회하지 않는다. -- 임의 외부 URL을 연결하지 않는다. 확정 URL은 약관 Notion URL뿐이다. +- 임의 외부 URL을 연결하지 않는다. 확정 URL은 기존 약관 Notion URL과 Phase 11 파손 정책 Notion URL뿐이다. ## 의사결정 및 중단 규칙 @@ -1026,6 +1146,10 @@ P2 -> P3/P4/P5 -> P6/P7 -> P8 | 2026-10-08 | `P10-T5` | tracking harness에서 9자리 `123456789`가 제출되는 기존 동작을 RED로 확인했다. 편집은 ASCII 숫자 최대 14자, 제출은 10~14자리인 순수 predicate를 guarded `Binding`과 `canSubmit`에서 재사용했다. 142 assertions로 경계, 잘못된 값의 POST 차단, leading zero, 등록·실패·취소·navigation 회귀가 GREEN이다. | | 2026-10-08 | `P10-R1` | 정적 리뷰 `REV-P10-001`에서 연락처 UIKit 필드의 Pretendard 고정이 언어별 폰트 정책을 우회함을 확정했다. source contract RED 후 기존 `FontModifier` resolver를 재사용하는 `.body3.localizedFontName()` bridge로 수정했다. contact 80 assertions와 localized typography contract, recipient 280 assertions, tracking 142 assertions, Swift/shell parse, project lint, `git diff --check`, 양 스킴 generic iOS Debug build가 성공했고 재리뷰는 `APPROVE_STATIC`이다. | | 2026-10-08 | `P10-GATE` | 기능 독립 리뷰 `APPROVE`, 폰트 회귀 수정 후 정적 UI 재리뷰 `APPROVE_STATIC`. 실제 한글 조합, 12/13자, 휴대폰 11/12자, 운송장 9/10/14/15자 입력·붙여넣기, keyboard·Dynamic Type·VoiceOver·screenshot QA는 부팅된 인증 실행 환경 부재로 미수행이며 runtime 체크박스를 미완료로 유지한다. | +| 2026-10-08 | `P11-T1` | 경로형 딥링크 RED가 `path gift detail accepted`에서 실패함을 확인하고 `makeAction`에 `gift-detail` 최소 분기를 추가했다. 기존 query/splash/content 우선순위를 포함한 production parser harness가 `PASS AppDeepLinkGiftDetailCheck assertions=18`로 GREEN이다. | +| 2026-10-08 | `P11-T2` | profile/policy source contract가 각각 route 값과 파손 정책 URL 부재로 RED임을 확인했다. 프로필 URL을 표시 전용 route 값으로 전달해 38pt 원형 `DownsampledKFImage`를 표시하고, 파손 행만 새 정책 URL을 사용하도록 보정했다. Phase 11 profile/policy, address, contact 80 assertions, recipient 280 assertions, recipient-form, received-states 회귀와 shell parse가 GREEN이다. | +| 2026-10-08 | `P11-T3` | button source contract가 기존 text-only outline UI에서 RED임을 확인했다. 기존 predicate와 세 recipient route 값을 유지하면서 20pt `ic_send_gift`, 검은 문구, 흰색 capsule을 적용했고 button mode와 전체 Phase 11 source contract, shell parse가 GREEN이다. Talk/DM UI는 변경하지 않았다. | +| 2026-10-08 | `P11-GATE` | 계획된 경로형 누락 identifier 거부와 path splash pending coverage를 보강해 deep-link harness 22 assertions가 GREEN이다. Phase 11 profile/policy/button, address, contact 80, recipient 280, recipient-form, received-states, decoding 22 assertions와 shell parse, `git diff --check`가 성공했다. `SodaLive-dev`, `SodaLive` generic iOS Debug build는 각각 `BUILD SUCCEEDED`다. 독립 기능 리뷰는 `APPROVE`, Critical/Important/Minor 없음이며 정적 시각 구현도 제품 결함 없이 승인됐다. 인증 화면 screenshot·링크 탭·VoiceOver·좁은 화면/Dynamic Type은 실행 환경 부재로 미완료다. | ## Decision Log @@ -1040,6 +1164,10 @@ P2 -> P3/P4/P5 -> P6/P7 -> P8 | 2026-10-07 | `DEC-007` | 확정 | 상세의 nested `giftInfo.applicationNo`는 nullable로 decode하고, 화면 신청번호는 top-level `data.applicationNo`를 사용한다. | 인증 runtime `valueNotFound`와 null/string toggle | `P2-R2`, `P5-T1` | | 2026-10-07 | `DEC-008` | 확정 | 전달 불가 상세의 정책 버튼은 약관 `(필수)` 링크와 동일하게 `GiftConstants.termsURL`을 시스템 브라우저로 연다. | 사용자 확인 | `P2-R3`, `P5-T4`, `P7-T4` | | 2026-10-08 | `DEC-009` | 확정 | 휴대폰 제출은 `010`으로 시작하는 ASCII 숫자 11자리만, 운송장 제출은 ASCII 숫자 10~14자리만 허용한다. | 사용자 선택과 국내 번호체계 조사 | `P10-T4`, `P10-T5`, PRD `SEND-007`, `TRACK-007`, `RECV-007` | +| 2026-10-08 | `DEC-010` | 정정 | `ic_send_gift`, 흰색 배경, 검은색 문구로 기존 아이콘 없는 선물 버튼 결정을 정정한다. | 사용자 요청 및 설계 승인 | `P11-T3`, PRD `GIFT-004` | +| 2026-10-08 | `DEC-011` | 확정 | `gift-detail/{applicationNo}` 경로형 딥링크는 기존 scheme/parser/navigation을 최소 확장한다. | 사용자 제공 예시 및 설계 승인 | `P11-T1`, PRD `COMMON-006` | +| 2026-10-08 | `DEC-012` | 확정 | 파손 면책 행만 새 정책 URL을 사용하고 기존 약관 URL은 유지한다. | 사용자 제공 URL 및 설계 승인 | `P11-T2`, PRD `COMMON-007` | +| 2026-10-08 | `DEC-013` | 확정 | Gift source의 브랜드 문구는 이미 `소다라이브`이므로 변경하지 않는다. | source 검색과 사용자 선택 A | Phase 11, PRD `DEC-013` | ## 발견된 문제