14 KiB
코드 리뷰 보고서: 커뮤니티 아이템 통일
1. 리뷰 정보
| 항목 | 내용 |
|---|---|
| 리뷰 대상 | Phase 1~2 / P1-T1~P2-R4 |
| 기준 commit 또는 working tree | 89c070875cbeea8395c1e90cb9f47ff80df5d90f 이후 미커밋 변경 |
| 리뷰 일자 | 2026-08-10 |
| 리뷰어 | Sisyphus 구현 검토·Oracle 독립 검토 |
| 기준 문서 | docs/20260810_크리에이터_채널_커뮤니티_아이템_통일/prd.md, plan-task.md |
| 리뷰 상태 | REV-P3-005 수동 검증 완료·REV-P3-006 코드/자동 검증 완료·상태별 더보기 확인 대기 |
2. 리뷰 목적과 범위
목적
- 홈·커뮤니티 탭의 아이템과 공지, 상세 진입, 더보기 노출, 목록 구매 제거, 상세 구매 이동·댓글 잠금이
CCCI-001~012를 충족하는지 확인한다. - 코드·문서·검증 기록이 실제 working tree와 일치하는지 확인한다.
포함 범위
- 코드:
SodaLive/Sources/V2/CreatorChannel/Home/**,Community/**,CreatorChannelView.swift의 변경분 - 검증: 정적 contract check,
git diff --check,SodaLive-devDebug Simulator build - 수동 검증: 부팅된 Simulator와
EXT-001반영 여부 확인
제외 범위
- 백엔드 구현·배포
- 구매 endpoint와
CommunityPostPurchaseDialog내부 UI CommunityPostCard의 메인 홈 사용처
3. 판정 기준
| 심각도 | 기준 |
|---|---|
| Blocker | 핵심 상세·구매·관리 흐름이 불가능하거나 완료 판정을 무효화함 |
| High | 확정 요구사항 또는 API 계약 위반 |
| Medium | 제한된 조건의 기능·상태 동기화 문제 |
| Low | 문서 정합성 또는 비핵심 유지보수 문제 |
| 상태 | 의미 |
|---|---|
| 확정 | 코드·명령 근거로 문제 확인 |
| 오탐 | 요구사항·실행 결과상 문제가 아님 |
| 보류 | 외부 계약·환경 반영 후 판정 가능 |
| 수정 완료 | 수정과 관련 검증 완료 |
4. 검토한 근거
문서와 코드
- 요구사항:
CCCI-001~012,DEC-001~016,EXT-001 - 계획:
P1-T1~P2-T2,P2-R1,P2-R2,P2-R3,P2-R4,P1-GATE,P2-GATE - 홈 변환·아이템:
CreatorChannelCommunitySection.swift:3 - 목록 잠금·상세 gesture:
CreatorChannelCommunityListItem.swift,CreatorChannelCommunityGridItem.swift - 상세 구매:
CreatorChannelCommunityPostDetailView.swift:19,CreatorChannelCommunityPostDetailViewModel.swift:186 - 메뉴·route·동기화:
CreatorChannelView.swift:480,CreatorChannelView.swift:605
실행 환경
OS: macOS 26.0 (25A354)
Xcode: 26.0 (17A324)
Scheme: SodaLive-dev / Debug
Destination: iPhone 17 Pro, iOS 26.0 Simulator
Backend: EXT-001 반영 여부를 이 환경에서 확인하지 못함
실행한 검증
| 명령 또는 수동 검증 | 결과 | 핵심 증거 |
|---|---|---|
홈 모델·변환·route·menu rg contract check |
성공 | 필드·communityPostItem·CreatorChannelCommunityListItem·postId route match |
목록 구매 심볼·잠금 배경 rg contract check |
성공 | 목록 구매 심볼과 잠금 Color.gray400 0건, 목록·상세 Color.gray800 match |
상세 구매 rg contract check |
성공 | showPurchaseError 0건, 상세 dialog·repository 호출 match |
reaction bar 조건부 삽입 rg contract check |
성공 | 무조건 삽입 0건, if !isPaidLocked 조건부 삽입 2건 |
공지 상세 전용 구매 rg RED/GREEN contract check |
성공 | RED 직접 구매 callback 7건·미연결 생성부 1건, GREEN 기존 callback 0건·상세 연결 match |
상세 댓글 잠금 rg RED/GREEN contract check |
성공 | RED View 직접 조건 2건, GREEN 직접 조건 0건·shared 상태 참조 10건·mutation guard match |
리스트 더보기 노출 rg RED/GREEN contract check |
성공 | RED else if !isOwnPost 1건, GREEN 기존 조건 0건·else if !isPaidLocked 1건·production diff 한 줄 |
| P2-R4 Oracle 독립 코드 리뷰 | 승인 | 네 상태 논리표·공용 호출부·범위 외 회귀·문서 추적성 확인, blocker 0건 |
| Oracle 독립 코드 리뷰 | 승인 | 세 상태 시나리오·mutation API 경로·문서 보류 판정 확인, blocker 0건 |
git diff --check |
성공 | whitespace 오류 0건 |
xcodebuild -quiet -workspace SodaLive.xcworkspace -scheme SodaLive-dev -configuration Debug -destination 'platform=iOS Simulator,id=E9FC7721-AA96-440F-8349-2DC4B85F40F5' -derivedDataPath /tmp/sodalive-community-baseline CODE_SIGNING_ALLOWED=NO ONLY_ACTIVE_ARCH=YES build |
성공 | exit code 0 |
| iPhone 17 Pro iOS 26.0 Simulator build·install·launch·screenshot | 부분 성공 | Simulator build exit 0, 홈 실행 /tmp/p2-r3-launch.png; 익명 세션에 유효 상세 데이터가 없어 상태별 상세 검증 대기, 이후 Simulator 종료 |
5. 발견 사항 요약
사용자 회귀 제보로 확정한 reaction bar 빈 공간 1건은 수정·빌드를 완료했고, 홈 공지의 상세 전용 구매 원칙 누락 1건을 추가 확정했다.
| ID | 심각도 | 상태 | 제목 | 소유 Task | 후속 goal |
|---|---|---|---|---|---|
REV-P3-001 |
High | 수정 완료 | 상세 잠금 버튼이 구매 대신 공통 오류만 표시하던 계획 누락 | P1-T3 |
완료 |
REV-P3-002 |
High | 보류 | 홈 API 신규 필드와 런타임 동작의 통합 검증 필요 | P3-GATE, EXT-001 |
외부 반영 후 재개 |
REV-P3-003 |
Medium | 수정 완료 | 하트·댓글이 숨겨져도 빈 reaction bar가 24pt 공간을 차지함 | P2-R1 |
완료 |
REV-P3-004 |
High | 수정 완료 | 홈 공지에 목록 구매 callback이 남고 상세 callback이 연결되지 않음 | P2-R2 |
완료 |
REV-P3-005 |
High | 수정·수동 검증 완료 | 유료 미구매 상세가 댓글 UI와 mutation을 허용함 | P2-R3 |
완료 |
REV-P3-006 |
Medium | 코드·자동 검증 완료·수동 대기 | 유료 미구매 타인 게시글에도 더보기가 표시됨 | P2-R4 |
홈·커뮤니티 상태별 확인 |
6. 발견 사항 상세
REV-P3-001 — 상세 구매 연결 누락
- 심각도: High
- 상태: 수정 완료
- 관련 요구사항:
CCCI-004,CCCI-007 - 소유 Task:
P1-T3
기준선에서 상세 잠금 영역은 showPurchaseError()만 호출해 목록 구매 제거 후 실제 구매가 불가능했다. 코드 수정 전에 PRD DEC-012와 계획 P1-T3를 추가하고, 기존 CommunityPostPurchaseDialog·CreatorCommunityRepository.purchaseCommunityPost(postId:)를 상세 View·ViewModel로 이동했다. 정적 contract check와 Debug build가 통과했다.
REV-P3-002 — 백엔드·Simulator 통합 검증 대기
- 심각도: High
- 상태: 보류
- 관련 요구사항:
CCCI-001~008,EXT-001 - 소유 Task:
P3-GATE
백엔드가 홈 API notices·communities에 isCommentAvailable·isPinned을 제공해야 하며, 실제 터치·메뉴·구매 흐름은 부팅된 Simulator에서 확인해야 한다. 현재 Simulator는 모두 종료 상태다. 백엔드 반영과 Simulator 부팅 후 홈·리스트·썸네일·상세 흐름을 재검증한다.
REV-P3-003 — 표시할 reaction이 없을 때 빈 공간 유지
- 심각도: Medium
- 상태: 수정 완료
- 관련 요구사항:
CCCI-009 - 소유 Task:
P2-R1
CreatorChannelCommunityListItem과 CreatorChannelCommunityPostDetailContentView는 유료 잠금 상태에서 하트·댓글 자식만 숨기고, body에는 reactionBar를 항상 삽입했다. 그 결과 빈 HStack의 .frame(height: 24)와 부모 VStack spacing이 홈·커뮤니티 리스트·상세에 남았다. 코드 수정 전에 P2-R1을 추가하고, 두 body에서 기존 isPaidLocked로 reaction bar 전체를 조건부 제외했다. focused contract check·git diff --check·Debug build가 통과했다.
REV-P3-004 — 홈 공지의 상세 전용 구매 원칙 누락
- 심각도: High
- 상태: 수정 완료
- 관련 요구사항:
CCCI-010 - 소유 Task:
P2-R2
CreatorChannelNoticeSection은 onTapNotice·onTapComment·onTapPurchase를 각각 기본 no-op으로 선언하고 잠금 영역에 별도 구매 Button을 뒀다. CreatorChannelHomeView는 notices만 전달해 상세 callback을 연결하지 않았다. 코드 수정 전에 P2-R2를 추가하고, 세 callback을 단일 onTapDetail로 통일해 기존 onTapCommunityDetail route에 연결했다. 잠금 구매 Button wrapper만 제거했으며 카드 외형과 상세 구매·refresh 구현은 변경하지 않았다. focused RED/GREEN contract check·git diff --check·Debug build가 통과했다.
REV-P3-005 — 유료 미구매 상세의 댓글 접근 허용
- 심각도: High
- 상태: 수정·수동 검증 완료
- 관련 요구사항:
CCCI-011 - 소유 Task:
P2-R3
상세 View와 ViewModel이 isCommentAvailable만 확인해 타인 유료 미구매 게시글에서도 댓글 구분선·목록·입력창과 작성·수정·삭제 mutation을 허용했다. 기존 유료 잠금 조건과 isCommentAvailable을 결합한 isCommentInteractionAvailable을 추가하고 UI 삽입·페이지네이션·전송·편집·삭제·applyDetail 초기화에 재사용했다. 정적 contract check·device/Simulator Debug build가 통과했고 사용자가 상태별 상세 동작을 수동 확인했다.
REV-P3-006 — 유료 미구매 타인 게시글의 더보기 노출
- 심각도: Medium
- 상태: 코드·자동 검증 완료·수동 대기
- 관련 요구사항:
CCCI-012 - 소유 Task:
P2-R4
공용 리스트 아이템의 방문자 분기가 else if !isOwnPost만 확인해 유료 미구매 타인 게시글에도 더보기를 표시했다. 기존 isPaidLocked의 반대 조건으로 분기를 교체해 홈·커뮤니티 리스트에 함께 적용했다. production diff는 한 줄이며 정적 contract check·git diff --check·Debug build가 통과했다.
7. 확정 항목의 plan·goal 전환
REV-P3-001: 코드 수정 전에P1-T3로 전환했고 수정·빌드를 완료했다.REV-P3-003: 코드 수정 전에P2-R1로 전환했고 수정·검증을 완료했다.REV-P3-004: 코드 수정 전에P2-R2로 전환했고 수정·검증을 완료했다.REV-P3-005: 코드 수정 전에P2-R3로 전환했고 코드·자동·상태별 수동 검증을 완료했다.REV-P3-006: 코드 수정 전에P2-R4로 전환했고 코드·자동 검증을 완료했다. 상태별 더보기 수동 확인은 대기한다.REV-P3-002: 외부 조건이므로P3-GATE완료를 보류한다.
8. 리뷰 종료 판정
| 판정 항목 | 결과 | 근거 |
|---|---|---|
| 리뷰 범위 전체 확인 | 충족 | 사용자 회귀 제보와 수정 결과를 추가 반영 |
| 후보 항목 판정 완료 | 충족 | REV-P3-001·REV-P3-003·REV-P3-004 수정 완료, REV-P3-002 보류 |
| 확정 항목 plan 반영 | 충족 | P1-T3, P2-R1, P2-R2, DEC-012~014 |
| 보류 항목의 담당·재개 조건 기록 | 충족 | EXT-001·부팅된 Simulator |
| 검증 명령과 결과 기록 | 충족 | 정적 계약·Debug build exit 0 |
최종 결론: 상세 댓글 차단 상태별 검증 완료, 더보기 노출 조건 코드·자동 검증 완료·상태별 수동 확인 대기
남은 항목: 홈·커뮤니티 리스트에서 더보기 네 상태를 수동 확인하고, 백엔드 EXT-001 반영 후 나머지 통합 흐름을 확인한다.
9. 수정 후 검증 기록
1차 수정 검증 — 2026-08-10
- 무엇을:
REV-P3-001의 상세 구매 누락을 수정했다. - 왜: 목록 구매 제거 후에도 사용자가 상세에서 실제 구매할 수 있어야 한다.
- 어떻게:
- 상세 구매 contract check — 성공
SodaLive-dev단일 Simulator Debug build — exit code 0
- 남은 항목:
REV-P3-002
2차 수정 검증 — 2026-08-10
- 무엇을:
REV-P3-003의 빈 reaction bar 공간을 제거했다. - 왜: 하트·댓글을 모두 숨기는 유료 잠금 상태에서 고정 24pt 높이와 부모 spacing까지 없어져야 한다.
- 어떻게:
- 무조건
reactionBar삽입 contract check — 0건 if !isPaidLocked조건부 삽입 contract check — 2건git diff --check— 성공SodaLive-dev단일 Simulator Debug build — exit code 0
- 무조건
- 남은 항목:
REV-P3-002와 Simulator 시각 검증
3차 수정 검증 — 2026-08-10
- 무엇을:
REV-P3-004의 홈 공지 직접 구매·상세 미연결을 수정했다. - 왜: 공지도 커뮤니티 게시글이므로 목록이 아닌 상세에서만 구매해야 한다.
- 어떻게:
- RED: 직접 구매 callback 7건, 홈 상세 callback 미연결 생성부 1건 확인
- GREEN: 기존 callback 0건, 단일
onTapDetail·홈onTapCommunityDetail연결 확인 - 기존 상세 구매 dialog/API와 구매 후 상세·홈·커뮤니티 refresh 연결 유지 확인
git diff --check— 성공SodaLive-devDebug build — exit code 0
- 남은 항목:
REV-P3-002와 Simulator 통합 검증
4차 수정 검증 — 2026-08-10
- 무엇을:
REV-P3-005의 유료 미구매 상세 댓글 UI·mutation 허용을 차단했다. - 왜: 구매 전 방문자는 reaction뿐 아니라 댓글 영역과 작성·수정·삭제 API에도 접근할 수 없어야 한다.
- 어떻게:
- RED: 상세 View의
isCommentAvailable직접 조건 2건과 paid-lock 미반영 ViewModel guard 확인 - GREEN: View 직접 조건 0건, shared 상태 참조 10건, mutation guard match
git diff --check— 성공- device와 iPhone 17 Pro Simulator 대상
SodaLive-devDebug build — 각각 exit code 0 - Simulator build·install·launch·홈 캡처 후 종료
- RED: 상세 View의
- 남은 항목: 익명 세션에서 확보하지 못한 유효 유료 미구매·구매 완료·본인 게시글 기반 수동 검증,
REV-P3-002 - 독립 리뷰: Oracle
APPROVE, blocker 0건. 상태별 상세 fixture 부재는 문서화된 잔여 수동 검증 위험으로 판정했다.
5차 수정 검증 — 2026-08-10
- 무엇을:
REV-P3-006의 유료 미구매 타인 게시글 더보기 노출을 차단했다. - 왜: 구매 전 타인 게시글은 관리·신고 더보기 진입점을 표시하지 않아야 한다.
- 어떻게:
- RED:
else if !isOwnPost1건 확인 - GREEN: 기존 조건 0건,
else if !isPaidLocked1건, production diff 한 줄 git diff --check— 성공SodaLive-devDebug build — exit code 0
- RED:
- 남은 항목: 홈·커뮤니티 탭에서 유료 미구매 타인 숨김, 무료·구매 완료·작성자 표시 수동 확인
- 독립 리뷰: 최초 문서 상태·추적 범위 2건을 수정한 뒤 Oracle 재검토
APPROVE, blocker 0건.