docs(creator): 커뮤니티 잠금 기록을 갱신한다
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:executing-plans` to implement this plan task-by-task. 프로젝트 보수적 실행 모드에 따라 multi-agent는 사용하지 않는다.
|
||||
|
||||
**Goal:** 홈과 커뮤니티 탭의 커뮤니티 아이템 외형·상세 진입·더보기를 통일하고 구매는 상세에서만 처리하며, 표시할 reaction이 없을 때 빈 공간을 제거한다.
|
||||
**Goal:** 홈과 커뮤니티 탭의 커뮤니티 아이템 외형·상세 진입·더보기를 통일하고 구매는 상세에서만 처리하며, 유료 미구매 상태의 reaction·댓글·더보기 노출을 차단한다.
|
||||
|
||||
**Architecture:** 홈 API 게시글을 private 로컬 변환으로 `CreatorChannelCommunityPostItem`에 연결해 기존 `CreatorChannelCommunityListItem`을 재사용한다. 목록 구매 상태·dialog는 상세 ViewModel·View로 옮기고 기존 구매 API를 재사용하며, 변경 성공 후 홈·커뮤니티 목록을 동기화한다. 목록·홈 공용 아이템과 상세는 유료 잠금 상태에서 reaction bar 전체를 조건부로 제외한다.
|
||||
**Architecture:** 홈 API 게시글을 private 로컬 변환으로 `CreatorChannelCommunityPostItem`에 연결해 기존 `CreatorChannelCommunityListItem`을 재사용한다. 목록 구매 상태·dialog는 상세 ViewModel·View로 옮기고 기존 구매 API를 재사용하며, 변경 성공 후 홈·커뮤니티 목록을 동기화한다. 목록·홈 공용 아이템과 상세는 유료 잠금 상태에서 reaction bar를 제외하고, 공용 리스트 아이템은 더보기도 제외한다. 상세 View·ViewModel은 하나의 댓글 상호작용 상태로 댓글 UI와 mutation을 차단한다.
|
||||
|
||||
**Tech Stack:** Swift, SwiftUI, Combine, Moya, Kingfisher, SDWebImageSwiftUI, Xcode workspace `SodaLive.xcworkspace`.
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
- 목록의 리스트형·썸네일형 구매 호출은 제거하고 기존 구매 dialog·API 호출을 상세로 옮긴다.
|
||||
- 유료 미구매 영역은 홈·리스트형·썸네일형·상세 모두 `Color.gray800`을 사용한다.
|
||||
- 하트·댓글을 모두 숨기는 유료 미구매 상태에서는 reaction bar의 고정 높이와 부모 spacing을 남기지 않는다.
|
||||
- 상세의 유료 미구매 상태에서는 댓글 구분선·목록·입력창을 표시하지 않고 작성·수정·삭제 API 요청을 시작하지 않는다.
|
||||
- 현재 실행 가능한 단일 test bundle이 없으므로 신규 test 타겟을 만들지 않고 정적 contract check·Preview·Debug build·시뮬레이터로 검증한다.
|
||||
- 사용자가 직접 요청하지 않았으므로 `git commit`은 실행하지 않는다.
|
||||
|
||||
@@ -24,24 +25,24 @@
|
||||
|
||||
| 문서 항목 | 내용 |
|
||||
|---|---|
|
||||
| 상태 | reaction bar 회귀 수정·빌드 완료·외부 통합 검증 대기 |
|
||||
| 상태 | `P2-R3` 상태별 수동 검증 완료·`P2-R4` 코드/자동 검증 완료·상태별 수동 확인 대기 |
|
||||
| 작성일 | 2026-08-10 |
|
||||
| 요구사항 기준 | `docs/20260810_크리에이터_채널_커뮤니티_아이템_통일/prd.md` |
|
||||
| API 기준 | `GET /api/v2/creator-channels/{creatorId}/home` 필드 확장·기존 커뮤니티 목록/상세 API |
|
||||
| 현재 Phase | Phase 3 Gate |
|
||||
| 현재 활성 Goal | `P3-T1`·`P3-GATE`—`EXT-001`·부팅된 Simulator 대기 |
|
||||
| 현재 Phase | Phase 2 |
|
||||
| 현재 활성 Goal | `P2-R4`—더보기 상태별 수동 확인 |
|
||||
|
||||
## 목표
|
||||
|
||||
홈 요약·커뮤니티 리스트·썸네일에서 게시글 터치 결과와 잠금 스타일을 통일하고, 더보기 권한 메뉴와 상세 구매 흐름을 정확하게 유지한다.
|
||||
홈 요약·커뮤니티 리스트·썸네일에서 게시글 터치 결과와 잠금 스타일을 통일하고, 더보기 권한 메뉴와 상세 구매 흐름을 정확하게 유지한다. 상세의 유료 미구매 방문자에게는 reaction·댓글 영역을 표시하지 않고 댓글 mutation을 허용하지 않는다.
|
||||
|
||||
## 현재 상태
|
||||
|
||||
| Phase | 상태 | 완료 Task | 활성/다음 Goal | 차단 또는 남은 조건 |
|
||||
|---:|---|---:|---|---|
|
||||
| 1 | 완료 | `3/3` | `P1-GATE` 완료 | 없음 |
|
||||
| 2 | 완료 | `3/3` | `P2-GATE` 완료 | 없음 |
|
||||
| 3 | 진행 | `0/1` | `P3-T1`, `P3-GATE` | `EXT-001` 반영·Simulator 부팅 |
|
||||
| 2 | 진행 | `5/6` | `P2-R4` | 상태별 수동 확인 |
|
||||
| 3 | 진행 | `0/1` | `P3-T1`, `P3-GATE` | `EXT-001` 반영 |
|
||||
|
||||
## 범위
|
||||
|
||||
@@ -52,6 +53,7 @@
|
||||
- 홈 섹션의 `CreatorChannelCommunityListItem` 재사용
|
||||
- 홈의 고정·수정·삭제·신고 메뉴 연결과 성공 후 목록 동기화
|
||||
- 홈·커뮤니티 리스트와 상세에서 표시할 reaction이 없을 때 빈 공간 제거
|
||||
- 커뮤니티 상세의 유료 미구매 상태에서 댓글 구분선·목록·입력창 미표시와 작성·수정·삭제 mutation 차단
|
||||
- 정적 검사·Preview·Debug build·시뮬레이터 검증·문서 누적
|
||||
|
||||
### 제외
|
||||
@@ -61,6 +63,7 @@
|
||||
- 커뮤니티 작성·상세·댓글의 범위 밖 리팩터링
|
||||
- 신규 공용 모델·protocol·factory·dependency·test target 추가
|
||||
- 백엔드 구현과 배포
|
||||
- 상세 API 댓글 payload 계약과 `CreatorChannelReplyDetail/**` 변경
|
||||
|
||||
## 기술적 제약
|
||||
|
||||
@@ -69,6 +72,7 @@
|
||||
- 홈·커뮤니티 변경 성공 후 갱신은 `CreatorChannelView`의 한 helper에서 두 ViewModel 재조회를 호출한다.
|
||||
- 사용자 노출 오류는 기존 `errorMessage`·`isShowPopup`·toast 흐름을 유지한다.
|
||||
- 홈 응답에 추가 필드가 없으면 decoding 실패를 기존 홈 API 실패로 처리하고 fallback 값을 만들지 않는다.
|
||||
- 댓글 차단은 기존 유료 잠금 조건 `price > 0 && existOrdered == false && isOwnPost == false`와 상세의 `isCommentAvailable`을 함께 사용한다.
|
||||
|
||||
## Task 검증 규칙
|
||||
|
||||
@@ -335,11 +339,11 @@ Expected: whitespace 오류 0건, 필드 2건, 세 UI의 `Color.gray800`·상세
|
||||
|
||||
## Phase 2: 홈 아이템 재사용과 메뉴 연결
|
||||
|
||||
**Phase 결과:** 홈이 기존 커뮤니티 리스트 아이템·상세 route·권한 메뉴를 재사용하고 변경 성공 후 홈·커뮤니티 목록을 동기화한다.
|
||||
**Phase 결과:** 홈이 기존 커뮤니티 리스트 아이템·상세 route·권한 메뉴를 재사용하고 변경 성공 후 홈·커뮤니티 목록을 동기화하며, 상세 유료 미구매 상태의 reaction·댓글 UI와 댓글 mutation을 차단한다.
|
||||
|
||||
**선행조건:** `P1-GATE` 완료.
|
||||
|
||||
**Phase 완료 조건:** `P2-T1`, `P2-T2`, `P2-R1`, `P2-GATE` 완료.
|
||||
**Phase 완료 조건:** `P2-T1`, `P2-T2`, `P2-R1`, `P2-R2`, `P2-R3`, `P2-R4`, `P2-GATE` 완료.
|
||||
|
||||
### Task 2.1 홈 섹션에 기존 리스트 아이템·상세·더보기 연결
|
||||
|
||||
@@ -614,6 +618,77 @@ Expected: 첫 명령 match 0건·exit code 1, 둘째 명령 필수 연결 match,
|
||||
|
||||
- [x] **REFACTOR:** 공지 카드 외형·오디오 재생과 기존 상세·구매·refresh 구현은 변경하지 않는다.
|
||||
|
||||
### Follow-up Task 2.5 상세 유료 미구매 댓글 영역·동작 차단
|
||||
|
||||
**Goal 실행 `P2-R3`:** 커뮤니티 상세의 유료 미구매 잠금 상태에서 댓글 UI를 표시하지 않고 작성·수정·삭제 mutation을 실행하지 않는다.
|
||||
|
||||
- **시작 조건:** 사용자 후속 요청·인터뷰 A안 확정, PRD `CCCI-011`·`DEC-015` 반영.
|
||||
- **완료 증거:** 상세 댓글 구분선·목록·입력창의 단일 조건부 삽입, ViewModel 댓글 mutation guard, focused contract check, `git diff --check`, Debug build, 상태별 수동 확인.
|
||||
- **범위 밖:** 기존 reaction bar 구현 재수정, 상세 API 댓글 payload 변경, `CreatorChannelReplyDetail/**`, 신규 공용 모델·test target 추가.
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `SodaLive/Sources/V2/CreatorChannel/Community/Detail/CreatorChannelCommunityPostDetailView.swift`
|
||||
- Modify: `SodaLive/Sources/V2/CreatorChannel/Community/Detail/CreatorChannelCommunityPostDetailViewModel.swift`
|
||||
- Test: 신규 test 파일 없음—focused contract check·Debug build·시뮬레이터 사용
|
||||
|
||||
**Interfaces:**
|
||||
|
||||
- Consumes: `detail.price`, `detail.existOrdered`, `detail.isCommentAvailable`, 기존 `isOwnPost`, 댓글 전송·삭제 진입점.
|
||||
- Produces: 유료 잠금과 댓글 허용 상태를 함께 판정하는 단일 ViewModel 상태, 잠금 상태에서 댓글 UI·mutation이 없는 상세 화면.
|
||||
|
||||
- [x] **RED:** 상세 View가 유료 잠금 여부 없이 `isCommentAvailable`만으로 댓글 목록·입력창을 표시하고 ViewModel의 댓글 전송 가능 여부도 같은 필드만 확인함을 재현한다.
|
||||
|
||||
```bash
|
||||
rg -n "if detail\.isCommentAvailable|detail\?\.isCommentAvailable == true" SodaLive/Sources/V2/CreatorChannel/Community/Detail/CreatorChannelCommunityPostDetailView.swift
|
||||
rg -n "guard detail\?\.isCommentAvailable == true|func sendComment|func confirmDelete" SodaLive/Sources/V2/CreatorChannel/Community/Detail/CreatorChannelCommunityPostDetailViewModel.swift
|
||||
```
|
||||
|
||||
Expected: 상세 View의 댓글 목록·입력창 조건과 ViewModel의 기존 전송 조건이 match.
|
||||
|
||||
- [x] **GREEN:** ViewModel에 기존 유료 잠금 조건과 `isCommentAvailable`을 결합한 단일 댓글 상호작용 상태를 추가한다.
|
||||
- [x] **GREEN:** 상세 View의 댓글 구분선·목록·하단 입력창은 해당 상태가 `true`일 때만 삽입한다.
|
||||
- [x] **GREEN:** `sendComment`와 `confirmDelete`가 같은 상태를 guard하고, `applyDetail`은 잠금 상태의 댓글·편집·삭제 임시 상태를 기존 댓글 비활성 분기와 동일하게 비운다.
|
||||
- [x] **GREEN 확인:** 댓글 표시 조건과 mutation guard가 단일 상태를 사용하고 기존 직접 조건이 상세 View에서 제거됐는지 확인한다.
|
||||
|
||||
```bash
|
||||
rg -n "isCommentInteractionAvailable" SodaLive/Sources/V2/CreatorChannel/Community/Detail/CreatorChannelCommunityPostDetailView.swift SodaLive/Sources/V2/CreatorChannel/Community/Detail/CreatorChannelCommunityPostDetailViewModel.swift
|
||||
rg -n "if detail\.isCommentAvailable|detail\?\.isCommentAvailable == true" SodaLive/Sources/V2/CreatorChannel/Community/Detail/CreatorChannelCommunityPostDetailView.swift
|
||||
rg -n "guard isCommentInteractionAvailable" SodaLive/Sources/V2/CreatorChannel/Community/Detail/CreatorChannelCommunityPostDetailViewModel.swift
|
||||
git diff --check
|
||||
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build
|
||||
```
|
||||
|
||||
Expected: 단일 상태가 View·ViewModel에서 match, 상세 View의 기존 직접 조건 0건·exit code 1, mutation guard match, whitespace 오류 0건, `** BUILD SUCCEEDED **`.
|
||||
|
||||
- [x] **수동 확인:** 타인 게시글의 유료 미구매 상태에서는 reaction·댓글 구분선·목록·입력창이 보이지 않고 댓글 요청이 발생하지 않는다.
|
||||
- [x] **수동 확인:** 무료·구매 완료·본인 게시글에서는 기존 `isCommentAvailable` 값에 따라 댓글 UI와 동작이 유지된다.
|
||||
- [x] **REFACTOR:** 기존 상세 응답·repository·답글 화면과 이미 완료된 reaction bar 구현은 변경하지 않는다.
|
||||
|
||||
### Follow-up Task 2.6 유료 미구매 타인 게시글 더보기 숨김
|
||||
|
||||
**Goal 실행 `P2-R4`:** 홈·커뮤니티 탭 리스트 아이템의 더보기를 유료 미구매 타인 게시글에서 숨기고 무료·구매 완료·작성자 게시글에서 표시한다.
|
||||
|
||||
- **시작 조건:** 사용자 상태별 수동 검증과 후속 노출 규칙 확정, PRD `CCCI-012`·`DEC-016` 반영.
|
||||
- **완료 증거:** 공용 리스트 아이템 조건의 RED/GREEN contract check, `git diff --check`, Debug build, 상태별 수동 확인.
|
||||
- **범위 밖:** grid·공지 카드, 메뉴 내용·권한, 가격 표시, 상세·좋아요 gesture 변경.
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityListItem.swift`
|
||||
- Test: 신규 test 파일 없음—focused contract check·Debug build·수동 확인 사용
|
||||
|
||||
**Interfaces:**
|
||||
|
||||
- Consumes: 기존 `isPaidLocked`, `isOwnPost`, `post.price`, `post.existOrdered`.
|
||||
- Produces: 유료 미구매 타인 게시글에는 더보기가 없고 나머지 상태에는 기존 더보기 callback이 유지되는 header.
|
||||
|
||||
- [x] **RED:** 방문자 분기가 구매 상태와 무관하게 `else if !isOwnPost`로 더보기를 삽입함을 확인한다.
|
||||
- [x] **GREEN:** 방문자 분기를 `else if !isPaidLocked`로 변경해 기존 잠금 판정을 재사용한다.
|
||||
- [x] **GREEN 확인:** 기존 조건 0건, 신규 조건 1건, `git diff --check`, Debug build를 확인한다.
|
||||
- [ ] **수동 확인:** 홈·커뮤니티 탭에서 유료 미구매 타인은 숨김, 무료·구매 완료·작성자는 표시된다.
|
||||
- [x] **REFACTOR:** 신규 상태·helper 없이 조건 한 줄만 변경하고 grid·공지·메뉴 callback은 수정하지 않는다.
|
||||
|
||||
### Phase 2 Gate
|
||||
|
||||
**Goal 실행 `P2-GATE`:** 홈 재사용·상세·더보기·목록 동기화 구조를 판정한다.
|
||||
@@ -625,16 +700,18 @@ rg -n "CommunityPostCard\(" SodaLive/Sources/V2/CreatorChannel/Home/Components/C
|
||||
rg -n -U 'if !isPaidLocked \{\n[[:space:]]+reactionBar' SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityListItem.swift SodaLive/Sources/V2/CreatorChannel/Community/Detail/Components/CreatorChannelCommunityPostDetailContentView.swift
|
||||
rg -n "onTapPurchase|onTapNotice|onTapComment" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelNoticeSection.swift
|
||||
rg -n "onTapDetail|onTapCommunityDetail" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelNoticeSection.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift
|
||||
rg -n "isCommentInteractionAvailable|guard isCommentInteractionAvailable" SodaLive/Sources/V2/CreatorChannel/Community/Detail/CreatorChannelCommunityPostDetailView.swift SodaLive/Sources/V2/CreatorChannel/Community/Detail/CreatorChannelCommunityPostDetailViewModel.swift
|
||||
rg -n "else if !isPaidLocked" SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityListItem.swift
|
||||
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build
|
||||
```
|
||||
|
||||
Expected: whitespace 오류 0건, 필수 연결 match, 홈 `CommunityPostCard`·공지 기존 callback match 0건·exit code 1, `** BUILD SUCCEEDED **`.
|
||||
Expected: whitespace 오류 0건, 필수 연결·상세 댓글 조건/guard match, 홈 `CommunityPostCard`·공지 기존 callback match 0건·exit code 1, `** BUILD SUCCEEDED **`.
|
||||
|
||||
## Phase 3: 리뷰·통합 검증·문서 종결
|
||||
|
||||
**Phase 결과:** 정적 계약·Debug build·Preview·시뮬레이터 흐름을 확인하고 PRD·계획·리뷰 기록을 동기화한다.
|
||||
|
||||
**선행조건:** `P2-GATE` 완료. 시뮬레이터 통합 판정은 `EXT-001` 반영 후 실행.
|
||||
**선행조건:** `P2-R3`와 재개한 `P2-GATE` 완료. 시뮬레이터 통합 판정은 `EXT-001` 반영 후 실행.
|
||||
|
||||
**Phase 완료 조건:** `P3-T1`, `P3-GATE` 완료·검증 기록 누적.
|
||||
|
||||
@@ -657,7 +734,7 @@ Expected: whitespace 오류 0건, 필수 연결 match, 홈 `CommunityPostCard`·
|
||||
|
||||
**Interfaces:**
|
||||
|
||||
- Consumes: `CCCI-001~008`, `EXT-001`, Phase 1·2 산출물.
|
||||
- Consumes: `CCCI-001~012`, `EXT-001`, Phase 1·2 산출물.
|
||||
- Produces: Phase 3 리뷰 판정, 최종 Progress, 남은 외부 조건.
|
||||
|
||||
- [x] 정적 검사로 필수 연결과 금지 호출처를 확인한다.
|
||||
@@ -685,6 +762,7 @@ Expected: exit code 0, `** BUILD SUCCEEDED **`.
|
||||
- [ ] Preview에서 홈 유료 잠금·고정·댓글 비활성 상태와 썸네일 유료 잠금 상태를 확인한다.
|
||||
- [ ] `EXT-001` 반영 후 시뮬레이터에서 홈·리스트형·썸네일형 본체 터치가 상세로 이동하고 목록 구매 dialog가 나오지 않음을 확인한다.
|
||||
- [ ] 본인 채널의 고정·수정·삭제, 타인 채널의 신고, 상세 구매, 더보기·좋아요 터치 중복 없음을 수동 확인한다.
|
||||
- [ ] 상세의 유료 미구매 상태에서 reaction·댓글 UI 미노출과 댓글 mutation 차단을 확인하고, 구매 후 `isCommentAvailable`에 따른 복원을 확인한다.
|
||||
- [x] `docs/sample/sample-review.md`를 읽고 `phase3-community-item-unification.md`에 검토 범위·근거·명령·발견 사항을 기록한다.
|
||||
- [x] 확정 수정 항목이 있으면 코드 수정 전 해당 Phase에 회귀 Task를 추가한다.
|
||||
- [x] PRD 상태·요구사항 추적표와 이 문서의 체크박스·Progress를 실제 결과로 갱신한다.
|
||||
@@ -711,12 +789,14 @@ Expected: exit code 0, `** BUILD SUCCEEDED **`.
|
||||
| 6 | `P2-T2` | `P2-T1` | 아니요 | mutation 성공 callback 호출처 재확인 |
|
||||
| 7 | `P2-R1` | 사용자 회귀 제보·PRD 반영 | 아니요 | reaction bar 삽입 조건 재확인 |
|
||||
| 8 | `P2-R2` | 사용자 후속 요청·PRD 반영 | 아니요 | 공지 상세 callback 경계 재확인 |
|
||||
| 9 | `P2-GATE` | Phase 2 Task 전체 | 아니요 | 실패 소유 Task 수정 |
|
||||
| 10 | `P3-T1` | `P2-GATE` | 아니요 | 리뷰 수정 Task 추가 |
|
||||
| 11 | `P3-GATE` | `P3-T1`·`EXT-001` | 아니요 | 백엔드 반영 후 통합 검증 재개 |
|
||||
| 9 | `P2-R3` | 사용자 후속 요청·인터뷰·PRD 반영 | 아니요 | 상세 댓글 표시·mutation 진입점 재확인 |
|
||||
| 10 | `P2-R4` | 사용자 상태별 수동 검증·PRD 반영 | 아니요 | 공용 리스트 아이템 더보기 조건 재확인 |
|
||||
| 11 | `P2-GATE` | Phase 2 Task 전체 | 아니요 | 실패 소유 Task 수정 |
|
||||
| 12 | `P3-T1` | `P2-GATE` | 아니요 | 리뷰 수정 Task 추가 |
|
||||
| 13 | `P3-GATE` | `P3-T1`·`EXT-001` | 아니요 | 백엔드 반영 후 통합 검증 재개 |
|
||||
|
||||
```text
|
||||
P1-T1 → P1-T2 → P1-T3 → P1-GATE → P2-T1 → P2-T2 → P2-R1 → P2-R2 → P2-GATE → P3-T1 → P3-GATE
|
||||
P1-T1 → P1-T2 → P1-T3 → P1-GATE → P2-T1 → P2-T2 → P2-R1 → P2-R2 → P2-R3 → P2-R4 → P2-GATE → P3-T1 → P3-GATE
|
||||
```
|
||||
|
||||
## 변경 금지 항목
|
||||
@@ -726,6 +806,7 @@ P1-T1 → P1-T2 → P1-T3 → P1-GATE → P2-T1 → P2-T2 → P2-R1 → P2-R2
|
||||
- 홈 API의 `dateUtc`를 임의로 rename·parse·timezone 변환하지 않는다.
|
||||
- 백엔드 미반영 필드에 optional·fallback 값을 만들어 통합 실패를 숨기지 않는다.
|
||||
- 신규 protocol·factory·display model·dependency·test target을 추가하지 않는다.
|
||||
- 상세 API의 댓글 payload 계약과 `CreatorChannelReplyDetail/**`를 변경하지 않는다.
|
||||
- 요청 범위 밖의 기존 dead code·format·naming을 정리하지 않는다.
|
||||
|
||||
## 의사결정 및 중단 규칙
|
||||
@@ -811,6 +892,53 @@ P1-T1 → P1-T2 → P1-T3 → P1-GATE → P2-T1 → P2-T2 → P2-R1 → P2-R2
|
||||
- 남은 항목: 기존 `EXT-001`·부팅된 Simulator 기반 통합 검증.
|
||||
- 다음 행동: 외부 조건 충족 후 `P3-GATE`를 재개한다.
|
||||
|
||||
### 상세 유료 미구매 댓글 차단 계획 — 2026-08-10
|
||||
|
||||
- 상태: `P2-R3` 계획 확정·구현 대기
|
||||
- 무엇을: 상세의 유료 미구매 상태에서 기존 reaction bar 차단을 유지하고 댓글 구분선·목록·입력창과 작성·수정·삭제 mutation을 차단하는 후속 Task를 추가했다.
|
||||
- 왜: 현재 상세 View와 ViewModel은 `isCommentAvailable`만 확인해 유료 미구매 방문자도 댓글을 보고 mutation을 실행할 수 있기 때문이다.
|
||||
- 어떻게:
|
||||
- 사용자 인터뷰에서 UI와 ViewModel 동작을 모두 차단하는 A안을 확정했다.
|
||||
- 기존 유료 잠금 조건과 댓글 허용 값을 결합한 단일 ViewModel 상태를 View 표시 조건·mutation guard에 재사용하도록 `P2-R3`에 기록했다.
|
||||
- 이미 완료된 reaction bar 차단은 `P2-R1`을 유지하고 중복 Task를 만들지 않았다.
|
||||
- 남은 항목: `P2-R3` 구현·focused contract check·Debug build·상태별 수동 확인.
|
||||
- 다음 행동: 사용자가 별도로 구현을 요청할 때 `P2-R3`부터 실행한다. 현재 요청에 따라 코드 수정·커밋은 진행하지 않는다.
|
||||
|
||||
### 상세 유료 미구매 댓글 차단 구현 — 2026-08-10
|
||||
|
||||
- 상태: `P2-R3` 코드·정적 계약·device/Simulator Debug build·상태별 수동 검증 완료
|
||||
- 무엇을: `isCommentInteractionAvailable` 하나로 상세 댓글 구분선·목록·입력창과 페이지네이션·작성·수정·삭제·상태 초기화를 통일했다.
|
||||
- 왜: `isCommentAvailable`만으로는 타인 유료 미구매 게시글의 댓글 접근과 mutation을 차단하지 못하기 때문이다.
|
||||
- 어떻게:
|
||||
- RED: 상세 View 직접 조건 2건과 ViewModel의 paid-lock 미반영 guard를 확인했다.
|
||||
- GREEN: 상세 View 직접 조건 0건, shared 상태 참조 10건, mutation guard match, `git diff --check` 성공을 확인했다.
|
||||
- `SodaLive-dev` device Debug build와 iPhone 17 Pro iOS 26.0 Simulator Debug build가 각각 exit code 0으로 성공했다.
|
||||
- Simulator에 앱을 설치·실행해 홈 진입을 캡처한 뒤 종료했다.
|
||||
- 수동 검증: 사용자가 유료 미구매·무료·구매 완료·본인 게시글의 댓글 UI·요청 동작을 확인했다.
|
||||
- 남은 항목: `EXT-001` 통합 검증.
|
||||
- 다음 행동: 후속 `P2-R4`를 실행한다.
|
||||
|
||||
### 유료 미구매 타인 게시글 더보기 숨김 계획 — 2026-08-10
|
||||
|
||||
- 상태: `P2-R4` 계획 확정·구현 대기
|
||||
- 무엇을: 홈·커뮤니티 탭의 공용 리스트 아이템에서 유료 미구매 타인의 더보기를 숨기고 무료·구매 완료·작성자에게 표시한다.
|
||||
- 왜: 현재 방문자 분기 `else if !isOwnPost`가 구매 상태를 확인하지 않아 유료 미구매 게시글에도 더보기를 표시한다.
|
||||
- 어떻게: 기존 `isPaidLocked`를 재사용해 방문자 분기를 `else if !isPaidLocked`로 교체하는 한 줄 변경과 focused RED/GREEN 검증을 `P2-R4`에 기록했다.
|
||||
- 남은 항목: 코드 수정·정적 검사·Debug build·상태별 확인.
|
||||
- 다음 행동: `P2-R4` RED 확인 후 최소 구현한다.
|
||||
|
||||
### 유료 미구매 타인 게시글 더보기 숨김 구현 — 2026-08-10
|
||||
|
||||
- 상태: `P2-R4` 코드·정적 계약·Debug build 완료, 상태별 수동 확인 대기
|
||||
- 무엇을: 공용 `CreatorChannelCommunityListItem`의 방문자 더보기 조건을 `!isOwnPost`에서 `!isPaidLocked`로 변경했다.
|
||||
- 왜: 홈·커뮤니티 리스트의 유료 미구매 타인 게시글에서 더보기를 제거하고 무료·구매 완료·작성자 게시글에는 유지하기 위해서다.
|
||||
- 어떻게:
|
||||
- RED: 기존 조건 1건·신규 조건 0건을 확인했다.
|
||||
- GREEN: 기존 조건 0건·신규 조건 1건, production diff 한 줄, `git diff --check` 성공을 확인했다.
|
||||
- `SodaLive-dev` Debug build가 exit code 0으로 성공했다.
|
||||
- 남은 항목: 홈·커뮤니티 탭의 네 가지 상태별 수동 확인, `EXT-001` 통합 검증.
|
||||
- 다음 행동: 상태별 수동 확인 후 `P2-R4`와 `P2-GATE`를 완료 판정한다.
|
||||
|
||||
## Decision Log
|
||||
|
||||
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 Goal/문서 |
|
||||
@@ -822,6 +950,8 @@ P1-T1 → P1-T2 → P1-T3 → P1-GATE → P2-T1 → P2-T2 → P2-R1 → P2-R2
|
||||
| 2026-08-10 | `PLAN-DEC-005` | 확정 | 목록의 기존 구매 상태·API 호출을 상세 View·ViewModel로 옮긴다. | 상세의 현재 `showPurchaseError()`만으로는 사용자 요구인 상세 구매가 불가능함 | `P1-T2`, `P1-T3` |
|
||||
| 2026-08-10 | `PLAN-DEC-006` | 확정 | 하트·댓글이 모두 숨겨지는 경우 높이 보정 대신 reaction bar 전체를 조건부로 제외한다. | 공용 리스트·상세의 빈 고정 높이를 같은 기존 상태로 제거하는 최소 변경 | `P2-R1`, `CCCI-009` |
|
||||
| 2026-08-10 | `PLAN-DEC-007` | 확정 | 공지 카드의 별도 구매·상세·댓글 callback을 단일 상세 callback으로 교체하고 기존 홈 상세 route를 재사용한다. | 공지도 커뮤니티 게시글이며 상세 전용 구매 원칙을 동일하게 적용 | `P2-R2`, `CCCI-010` |
|
||||
| 2026-08-10 | `PLAN-DEC-008` | 확정 | 상세 View와 ViewModel은 기존 유료 잠금 조건과 `isCommentAvailable`을 결합한 단일 상태로 댓글 UI·작성·수정·삭제 mutation을 함께 차단한다. | 사용자 인터뷰 A안·PRD `DEC-015` | `P2-R3`, `CCCI-011` |
|
||||
| 2026-08-10 | `PLAN-DEC-009` | 확정 | 공용 리스트 아이템의 방문자 더보기 분기를 기존 `isPaidLocked`의 반대로 제한한다. | 신규 helper 없이 홈·커뮤니티 리스트에 동시에 적용되는 최소 변경 | `P2-R4`, `CCCI-012` |
|
||||
|
||||
## 발견된 문제
|
||||
|
||||
@@ -831,14 +961,16 @@ P1-T1 → P1-T2 → P1-T3 → P1-GATE → P2-T1 → P2-T2 → P2-R1 → P2-R2
|
||||
| `ISSUE-002` | High | 환경 대기 | 사용 가능한 Simulator가 모두 `Shutdown`이라 실제 터치·메뉴·구매 검증을 실행하지 못했다. | `P3-T1`, `P3-GATE` | Simulator 부팅 후 수동 검증을 재개한다. |
|
||||
| `ISSUE-003` | Medium | 수정 완료 | 유료 잠금 상태에서 하트·댓글은 숨겨지지만 빈 reaction bar의 고정 24pt 높이가 홈·목록·상세에 남는다. | `P2-R1`, `P3-GATE` | 조건부 삽입 contract check·Debug build 통과. |
|
||||
| `ISSUE-004` | High | 수정 완료 | 홈 공지는 별도 구매 callback이 남고 실제 조립부가 상세 callback을 전달하지 않아 상세 전용 구매 원칙을 충족하지 않는다. | `P2-R2`, `P3-GATE` | 단일 상세 callback 연결·직접 구매 callback 제거·Debug build 통과. |
|
||||
| `ISSUE-005` | High | 수정·수동 검증 완료 | 상세가 `isCommentAvailable`만으로 댓글 UI·전송 가능 여부를 판정해 유료 미구매 상태에서도 댓글을 조회하고 mutation을 실행할 수 있다. | `P2-R3`, `P2-GATE`, `P3-GATE` | 단일 댓글 상호작용 상태와 mutation guard를 적용하고 사용자가 상태별 동작을 확인했다. |
|
||||
| `ISSUE-006` | Medium | 코드·자동 검증 완료·수동 대기 | 공용 리스트 아이템이 타인 게시글이면 구매 상태와 무관하게 더보기를 표시한다. | `P2-R4`, `P2-GATE` | 방문자 분기를 `!isPaidLocked`로 제한했다. 홈·커뮤니티 리스트 상태를 수동 검증한다. |
|
||||
|
||||
## 최종 보고 형식
|
||||
|
||||
```markdown
|
||||
구현 결과: 홈·커뮤니티 아이템 통일과 상세 구매 일원화
|
||||
구현 결과: 홈·커뮤니티 아이템 통일과 상세 구매·댓글 잠금 일원화
|
||||
|
||||
- 변경: 홈 아이템 재사용, 목록 구매 제거, 더보기·상세·잠금 색상 통일
|
||||
- 결정: `DEC-001~012`, `PLAN-DEC-001~005`
|
||||
- 변경: 홈 아이템 재사용, 목록 구매 제거, 더보기·상세·잠금 색상 통일, 상세 유료 미구매 댓글 차단
|
||||
- 결정: `DEC-001~015`, `PLAN-DEC-001~008`
|
||||
- 검증:
|
||||
- 정적 contract check·`git diff --check` — 실제 결과
|
||||
- `SodaLive-dev` Debug build — 실제 결과
|
||||
|
||||
Reference in New Issue
Block a user