Files
sodalive-ios/docs/20260602_메인_홈_추천_UI_API_연동/prd.md

27 KiB
Raw Blame History

PRD: 메인 홈 추천 탭 UI와 API 연동

1. Overview

메인 홈 화면의 추천 탭을 Figma 디자인 기준으로 구성하고, 신규 API GET /api/v2/home/recommendations 응답을 섹션별 UI에 연동한다.

기존 홈 API에 필드를 추가하지 않고 홈 추천 전용 API, Repository, ViewModel, 화면 조립 계층을 새로 만든다. MainHomeView는 홈 상단 공통 shell과 추천/랭킹/팔로잉 탭 전환만 담당하고, 탭 아래 콘텐츠는 Recommendation, Ranking, Following 하위 폴더의 전용 View로 분리한다. 이미 생성된 V2 공용 widget과 저장소 컴포넌트로 처리 가능한 UI는 재사용하고, 추천 탭에서만 쓰이는 조립 UI는 SodaLive/Sources/V2/Main/Home/Recommendation/Components/** 아래에 둔다.

2. Problem

  • 추천 탭 전용 데이터가 기존 홈 API와 섞이면 응답/화면 책임이 커지고 회귀 위험이 커진다.
  • Figma 추천 탭은 라이브, 배너, 최근 활동, 최근 데뷔, AI 캐릭터, 응원 크리에이터, 인기 커뮤니티, 사업자 정보 등 여러 독립 섹션으로 구성된다.
  • 섹션별 UI가 많으므로 한 화면 파일에 직접 구현하면 유지보수와 검증이 어려워진다.
  • FeedCommunityView는 추천 탭 요구에 맞춰 키워드 영역 제거, 이미지 표시, 오디오 재생, 유료/구매 상태 UI가 필요하다.
  • 사업자 정보는 외부 라이브러리 없이 최대 3줄 말줄임표, 더보기, 접기 동작을 제공해야 한다.
  • 모두 팔로우하기는 한 번의 요청으로 여러 크리에이터를 팔로우하지만 현재 버튼 터치 즉시 API를 호출하므로, 사용자가 대상을 충분히 확인하지 못한 상태에서 의도하지 않은 크리에이터까지 팔로우할 수 있다.

3. Goals

  • 추천 탭 진입 시 GET /api/v2/home/recommendations를 호출하고 응답 데이터로 화면을 구성한다.
  • 기존 API에 추천 endpoint를 추가하지 않고 신규 MainHomeRecommendationApi, Repository, ViewModel 계층을 만든다.
  • Figma 확인 시 이미 생성된 widget이나 기존 V2 공용 컴포넌트로 처리 가능한 부분은 재사용한다.
  • MainHomeView를 추천/랭킹/팔로잉 탭 shell로 유지하고, 추천 탭 콘텐츠는 MainHomeRecommendationView에서 조립한다.
  • 랭킹/팔로잉 탭은 MainHomeRankingView, MainHomeFollowingView로 별도 파일/폴더를 준비해 이후 구현이 MainHome shell에 누적되지 않게 한다.
  • 섹션별 UI를 작은 단위의 Custom Widget으로 분리한다.
  • RecommendedActivityType 서버 enum 값을 앱 enum으로 변환하고 I18n 문구로 표시한다.
  • 빈 데이터 섹션은 제목과 컨테이너를 표시하지 않는다.
  • 사업자 정보 섹션은 화면 width를 채우고, 기본 3줄 말줄임표와 더보기/접기 전환을 지원한다.
  • FeedCommunityView는 추천 탭 요구에 맞게 세로 피드형 이미지/오디오/유료 커뮤니티 포스트 UI를 지원한다.
  • 추천 탭의 모든 모두 팔로우하기 진입점은 로그인 사용자에게 확인 Dialog를 먼저 표시하고, 명시적으로 확인한 경우에만 기존 모두 팔로우 API를 호출한다.

4. Non-Goals

  • 추천 필모그래피 섹션은 만들지 않는다.
  • 또 다른 모습 섹션은 만들지 않는다.
  • 기존 홈 API 또는 기존 HomeApi/api/v2/home/recommendations를 추가하지 않는다.
  • 외부 라이브러리를 추가하지 않는다.
  • Figma 로컬 asset URL 또는 Figma 웹 URL을 앱 코드에 직접 사용하지 않는다.
  • 서버 응답 스펙에 없는 개별 팔로우 상태, 페이지네이션, 정렬/필터 기능은 이번 범위에 포함하지 않는다.
  • Figma node-id=309-19775구매완료 버튼은 구현하지 않는다.
  • 장르 크리에이터 섹션은 현재 추천 탭에 노출하지 않는다. 단, API 디코딩을 위해 genreCreators 응답 모델 필드는 유지한다.
  • 개별 크리에이터 팔로우/언팔로우 흐름에는 이번 Confirm Dialog를 적용하지 않는다.
  • 기존 모두 팔로우 API의 endpoint, request/response 계약과 서버 동작은 변경하지 않는다.

5. Target Users

  • 앱 홈에서 추천 라이브, 크리에이터, 콘텐츠, 커뮤니티를 빠르게 탐색하는 사용자
  • 최근 활동 타입과 추천 콘텐츠 상태를 현재 앱 언어와 디자인에 맞게 확인하려는 사용자
  • 사업자 정보를 짧게 확인하고 필요할 때 전체 내용을 펼쳐 보려는 사용자

6. User Stories

  • 사용자는 홈 추천 탭에서 현재 라이브 중인 크리에이터와 추천 콘텐츠를 한 화면에서 보고 싶다.
  • 사용자는 최근 활동한 크리에이터의 활동 타입을 라이브, 오디오, 커뮤니티처럼 이해 가능한 문구로 보고 싶다.
  • 사용자는 이미지가 포함된 커뮤니티 포스트와 유료/구매 상태를 카드에서 구분하고 싶다.
  • 사용자는 사업자 정보를 기본적으로 짧게 보고, 필요할 때 더보기/접기로 전환하고 싶다.
  • 사용자는 로그인이 필요하거나 민감 콘텐츠 제한이 필요한 상세 화면에 진입할 때 기존 홈과 같은 로그인/본인인증/콘텐츠 보기 설정 안내를 받고 싶다.
  • 사용자는 여러 크리에이터를 한 번에 팔로우하기 전에 영향을 확인하고, 원하지 않으면 API 요청 없이 취소하고 싶다.

7. Core Requirements

7.1 추천 홈 데이터 조회

API

  • Method: GET
  • Path: /api/v2/home/recommendations
  • 기존 API에 추가하지 않고 신규 API 타입으로 만든다.
  • 인증: 기존 인증 헤더 패턴과 동일하게 Authorization: Bearer {token} 사용
  • 응답 래퍼: 기존 관례대로 ApiResponse<HomeRecommendationResponse> 디코딩

Response

data class HomeRecommendationResponse(
    val lives: List<HomeLiveItem>,
    val banners: List<RecommendationBannerResponse>,
    val recentlyActiveCreators: List<HomeActiveCreatorItem>,
    val recentDebutCreators: List<HomeCreatorItem>,
    val aiCharacters: List<HomeAiCharacterItem>,
    val genreCreators: List<HomeGenreCreatorGroupItem>,
    val cheerCreators: List<HomeCreatorItem>,
    val popularCommunityPosts: List<HomePopularCommunityPostItem>
)

data class HomeLiveItem(
    val roomId: Long,
    val creatorNickname: String,
    val creatorProfileImage: String
)

data class HomeActiveCreatorItem(
    val creatorId: Long,
    val creatorNickname: String,
    val creatorProfileImage: String,
    val activityType: String,
    val activityAt: String,
    val targetId: Long?
)

data class HomeCreatorItem(
    val creatorId: Long,
    val creatorNickname: String,
    val creatorProfileImage: String
)

data class HomeAiCharacterItem(
    val characterId: Long,
    val creatorId: Long,
    val name: String,
    val description: String,
    val profileImage: String?,
    val totalChatCount: Long,
    val originalWorkTitle: String?
)

data class HomeGenreCreatorGroupItem(
    val genreName: String,
    val creators: List<HomeCreatorItem>
)

RecommendationBannerResponse

data class RecommendationBannerResponse(
    val imageUrl: String,
    val eventItem: EventItem?,
    val creatorId: Long?,
    val seriesId: Long?,
    val link: String?
)

배너 탭 이동은 eventItem, creatorId, seriesId, link 순서로 첫 non-null 값을 사용한다.

  • eventItem -> 이벤트 상세
  • creatorId -> 크리에이터 상세
  • seriesId -> 시리즈 상세
  • link -> 외부 URL 열기

HomePopularCommunityPostItem

data class HomePopularCommunityPostItem(
    val postId: Long,
    val creatorId: Long,
    val creatorNickname: String,
    val creatorProfileImage: String?,
    val imageUrl: String?,
    val audioUrl: String?,
    val content: String,
    val price: Int,
    val createdAt: String,
    val likeCount: Long,
    val commentCount: Long,
    val isLiked: Boolean,
    val existOrdered: Boolean
)

Swift 모델은 위 필드명을 우선 기준으로 Decodable을 구성한다. 서버 nullable 필드는 Swift optional로 선언한다. 현재 코드에 과거 추정 필드명이 이미 있다면 신규 스펙 필드명을 추가하거나 보정하고, 실제 사용 UI는 신규 스펙 필드명을 기준으로 매핑한다.

7.2 활동 타입 다국어 표시

서버 enum:

enum class RecommendedActivityType(val code: String) {
    LIVE("LIVE"),
    AUDIO("AUDIO"),
    COMMUNITY("COMMUNITY"),
    LIVE_REPLAY("LIVE_REPLAY")
}

앱 변환:

  • LIVE, LIVE_REPLAY -> I18n.HomeRecommendation.activityLive
  • AUDIO -> I18n.HomeRecommendation.activityAudio
  • COMMUNITY -> I18n.HomeRecommendation.activityCommunity
  • 알 수 없는 값은 서버 코드를 그대로 노출하지 않고 보조 문구를 숨긴다.
  • LIVELIVE_REPLAY는 표시 문구만 동일하게 사용하며, 탭 이동 분기를 구분할 수 있도록 서로 다른 앱 enum case로 변환한다.

다국어 기본 문구:

  • ko: 라이브, 오디오, 커뮤니티
  • en: Live, Audio, Community
  • ja: ライブ, オーディオ, コミュニティ

7.3 추천 탭 상세 진입 guard

기본 방향:

  • 추천 API 호출과 추천 탭 섹션 노출 자체는 로그인/본인인증/민감 콘텐츠 보기 설정으로 막지 않는다.
  • guard는 라이브, 크리에이터, 오디오 콘텐츠, AI 캐릭터, 커뮤니티 등 사용자가 상세 화면으로 진입하는 탭 액션 앞에서 적용한다.
  • 신규 MainHomeView에 Bootpay 인증 UI와 인증 상태를 중복 구현하지 않고, V2 MainView의 기존 token, auth, isShowAuthView, isShowAuthConfirmView, pendingAction, authConfirmDialog, authView 인프라를 재사용한다.

진입 규칙:

  • 토큰이 비어 있으면 AppState.shared.setAppStep(step: .login)으로 로그인 화면으로 이동한다.
  • 민감/성인 콘텐츠 진입이 필요한 항목은 한국 사용자이고 auth == false이면 원래 이동 액션을 pendingAction에 저장하고 본인인증 안내 dialog를 표시한다.
  • 본인인증 성공 후 pendingAction을 실행해 원래 상세 화면으로 이동한다.
  • 민감 콘텐츠 보기 설정이 꺼져 있으면 AppState.shared.setPendingContentSettingsGuideMessage(I18n.Settings.adultContentEnableGuide)로 안내 문구를 예약하고 AppState.shared.setAppStep(step: .contentViewSettings)로 이동한다.
  • 위 조건을 통과한 경우에만 liveDetail, creatorDetail, contentDetail, characterDetail 등 실제 상세 이동을 실행한다.
  • 추천 탭 현재 라이브 아이템은 roomId가 항상 존재하는 값으로 취급하고, 아이템 탭 시 상세 화면을 거치지 않고 기존 LiveViewModel.enterLiveRoom(roomId:) 흐름을 호출해 방 상세 조회, 입장 전 결제 확인, 비밀방 비밀번호 dialog, LiveRoomViewV2 입장을 재사용한다.
  • 최근 활동 크리에이터에서 서버 원본 activityType == LIVE이고 targetId != null이면 targetId를 라이브룸 roomId로 사용해 기존 라이브룸 입장 흐름을 실행한다.
  • 최근 활동 크리에이터에서 서버 원본 activityType == LIVE이고 targetId == null이면 creatorId를 사용해 크리에이터 채널로 이동한다.
  • 최근 활동 크리에이터의 creatorId는 서버에서 항상 유효한 양수로 제공하지만, 앱에서도 creatorId > 0을 확인한 뒤에만 크리에이터 채널 이동을 실행한다. 검사를 통과하지 못하면 이동하지 않는다.
  • LIVE_REPLAYAUDIO와 동일하게 targetId를 콘텐츠 ID로 사용해 콘텐츠 상세 페이지로 이동한다. targetId가 없으면 이동하지 않으며, LIVEcreatorId fallback은 적용하지 않는다.
  • 최근 활동 크리에이터의 AUDIO, COMMUNITY, 알 수 없는 활동 타입은 기존 탭 동작을 유지한다.
  • 최근 활동 크리에이터에서 activityType == COMMUNITY인 아이템은 targetId를 커뮤니티 게시물 postId로 취급하고, 탭 시 커뮤니티 게시물 상세 페이지로 이동한다.
  • 인기 커뮤니티 섹션의 커뮤니티 게시물은 postId 기준으로 커뮤니티 게시물 상세 페이지로 이동한다. 좋아요, 구매, 오디오 재생 액션은 기존 개별 액션을 유지한다.

라이브 항목 주의사항:

  • 기존 홈의 라이브 guard는 roomIdisAdult를 함께 받아 성인 여부를 판단한다.
  • 현재 HomeLiveItem 신규 응답 스펙에는 isAdult가 없으므로, 라이브 성인 guard를 앱에서 적용하려면 서버 응답에 isAdult 또는 동등한 필드가 필요하다.
  • 해당 필드가 없으면 앱에서 성인 여부를 임의 추정하지 않고, 서버 필터링 전제인지 확인한다.

7.4 FeedCommunityView

참조 Figma:

  • 인기 커뮤니티 섹션: node-id=24-5645
  • Text Only Feed: node-id=567-17875
  • Text + Image Feed: node-id=567-17878

요구사항:

  • 키워드 영역을 제거한다.
  • 인기 커뮤니티 섹션은 가로 캐러셀이 아니라 세로 피드 목록으로 배치한다.
  • 커뮤니티 포스트 이미지를 추가한다.
  • imageUrl == nil이면 이미지 영역 없이 본문 중심으로 표시한다.
  • imageUrl != nil && price > 0 && existOrdered == false이면 유료 미구매 상태 UI를 표시한다.
  • imageUrl != nil && (price <= 0 || existOrdered == true)이면 이미지를 일반 노출한다.
  • audioUrl이 있으면 이미지 중앙에 재생/일시정지 버튼을 표시하고 기존 커뮤니티 오디오 재생 흐름을 재사용한다.
  • 유료 미구매 커뮤니티 포스트는 기존 커뮤니티 구매 API로 구매 가능해야 한다.
  • 구매완료 버튼은 표시하지 않는다.
  • 작성자, 본문, 생성 시간, 좋아요 수, 댓글 수를 표시한다.
  • 반응 정보는 Figma 기준으로 댓글 아이콘/댓글 수를 먼저, 좋아요 아이콘/좋아요 수를 뒤에 표시한다.
  • 생성 시간은 UTC 값을 디바이스 Timezone 기준 상대 날짜로 표시한다.
  • 게시물 카드의 일반 탭 액션과 댓글 아이콘 탭 액션은 커뮤니티 게시물 상세 페이지로 이동한다.

7.5 사업자 정보 더보기/접기

요구사항:

  • UI 가장 마지막에 사업자 정보 섹션을 배치한다.
  • width는 화면에 채운다.
  • 외부 라이브러리를 사용하지 않는다.
  • 기본 상태는 최대 3줄 표시, 말줄임표 적용, 더보기 액션 제공
  • 더보기 터치 시 전체 표시로 전환하고 접기 액션 제공
  • 접기 터치 시 다시 3줄 말줄임표 상태로 돌아간다.
  • 실제 텍스트가 3줄 이하이면 더보기/접기 버튼은 숨긴다.

구현 방향:

  • SwiftUI TextlineLimit(isExpanded ? nil : 3) 기반으로 구현한다.
  • 줄 수 판정은 제한/무제한 높이 비교 또는 Geometry 기반 측정 방식을 사용한다.
  • 사업자 정보 wrapper는 MainHomeBusinessInfoSection, 재사용 가능한 텍스트 UI는 V2ExpandableTextView로 분리한다.

7.6 모두 팔로우 확인 Dialog

적용 범위:

  • 메인 홈 추천 탭에서 공통 onTapFollowAll 흐름을 사용하는 모든 모두 팔로우하기 진입점에 적용한다.
  • 현재 화면에 노출되는 최근 응원이 많은 크리에이터 섹션뿐 아니라, 같은 공통 흐름에 연결되는 다른 모두 팔로우 진입점도 동일한 확인 절차를 사용한다.
  • 현재 미노출 상태인 장르 크리에이터 섹션을 다시 노출하는 작업은 이번 범위에 포함하지 않는다.

로그인 및 확인 흐름:

  1. 비로그인 사용자가 모두 팔로우하기를 터치하면 기존 동작과 동일하게 확인 Dialog 없이 로그인 화면으로 이동한다.
  2. 로그인 사용자가 모두 팔로우하기를 터치하면 기존 SodaV2ActionModal을 사용한 Confirm Dialog를 표시한다.
  3. Dialog가 표시된 시점에는 POST /api/v2/home/recommendations/creators/follow를 호출하지 않는다.
  4. 사용자가 팔로우 하기를 터치하면 Dialog를 닫고 선택한 섹션의 기존 모두 팔로우 action을 한 번 실행한다.
  5. 사용자가 취소 또는 dimmed 영역을 터치하면 Dialog를 닫고 보류한 action을 폐기하며 API를 호출하지 않는다.
  6. 로그인 화면에서 돌아온 뒤 모두 팔로우를 자동 실행하지 않는다. 사용자가 버튼을 다시 터치하면 확인 Dialog부터 새로 진행한다.
  7. 기존 모두 팔로우 완료, 호출 중, 오류 toast와 중복 호출 방지 동작은 유지한다.

다국어 문구:

용도 ko en ja
제목 모두 팔로우할까요? Follow all creators? すべてのクリエイターをフォローしますか?
설명 추천된 크리에이터를 모두 팔로우합니다. Youll follow all recommended creators. おすすめのクリエイターをすべてフォローします。
확인 팔로우 하기 Follow フォローする
취소 I18n.Common.cancel 재사용 I18n.Common.cancel 재사용 I18n.Common.cancel 재사용

8. UX / UI Expectations

8.1 Figma 기준

  • 추천 화면: node-id=24-5514
  • FeedCommunityView 유료 미구매: node-id=309-19774
  • FeedCommunityView 유료 구매함 또는 무료: node-id=309-19775

Figma 확인 시 이미 생성해 둔 widget 또는 저장소 내 공용 컴포넌트로 구현 가능한 UI는 재사용한다. 단, Figma asset URL을 코드에 직접 넣지 않고 프로젝트 asset 또는 기존 이미지 로딩 패턴을 사용한다.

8.2 화면 구성

아래 도식은 구현 대상만 포함한다. 추천 필모그래피, 또 다른 모습은 제외한다.

MainHomeView
└─ HomeTitleBar 재사용
└─ 홈 상단 탭(추천/랭킹/팔로잉)
└─ 선택된 탭 콘텐츠
   ├─ MainHomeRecommendationView
   │  └─ ScrollView
   │     ├─ 현재 라이브 섹션
   │     ├─ 배너 섹션
   │     ├─ 최근 활동 크리에이터 섹션
   │     ├─ 최근 데뷔한 크리에이터 섹션
   │     ├─ AI 캐릭터 섹션
   │     ├─ 최근 응원이 많은 크리에이터 섹션
   │     ├─ 인기 커뮤니티 섹션
   │     └─ 사업자 정보 섹션
   ├─ MainHomeRankingView
   └─ MainHomeFollowingView
└─ MainTabBarView는 기존 MainView 구조에서 유지

8.3 재사용 컴포넌트 후보

  • SodaLive/Sources/V2/Component/HomeTitleBar.swift
  • SodaLive/Sources/V2/Component/SectionTitle.swift
  • SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift
  • SodaLive/Sources/V2/Component/Card/AiCharacterCard.swift
  • SodaLive/Sources/V2/Component/Card/CommunityPostCard.swift
  • SodaLive/Sources/V2/Component/Creator/CreatorProfileGrid.swift
  • SodaLive/Sources/V2/Component/Creator/CreatorProfileItem.swift
  • SodaLive/Sources/V2/Component/Text/V2ExpandableTextView.swift

이미 존재하는 컴포넌트가 Figma 요구를 일부만 충족하면 새 컴포넌트를 중복 생성하지 않고 필요한 범위만 보완한다.

8.4 컴포넌트 위치 기준

  • 홈 상단 공통 shell: SodaLive/Sources/V2/Main/Home/MainHomeView.swift
  • 추천 탭 루트: SodaLive/Sources/V2/Main/Home/Recommendation/MainHomeRecommendationView.swift
  • 추천 탭 API, Repository, ViewModel, 모델: SodaLive/Sources/V2/Main/Home/Recommendation/**
  • 추천 탭에서만 쓰는 섹션 wrapper: SodaLive/Sources/V2/Main/Home/Recommendation/Components/**
  • 랭킹 탭 루트: SodaLive/Sources/V2/Main/Home/Ranking/MainHomeRankingView.swift
  • 팔로잉 탭 루트: SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift
  • 여러 페이지에서 재사용 가능한 Card/Banner/Text/Button/Creator widget: SodaLive/Sources/V2/Component/**
  • 기존 로직 수정이 아닌 신규 View/ViewModel/Repository는 SodaLive/Sources/V2/** 아래에 둔다.

9. Technical Constraints

  • 앱 소스 변경은 SodaLive/Sources/**에서 수행한다.
  • Pods/**, generated/**, build/**는 직접 수정하지 않는다.
  • 기존 HomeApi에 추천 API를 추가하지 않는다.
  • 외부 라이브러리를 추가하지 않는다.
  • 이미지 로딩은 기존 앱 이미지 컴포넌트/패턴을 따른다.
  • 인증 헤더는 기존 UserDefaultsKey.token 기반 패턴을 따른다.
  • 서버 Long 값은 Swift에서 기존 라우팅/모델 관례와 맞는 Int 또는 Int64로 사용한다.
  • 사용자 노출 문구는 가능한 I18n에 추가한다.
  • 모두 팔로우 Confirm Dialog는 기존 SodaV2ActionModalI18n.Common.cancel을 재사용하고 새 Dialog 컴포넌트 또는 외부 의존성을 추가하지 않는다.
  • 모두 팔로우 API/Repository/ViewModel 계약은 유지하고, 공통 callback에서 API action 실행 시점만 확인 이후로 지연한다.
  • 상세 진입 guard는 MainHomeView 내부에 인증 UI를 중복 구현하지 않고, V2 MainView의 기존 인증/민감 콘텐츠 guard 인프라를 재사용한다.
  • MainHomeView에는 추천 탭의 섹션 조립을 직접 누적하지 않고, 탭별 콘텐츠 View를 조합하는 역할만 둔다.
  • Open Questions에 남긴 항목은 임의 구현하지 않고 확인 후 반영한다.

10. Success Criteria

  • 추천 탭에서 GET /api/v2/home/recommendations를 호출하고 success == true 응답 데이터를 섹션별로 렌더링한다.
  • 응답 배열이 비어 있는 섹션은 화면에 표시하지 않는다.
  • 추천 필모그래피, 또 다른 모습은 코드와 화면에 포함하지 않는다.
  • LIVE, LIVE_REPLAY, AUDIO, COMMUNITY 활동 타입이 I18n 문구로 표시된다.
  • FeedCommunityView에서 키워드 영역이 제거되고, 이미지/유료 미구매/유료 구매함 또는 무료 상태가 조건에 맞게 표시된다.
  • FeedCommunityView구매완료 버튼이 표시되지 않는다.
  • 사업자 정보는 마지막 섹션에서 화면 width를 채우고, 기본 3줄 말줄임표, 더보기, 전체 표시, 접기 전환이 동작한다.
  • 상세 진입 탭 액션은 기존 홈과 같은 로그인, 한국 사용자 본인인증, 민감 콘텐츠 보기 설정 guard를 통과한 뒤에만 실행된다.
  • 최근 활동 크리에이터의 LIVE 활동은 targetId가 있으면 라이브룸으로 이동하고, targetId가 없고 creatorId > 0이면 크리에이터 채널로 이동한다.
  • 최근 활동 크리에이터의 LIVE_REPLAY 표시 문구는 기존과 같이 라이브 계열 I18n 문구를 유지하되, 탭 시에는 AUDIO와 동일하게 targetId 기반 콘텐츠 상세 페이지로 이동하며 creatorId fallback은 적용되지 않는다.
  • 최근 활동 크리에이터의 AUDIO, COMMUNITY, 알 수 없는 활동 타입의 기존 동작에 회귀가 없다.
  • 최근 활동 크리에이터의 COMMUNITY 활동과 인기 커뮤니티 섹션의 게시물은 커뮤니티 게시물 상세 페이지로 이동한다.
  • MainHomeView는 추천/랭킹/팔로잉 탭 shell 역할만 하고, 추천 탭 섹션 조립은 MainHomeRecommendationView에 분리되어 있다.
  • 반복 UI는 기존 widget 또는 공용 컴포넌트를 재사용하고 불필요하게 중복 구현하지 않는다.
  • 로그인 사용자가 추천 탭의 모두 팔로우하기를 터치하면 Confirm Dialog가 표시되고, 확인 전에는 모두 팔로우 API 요청이 발생하지 않는다.
  • Dialog에서 팔로우 하기를 한 번 터치하면 해당 섹션의 기존 모두 팔로우 API가 한 번 호출된다.
  • Dialog에서 취소 또는 dimmed 영역을 터치하면 모두 팔로우 API 요청이 발생하지 않는다.
  • 비로그인 사용자는 기존처럼 로그인 화면으로 이동하며, 확인 Dialog 또는 로그인 완료 후 자동 팔로우가 실행되지 않는다.
  • 모두 팔로우 Dialog의 제목, 설명, 확인 버튼은 ko/en/ja로 표시되고 취소 버튼은 기존 공통 I18n을 재사용한다.
  • 빌드가 성공하고, 가능하면 ViewModel 디코딩/상태 전환 검증을 수행한다.

11. Open Questions

  • RecommendationBannerResponse는 변경된 백엔드 스펙 기준으로 eventItem, creatorId, seriesId, link 순서의 이동 규칙을 사용한다.
  • 각 섹션별 최대 표시 개수와 가로/세로 스크롤 정책이 Figma 기준 그대로인지, 서버 응답 전체를 모두 표시해야 하는지 확인이 필요하다.
  • HomeLiveItem에 민감/성인 라이브 여부를 판단할 isAdult 또는 동등한 필드가 추가되는지, 아니면 서버에서 추천 라이브를 사전 필터링하는지 확인이 필요하다.
  • 커뮤니티 audioUrl을 추천 탭 카드에서 표시/재생해야 하는지 확인이 필요하다.
  • 각 카드 터치 시 상세 이동 대상이 모두 정의되어 있는지 확인이 필요하다. 단, 최근 활동 LIVE, LIVE_REPLAY, COMMUNITY, 인기 커뮤니티 게시물의 이동 규칙은 확정한다.
  • 모두 팔로우 확인 Dialog의 적용 범위, 로그인 순서, 취소 동작, 문구와 다국어에는 열린 질문이 없다.

12. Verification Plan

  • 문서 검증: API URL, 응답 모델, 제외 섹션, FeedCommunityView, 사업자 정보 요구가 PRD와 계획 문서에 반영되었는지 확인한다.
  • 정적 검증: 신규 추천 API가 기존 HomeApi에 추가되지 않았고, Figma URL이 앱 코드에 직접 포함되지 않았는지 확인한다.
  • 빌드 검증: docs/agent-guides/build-test-verification.md 기준으로 가능한 iOS 빌드 또는 최소 정적 검증을 실행한다.
  • 기능 검증: 추천 API 성공/실패, 빈 섹션, 활동 타입 I18n, 상세 진입 guard, 최근 활동 LIVEtargetId 유무별 이동, creatorId 양수 검사, LIVE_REPLAY의 콘텐츠 상세 이동, 다른 활동 타입의 회귀 여부, 커뮤니티 카드 상태, 사업자 정보 더보기/접기를 확인한다.
  • 모두 팔로우 기능 검증: 로그인/비로그인 상태를 구분해 Dialog 표시 여부를 확인하고, 확인 전·취소·dimmed 영역 터치에는 API 요청이 0회이며 팔로우 하기 선택 시에만 요청이 1회인지 확인한다.
  • 다국어 검증: 앱 언어를 ko/en/ja로 전환해 모두 팔로우 Dialog의 제목, 설명, 확인, 취소 문구를 확인한다.

13. Decision Log

2026-07-30 모두 팔로우 확인 Dialog 인터뷰

  • 메인 홈 추천 탭의 모든 모두 팔로우하기 진입점에 공통 확인 Dialog를 적용한다.
  • 비로그인 사용자는 기존처럼 로그인 화면으로 바로 이동하고, 로그인 후 자동 팔로우하지 않는다.
  • 로그인 사용자는 팔로우 하기를 명시적으로 선택한 경우에만 API를 호출한다.
  • 취소와 dimmed 영역 터치는 모두 보류 action 폐기 및 API 미호출로 처리한다.
  • Dialog 문구는 7.6의 ko/en/ja 문구로 확정하며 관련 열린 질문은 없다.