Files
sodalive-ios/docs/20260707_글_상세_답글_쓰기/plan-task.md

23 KiB

글 상세 - 답글 쓰기 구현 계획

For agentic workers: PRD를 기준으로 task 단위로 진행한다. 구현 중 요구사항 변경이 생기면 먼저 docs/20260707_글_상세_답글_쓰기/prd.md를 보강하고 이 문서의 체크리스트를 갱신한다.

Goal: 커뮤니티 댓글 또는 본인 채널 팬Talk 댓글을 터치해 답글 상세 화면에 진입하고, 기존 API로 답글 작성/수정/삭제를 수행한다.

Architecture: V2 전용 답글 상세 화면과 ViewModel을 새로 만들고, 네트워크 mutation은 기존 CreatorCommunityRepositoryExplorerRepository를 재사용한다. 커뮤니티와 팬Talk의 화면 표시/입력/수정 모드는 공통 ViewModel 상태로 처리하되, API 호출과 갱신 전략은 source enum으로 분기한다.

Tech Stack: SwiftUI, Combine, Moya, Kingfisher, 기존 AppCoordinator, 기존 V2 design token(Color, SodaSpacing, appFont)


기준 문서

  • PRD: docs/20260707_글_상세_답글_쓰기/prd.md
  • 문서 정책: docs/agent-guides/documentation-policy.md
  • 코드 스타일: docs/agent-guides/code-style.md
  • 빌드/검증: docs/agent-guides/build-test-verification.md
  • Figma 답글 없음: 669:40462, https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=669-40462&m=dev
  • Figma 답글 있음: 669:40468, https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=669-40468&m=dev

구현 원칙

  • 신규 화면과 상태 관리는 SodaLive/Sources/V2/CreatorChannel/ReplyDetail/** 아래에 둔다.
  • 기존 답글 작성 API를 새로 만들지 않는다.
  • 커뮤니티 답글 API는 CreatorCommunityRepository.createCommunityPostComment, getCommentReplyList, modifyComment를 사용한다.
  • 팬Talk 답글 API는 ExplorerRepository.writeCheers, modifyCheers를 사용한다.
  • 팬Talk 답글 작성/수정/삭제 성공 후에는 팬Talk 목록 첫 페이지를 재조회하는 callback을 호출한다.
  • 커뮤니티 원댓글이 비밀댓글이면 답글 작성 시 isSecret에 원댓글의 isSecret 값을 그대로 전달한다.
  • send 버튼 활성 기준은 trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false로 통일한다.
  • 답글 수정은 별도 화면을 열지 않고 하단 입력창에 수정 대상 내용을 채운 뒤 send 버튼으로 수정 API를 호출한다.
  • 수정/삭제는 Figma 더보기 메뉴 노출 범위 안에서 구현하되, 기존 권한 규칙을 유지한다.
  • ic_arrow_up_gray, ic_arrow_up_white asset은 이미 추가된 것으로 간주하고, 구현 시 asset catalog 등록 상태를 검증한다.

주요 대상 파일

생성

  • SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Models/CreatorChannelReplyDetailContext.swift
  • SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Models/CreatorChannelReplyDetailDisplayItem.swift
  • SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailView.swift
  • SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift
  • SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailTitleBar.swift
  • SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailFeedView.swift
  • SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailInputBar.swift
  • SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailActionPopup.swift

수정

  • SodaLive/Sources/App/AppStep.swift
  • SodaLive/Sources/ContentView.swift
  • SodaLive/Sources/V2/CreatorChannel/FanTalk/CreatorChannelFanTalkTabView.swift
  • SodaLive/Sources/V2/CreatorChannel/FanTalk/Components/CreatorChannelFanTalkListItem.swift
  • SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityTabView.swift
  • SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentListView.swift
  • SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentItemView.swift
  • SodaLive/Sources/I18n/I18n.swift
  • SodaLive.xcodeproj/project.pbxproj

TASK 체크리스트

Phase 1: 모델과 라우팅 기반

  • Task 1.1: 답글 상세 context/display 모델 생성

    • 대상 파일:
      • 생성: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Models/CreatorChannelReplyDetailContext.swift
      • 생성: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Models/CreatorChannelReplyDetailDisplayItem.swift
    • 작업 내용:
      • CreatorChannelReplyDetailContext.community.fanTalk source를 둔다.
      • 커뮤니티 context는 creatorId, postId, parentComment: GetCommunityPostCommentListItem을 보유한다.
      • 팬Talk context는 creatorId, parentFanTalk: CreatorChannelFanTalkItemResponse를 보유한다.
      • display item은 id, writerId, nickname, profileImageUrl, content, relativeTimeText, isSecret, isMine, isCreatorReply 여부를 담는다.
    • 검증 기준:
      • 실행 명령: rg "enum CreatorChannelReplyDetailContext|case community|case fanTalk|struct CreatorChannelReplyDetailDisplayItem|isSecret|isCreatorReply" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Models
      • 기대 결과: 커뮤니티와 팬Talk를 모두 표현하는 context/display 모델이 확인된다.
  • Task 1.2: AppStep에 답글 상세 route 추가

    • 대상 파일:
      • 수정: SodaLive/Sources/App/AppStep.swift
      • 수정: SodaLive/Sources/ContentView.swift
    • 작업 내용:
      • AppStepcreatorChannelReplyDetail(context:onFanTalkRefresh:) case를 추가한다.
      • ContentView switch에서 CreatorChannelReplyDetailView(context:onFanTalkRefresh:)를 반환한다.
      • onFanTalkRefresh는 팬Talk 상세에서 작성/수정/삭제 성공 후 팬Talk 목록 첫 페이지를 재조회하기 위한 optional callback으로 둔다.
    • 검증 기준:
      • 실행 명령: rg "creatorChannelReplyDetail|CreatorChannelReplyDetailView|onFanTalkRefresh" SodaLive/Sources/App/AppStep.swift SodaLive/Sources/ContentView.swift
      • 기대 결과: 새 navigation step과 화면 연결이 확인된다.

Phase 2: ViewModel과 기존 API 재사용

  • Task 2.1: 답글 상세 ViewModel 생성

    • 대상 파일:
      • 생성: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift
    • 작업 내용:
      • @Published 상태로 replyText, replies, isLoading, errorMessage, isShowPopup, selectedActionItem, editingItem을 둔다.
      • isSendEnabledreplyText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false로 계산한다.
      • configure(context:)에서 원댓글 display item과 초기 답글 display items를 구성한다.
      • 커뮤니티 context는 fetchCommunityReplies()로 기존 답글 목록을 조회한다.
      • 팬Talk context는 parentFanTalk.creatorReplies를 초기 답글 목록으로 표시한다.
    • 검증 기준:
      • 실행 명령: rg "final class CreatorChannelReplyDetailViewModel|replyText|replies|isSendEnabled|editingItem|configure\\(|fetchCommunityReplies|creatorReplies" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift
      • 기대 결과: 입력 상태, 수정 상태, 커뮤니티 조회, 팬Talk 초기 답글 표시 상태가 확인된다.
  • Task 2.2: 커뮤니티 답글 작성/수정/삭제 처리

    • 대상 파일:
      • 수정: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift
    • 작업 내용:
      • 작성 모드 send 시 CreatorCommunityRepository.createCommunityPostComment(comment:postId:parentId:isSecret:)를 호출한다.
      • parentId는 원댓글 id, postId는 context post id, isSecret은 원댓글 isSecret 값을 전달한다.
      • 수정 모드 send 시 ModifyCommunityPostCommentRequest(commentId:)에 수정 content를 담아 modifyComment(request:)를 호출한다.
      • 삭제 confirm 시 ModifyCommunityPostCommentRequest(commentId:)isActive = false를 담아 modifyComment(request:)를 호출한다.
      • 성공 후 replyTexteditingItem을 초기화하고 fetchCommunityReplies()로 목록을 갱신한다.
    • 검증 기준:
      • 실행 명령: rg "createCommunityPostComment|parentId|isSecret|ModifyCommunityPostCommentRequest|modifyComment|isActive = false|fetchCommunityReplies" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift
      • 기대 결과: 커뮤니티 작성/수정/삭제가 기존 repository로 연결된다.
  • Task 2.3: 팬Talk 답글 작성/수정/삭제 처리

    • 대상 파일:
      • 수정: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift
    • 작업 내용:
      • 작성 모드 send 시 ExplorerRepository.writeCheers(parentCheersId:creatorId:content:)를 호출한다.
      • parentCheersId는 원 팬Talk의 fanTalkId, creatorId는 context creator id를 전달한다.
      • 수정 모드 send 시 ExplorerRepository.modifyCheers(cheersId:content:isActive:)를 호출하고 isActivenil로 전달한다.
      • 삭제 confirm 시 ExplorerRepository.modifyCheers(cheersId:content:isActive:)를 호출하고 contentnil, isActivefalse로 전달한다.
      • 성공 후 replyTexteditingItem을 초기화하고 onFanTalkRefresh callback을 호출한다.
    • 검증 기준:
      • 실행 명령: rg "writeCheers|parentCheersId|modifyCheers|isActive: nil|isActive: false|onFanTalkRefresh|editingItem = nil" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift
      • 기대 결과: 팬Talk 작성/수정/삭제가 기존 ExplorerRepository로 연결되고 성공 후 첫 페이지 재조회 callback이 호출된다.

Phase 3: Figma 기반 UI 컴포넌트

  • Task 3.1: back-only title bar 구현

    • 대상 파일:
      • 생성: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailTitleBar.swift
    • 작업 내용:
      • Figma 기준으로 status bar 아래 60pt 높이 영역에 back chevron만 표시한다.
      • title text는 표시하지 않는다.
      • tap action은 부모에서 주입한다.
    • 검증 기준:
      • 실행 명령: rg "struct CreatorChannelReplyDetailTitleBar|ic_back|chevron|frame\\(height: 60\\)|onTapBack|Text\\(" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailTitleBar.swift
      • 기대 결과: back 전용 title bar가 있고 title text가 없어야 한다.
  • Task 3.2: 원댓글/답글 feed 컴포넌트 구현

    • 대상 파일:
      • 생성: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailFeedView.swift
    • 작업 내용:
      • 원댓글은 42pt 프로필, 닉네임, 상대 시간, 본문, 우측 더보기 버튼을 표시한다.
      • 답글이 없으면 답글 카드와 연결선을 표시하지 않는다.
      • 답글이 있으면 좌측 연결선과 Color.gray900, radius 14pt의 답글 카드를 표시한다.
      • 답글 카드는 20pt 프로필, 닉네임, 상대 시간, 본문, 우측 더보기 버튼을 표시한다.
      • 더보기 버튼은 CreatorChannelReplyDetailActionPopup 표시를 위한 item 선택 action을 호출한다.
    • 검증 기준:
      • 실행 명령: rg "struct CreatorChannelReplyDetailFeedView|Color\\.gray900|Color\\.gray800|RoundedRectangle|42|20|selectedActionItem|CreatorChannelReplyDetailDisplayItem|Shape|Path" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailFeedView.swift
      • 기대 결과: 원댓글/답글 카드, 답글 연결선, action item 선택 구조가 확인된다.
  • Task 3.3: 하단 답글 input bar 구현

    • 대상 파일:
      • 생성: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailInputBar.swift
    • 작업 내용:
      • 하단 고정 영역 높이는 Figma 기준 60pt로 시작한다.
      • placeholder는 I18n.CreatorChannelReplyDetail.replyPlaceholder를 사용한다.
      • 비활성 send 버튼은 Color.gray900 배경과 ic_arrow_up_gray 아이콘을 표시한다.
      • 활성 send 버튼은 Color.soda400 배경과 ic_arrow_up_white 아이콘을 표시한다.
      • isSendEnabled == false이면 tap 시 action을 호출하지 않는다.
    • 검증 기준:
      • 실행 명령: rg "struct CreatorChannelReplyDetailInputBar|replyPlaceholder|ic_arrow_up_gray|ic_arrow_up_white|Color\\.gray900|Color\\.soda400|isSendEnabled|onTapSend" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailInputBar.swift
      • 기대 결과: 활성/비활성 send 버튼 상태가 PRD와 일치한다.
  • Task 3.4: 수정/삭제 action popup 구현

    • 대상 파일:
      • 생성: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailActionPopup.swift
    • 작업 내용:
      • Figma 669:40468 기준으로 수정하기, 삭제하기 항목을 표시한다.
      • item 권한에 따라 수정/삭제 노출 여부를 주입받는다.
      • 수정하기 tap은 ViewModel의 beginEditing(item:)으로 연결한다.
      • 삭제하기 tap은 삭제 confirm dialog 표시로 연결한다.
    • 검증 기준:
      • 실행 명령: rg "struct CreatorChannelReplyDetailActionPopup|수정하기|삭제하기|canEdit|canDelete|onTapEdit|onTapDelete|Color\\.gray900|Color\\.gray700" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailActionPopup.swift
      • 기대 결과: 수정/삭제 팝업과 권한별 노출 조건이 확인된다.
  • Task 3.5: 답글 상세 화면 조립

    • 대상 파일:
      • 생성: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailView.swift
    • 작업 내용:
      • CreatorChannelReplyDetailTitleBar, CreatorChannelReplyDetailFeedView, CreatorChannelReplyDetailInputBar를 배치한다.
      • 배경은 Color.black을 사용한다.
      • 하단 input bar는 safe area 하단에 고정한다.
      • 수정 모드 진입 시 input bar에 기존 답글 내용을 표시한다.
      • 삭제 confirm dialog와 toast/loading 표시를 연결한다.
    • 검증 기준:
      • 실행 명령: rg "struct CreatorChannelReplyDetailView|CreatorChannelReplyDetailTitleBar|CreatorChannelReplyDetailFeedView|CreatorChannelReplyDetailInputBar|SodaDialog|sodaToast|Color\\.black|safeAreaInset|editingItem" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailView.swift
      • 기대 결과: 상세 화면 조립과 수정/삭제/오류 UI 연결이 확인된다.

Phase 4: 커뮤니티 진입 연결

  • Task 4.1: 커뮤니티 댓글 목록에서 답글 상세로 진입

    • 대상 파일:
      • 수정: SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentListView.swift
      • 수정: SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentItemView.swift
    • 작업 내용:
      • 기존 V1 댓글 목록 전체를 교체하지 않고, 원댓글 item tap 또는 답글 텍스트 tap을 새 V2 답글 상세 route로 연결한다.
      • context는 .community(creatorId:postId:parentComment:)로 구성한다.
      • 커뮤니티는 본인 여부와 관계없이 진입 가능하게 한다.
      • 기존 댓글 작성 sheet 동작은 유지한다.
    • 검증 기준:
      • 실행 명령: rg "creatorChannelReplyDetail|CreatorChannelReplyDetailContext|case \\.community|parentComment|postId|creatorId" SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentListView.swift SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentItemView.swift
      • 기대 결과: 커뮤니티 댓글에서 V2 답글 상세 route를 생성하는 코드가 확인된다.
  • Task 4.2: V2 커뮤니티 탭의 댓글 흐름 회귀 확인

    • 대상 파일:
      • 확인: SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityTabView.swift
    • 작업 내용:
      • 현재 댓글 버튼이 여는 CreatorCommunityCommentListView sheet가 유지되는지 확인한다.
      • sheet 내부 댓글 item에서 새 답글 상세 route로 진입 가능한지 확인한다.
    • 검증 기준:
      • 실행 명령: rg "CreatorCommunityCommentListView|isShowCommentListView|NavigationStack|creatorChannelReplyDetail" SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityTabView.swift SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment
      • 기대 결과: V2 커뮤니티 탭에서 댓글 목록 진입과 답글 상세 진입 경로가 함께 확인된다.

Phase 5: 팬Talk 진입 연결

  • Task 5.1: 팬Talk item tap action 추가

    • 대상 파일:
      • 수정: SodaLive/Sources/V2/CreatorChannel/FanTalk/Components/CreatorChannelFanTalkListItem.swift
      • 수정: SodaLive/Sources/V2/CreatorChannel/FanTalk/CreatorChannelFanTalkTabView.swift
    • 작업 내용:
      • CreatorChannelFanTalkListItemonTapDetail closure를 추가한다.
      • CreatorChannelFanTalkTabView에서 isOwnCreatorChannel == true일 때만 detail tap action을 route로 연결한다.
      • 본인 채널이 아니면 item tap으로 상세 화면에 진입하지 않는다.
      • 더보기/신고 버튼 tap은 상세 진입과 충돌하지 않게 button action으로 유지한다.
    • 검증 기준:
      • 실행 명령: rg "onTapDetail|isOwnCreatorChannel|creatorChannelReplyDetail|case \\.fanTalk|contentShape|Button" SodaLive/Sources/V2/CreatorChannel/FanTalk/Components/CreatorChannelFanTalkListItem.swift SodaLive/Sources/V2/CreatorChannel/FanTalk/CreatorChannelFanTalkTabView.swift
      • 기대 결과: 팬Talk 본인 채널에서만 상세 진입 route가 생성된다.
  • Task 5.2: 팬Talk 성공 후 첫 페이지 재조회 callback 연결

    • 대상 파일:
      • 수정: SodaLive/Sources/V2/CreatorChannel/FanTalk/CreatorChannelFanTalkTabView.swift
      • 수정: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift
    • 작업 내용:
      • 팬Talk detail context 생성 시 onFanTalkRefreshviewModel.fetchFirstPage(creatorId:)를 전달한다.
      • 팬Talk 답글 작성/수정/삭제 성공 후 callback을 호출한다.
    • 검증 기준:
      • 실행 명령: rg "onFanTalkRefresh|fetchFirstPage\\(creatorId: creatorId\\)|writeCheers|modifyCheers" SodaLive/Sources/V2/CreatorChannel/FanTalk/CreatorChannelFanTalkTabView.swift SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift
      • 기대 결과: 팬Talk 답글 mutation 성공 후 첫 페이지 재조회 연결이 확인된다.

Phase 6: 문구, asset, 프로젝트 등록

  • Task 6.1: I18n 문구 추가

    • 대상 파일:
      • 수정: SodaLive/Sources/I18n/I18n.swift
    • 작업 내용:
      • I18n.CreatorChannelReplyDetail.replyPlaceholder답글을 입력하세요 ko/en/ja 문구를 추가한다.
      • 수정/삭제 문구는 기존 공통 문구를 우선 재사용하고, 새 scope 문구가 필요하면 같은 enum에 추가한다.
    • 검증 기준:
      • 실행 명령: rg "CreatorChannelReplyDetail|replyPlaceholder|답글을 입력하세요" SodaLive/Sources/I18n/I18n.swift
      • 기대 결과: 답글 placeholder 다국어 문구가 확인된다.
  • Task 6.2: asset catalog와 프로젝트 파일 등록

    • 대상 파일:
      • 확인: SodaLive/Resources/Assets.xcassets/v2/ic_arrow_up_gray.imageset/Contents.json
      • 확인: SodaLive/Resources/Assets.xcassets/v2/ic_arrow_up_white.imageset/Contents.json
      • 수정: SodaLive.xcodeproj/project.pbxproj
    • 작업 내용:
      • ic_arrow_up_gray, ic_arrow_up_white asset이 Xcode asset catalog에 존재하는지 확인한다.
      • 신규 Swift 파일이 앱 target에 포함되도록 프로젝트 파일을 등록한다.
    • 검증 기준:
      • 실행 명령: rg "ic_arrow_up_gray|ic_arrow_up_white" SodaLive/Resources/Assets.xcassets/v2 SodaLive.xcodeproj/project.pbxproj
      • 실행 명령: rg "CreatorChannelReplyDetailView|CreatorChannelReplyDetailViewModel|CreatorChannelReplyDetailInputBar" SodaLive.xcodeproj/project.pbxproj
      • 기대 결과: arrow asset과 신규 Swift 파일 target 등록이 확인된다.

Phase 7: 빌드와 수동 검증

  • Task 7.1: 정적 검색 검증

    • 대상 파일:
      • 확인: SodaLive/Sources/V2/CreatorChannel/ReplyDetail/**
      • 확인: SodaLive/Sources/V2/CreatorChannel/FanTalk/**
      • 확인: SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/**
    • 검증 기준:
      • 실행 명령: rg "CreatorChannelReplyDetail|createCommunityPostComment|writeCheers|modifyCheers|ic_arrow_up_gray|ic_arrow_up_white|isSecret|onFanTalkRefresh" SodaLive/Sources
      • 기대 결과: 답글 상세 화면, 기존 API 재사용, send icon, 비밀 답글, 팬Talk refresh callback이 모두 확인된다.
  • Task 7.2: Debug 빌드 검증

    • 대상 파일:
      • 확인: SodaLive.xcworkspace
    • 검증 기준:
      • 실행 명령: xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build
      • 기대 결과: ** BUILD SUCCEEDED **
  • Task 7.3: 수동 UI 검증

    • 대상 파일:
      • 확인: 앱 런타임
    • 검증 기준:
      • 커뮤니티 댓글 item 터치 시 본인 여부와 관계없이 답글 상세 화면에 진입한다.
      • 팬Talk item 터치 시 본인 채널에서만 답글 상세 화면에 진입한다.
      • 답글 없음 상태가 Figma 669:40462와 같은 정보 구조로 표시된다.
      • 답글 있음 상태가 Figma 669:40468와 같은 답글 카드/연결선 구조로 표시된다.
      • 입력값이 없으면 send 버튼이 gray900 + ic_arrow_up_gray 상태이고 API를 호출하지 않는다.
      • 입력값이 있으면 send 버튼이 soda400 + ic_arrow_up_white 상태이고 기존 답글 작성 API를 호출한다.
      • 커뮤니티 비밀 원댓글에 답글 작성 시 isSecret == true로 전송된다.
      • 답글 수정하기 터치 시 하단 입력창에 기존 답글 내용이 채워지고 send 시 수정 API가 호출된다.
      • 답글 삭제하기 confirm 시 삭제 API가 호출되고 목록이 갱신된다.
      • 팬Talk 답글 작성/수정/삭제 성공 후 팬Talk 목록 첫 페이지가 재조회된다.

검증 기록

  • 2026-07-07: PRD docs/20260707_글_상세_답글_쓰기/prd.md, 문서 정책, 빌드/검증 가이드, 기존 팬Talk plan-task 형식을 확인하고 계획 문서를 작성했다.
  • 2026-07-07: 답글 상세 구현, 정적 검색 검증, SodaLive-dev Debug 빌드 검증을 완료했다. 런타임 수동 UI 검증(Task 7.3)은 미수행 상태로 남겼다.
  • 2026-07-07: 리뷰 지적 사항을 반영해 팬Talk 임시 답글 row 생성을 제거하고 FanTalk 수정/삭제에 id > 0 guard를 추가했다. 답글 action popup은 row frame 기반 위치로 변경했고, popup 문구는 I18n.Explorer.edit, I18n.Common.delete를 사용하도록 수정했다. 정적 검색, ast-grep 검색, SodaLive-dev Debug 빌드 검증을 완료했다.
  • 2026-07-07: 추가 리뷰 지적 사항을 반영해 FanTalk 답글 갱신이 parent fanTalkId를 찾을 때까지 hasNext 기반으로 페이지를 조회하도록 수정했다. 커뮤니티 답글 상세는 totalCount 기반 pagination과 마지막 답글 onAppear 추가 조회를 연결했고, 커뮤니티 댓글 item의 전체 row tap은 제거해 본문/답글 텍스트만 답글 상세로 진입하도록 제한했다. 정적 검색, ast-grep 검색, SodaLive-dev Debug 빌드 검증을 완료했다.