10 KiB
10 KiB
PRD: 라이브 썸네일 컴포넌트
1. Overview
Figma 24:4999, 24:5017 디자인을 기준으로 현재 라이브 중인 상태를 표시하는 Android XML Views 기반 라이브 썸네일 컴포넌트를 문서화한다.
2. Problem
- 현재 Figma의 프로필 이미지 영역은 빈 이미지로 표시되어 있으나, 실제 앱에서는 라이브 크리에이터의 프로필 또는 커버 이미지를 표시해야 한다.
- 라이브 썸네일은 세로형 프로필 variant와 가로형 상세 variant가 함께 필요하다.
- 라이브 제목과 크리에이터 이름이 지정된 영역을 넘으면 UI가 깨질 수 있으므로 모든 텍스트는 1줄 제한과 말줄임 처리가 필요하다.
- 기존 라이브 관련 layout은 화면별로 흩어져 있어, 새 Figma variant를 재사용 가능한 v2 widget 계약으로 분리할 필요가 있다.
3. Goals
- Figma
24:4999기준 세로형Simple라이브 썸네일을 제공한다. - Figma
24:5017기준 가로형Detail라이브 썸네일을 제공한다. - Figma에서 빈 이미지로 보이는 영역에는 실제 이미지 URL을 바인딩할 수 있는
ImageView를 제공한다. - 모든 텍스트는
maxLines=1,ellipsize=end로 표시한다. - LIVE 배지, 라이브 테두리, 배경, 간격, typography는 Figma 기준을 Android resource로 옮긴다.
- 이미지 로딩 라이브러리는 컴포넌트 내부에 고정하지 않고, 기존 호출부가 Coil/Glide 등 현재 화면의 방식을 사용해 이미지를 로드할 수 있도록 한다.
4. Non-Goals
- 이번 문서 범위에서는 서버 API 또는 DTO 필드명을 변경하지 않는다.
- 라이브 목록 화면 전체 개편, 정렬, pagination, filtering은 포함하지 않는다.
- Compose 컴포넌트 또는 Compose Theme를 추가하지 않는다.
- Figma에 없는 skeleton loading, shimmer, pressed animation, 시청자 수, 가격, 잠금 배지는 추가하지 않는다.
- 이미지 로딩 라이브러리 교체를 수행하지 않는다.
- 라이브 상태 계산 로직 또는 라이브 입장 정책을 새로 만들지 않는다.
5. Target Users
- 라이브 중인 크리에이터를 탐색하는 앱 사용자.
- 메인/라이브/크리에이터 화면에서 라이브 썸네일 UI를 재사용해야 하는 Android 개발자.
6. User Stories
- 사용자는 현재 라이브 중인 크리에이터를 LIVE 배지와 테두리로 빠르게 구분하고 싶다.
- 사용자는 라이브 제목과 크리에이터 이름이 길어도 레이아웃이 깨지지 않는 썸네일을 보고 싶다.
- 개발자는 같은 라이브 상태 UI를 세로형/가로형 variant로 일관되게 바인딩하고 싶다.
- 개발자는 기존 이미지 로딩 방식을 유지하면서 실제 이미지 URL만 연결하고 싶다.
7. Core Features
Live Thumbnail Widget
현재 라이브 중인 콘텐츠를 Simple, Detail 두 variant로 표시한다.
Figma References
- Simple live thumbnail: 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=24-4999&m=dev
- Detail live thumbnail: 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=24-5017&m=dev
Variant Requirements
| Variant | Figma node | Size policy | Primary use |
|---|---|---|---|
Simple |
24:4999 |
기본 폭 70dp, profile area 70dp x 76dp, 이름 영역 70dp |
가로 스크롤 프로필 목록, 작은 추천 영역 |
Detail |
24:5017 |
기본 266dp x 99dp, pill radius 90dp |
넓은 카드형 라이브 추천 영역 |
Figma Token Requirements
Simpleroot는 세로 배치, gap6dp, width70dp를 기준으로 한다.Simple실제 이미지 영역은58dp x 58dp, 원형 crop, top/start6dp위치를 기준으로 한다.Simple라이브 ring은70dp x 70dp이며 ocean-blue gradient 또는 동일한 기존 drawable을 사용한다.SimpleLIVE badge는50dp x 18dp, black background,#62CFFFborder2dp, radius759dp, icon8dp, text12spregular white를 기준으로 한다.Simple크리에이터 이름은@style/Typography.Body5, white, center 정렬이다.Detailroot는266dp x 99dp,gray_900(#202020) background,#62CFFFborder2dp, radius90dp, overflow clipped 형태를 기준으로 한다.Detail실제 이미지 영역은75dp x 75dp, left10dp, vertical center, 원형 crop을 기준으로 한다.Detail텍스트 column은 left93dp, width149dp, vertical center, 내부 gap4dp를 기준으로 한다.DetailLIVE badge는Tag(size=s,type=live)형태로 black background, radius100dp, height18dp, horizontal padding4dp, icon/text gap4dp를 기준으로 한다.DetailLIVE badge는Simple의 cyan stroke badge와 달리 stroke 없는 capsule background를 사용한다.Detail라이브 시작 시간은@style/Typography.Body6,gray_500(#959595)를 기준으로 한다.Detail라이브 제목은@style/Typography.Heading4, white를 기준으로 한다.Detail크리에이터 이름은@style/Typography.Body6,gray_500(#959595)를 기준으로 한다.
Display Requirements
- 실제 이미지는 Figma placeholder가 아니라
imageUrl데이터로 표시한다. - 이미지 로딩 실패 시 placeholder 정책은 호출 화면의 기존 이미지 로딩 정책을 따른다.
Simple은 크리에이터 이름만 표시한다.Detail은 LIVE badge, 라이브 시작 시간, 라이브 제목, 크리에이터 이름을 표시한다.liveStartTimeText가 비어 있으면00:00을 강제하지 않고 빈 문자열 또는 호출부 정책을 따른다.- 모든 텍스트는 한 줄만 표시한다.
- 모든 텍스트는 영역을 초과하면 끝 말줄임 처리한다.
- LIVE 문구는 고정 문자열
LIVE로 표시한다. - 터치 동작은 컴포넌트 내부에서 목적지를 결정하지 않고 호출부 callback으로 위임한다.
Data Contract Requirements
- 최소 데이터 계약은 다음 정보를 포함해야 한다.
liveId: 라이브 식별자.creatorId: 크리에이터 식별자.imageUrl: 실제로 표시할 프로필 또는 라이브 이미지 URL.title: 라이브 제목.Detailvariant에서 사용한다.creatorName: 크리에이터 이름.liveStartTimeText: 라이브 시작 시간 표시 문자열.Detailvariant에서 사용한다.
- UI는
imageUrl의 의미가 프로필 이미지인지 커버 이미지인지 판단하지 않는다. 호출부가 variant 목적에 맞는 URL을 전달한다.
Edge Cases
imageUrl이 비어 있으면 호출부 이미지 로딩 정책에 따라 placeholder 또는 빈 상태를 표시한다.creatorName이 비어 있으면 해당 TextView는 빈 문자열로 유지하고 layout은 유지한다.title이 비어 있으면Detailtitle TextView는 빈 문자열로 유지하고 layout은 유지한다.- 긴 한글/영문/숫자 혼합 텍스트는 1줄 말줄임으로 처리한다.
liveStartTimeText가 긴 문자열이어도 1줄 말줄임으로 처리한다.
8. UX / UI Expectations
- 전체 컴포넌트는 어두운 배경에서 사용하는 것을 전제로 한다.
- 라이브 상태는
#62CFFF계열 ring/border와 LIVE badge로 식별 가능해야 한다. - 실제 이미지가 원형 영역을 벗어나지 않도록 centerCrop + circle clipping을 적용한다.
- 세로형과 가로형 모두 Figma의 둥근 형태와 clipping을 유지한다.
- 텍스트가 길어도 컴포넌트의 지정 width를 밀어내지 않아야 한다.
- Android 접근성 관점에서 장식용 LIVE dot/ring은
contentDescription=@null로 둔다.
9. Technical Constraints
- 현재 프로젝트는 Android XML Views + Kotlin custom View + ViewBinding/resource 기반이므로 XML layout과 Kotlin custom view 패턴을 우선한다.
- 신규 Kotlin 코드는
app/src/main/java/kr/co/vividnext/sodalive/v2하위 패키지에 작성한다. - 재사용 가능한 위젯은
kr.co.vividnext.sodalive.v2.widget.livethumbnail하위에 둔다. - 기존
AudioContentCardView,CreatorRanking*CardView처럼 custom view는 텍스트/상태를 바인딩하고, 실제 이미지 로딩은imageView()를 통해 호출부가 처리할 수 있게 한다. gray_900,gray_500,white등 기존 color resource를 우선 재사용한다.- Pretendard font는 기존
@font/regular,@font/medium,@font/bold를 사용한다. - 기존 Typography/spacing/radius token과 정확히 대응되는 값은 신규 token을 만들지 않고 재사용한다.
#62CFFF또는 ocean-blue gradient에 해당하는 기존 리소스가 없으면 구현 단계에서 drawable/color resource를 추가하고, drawable에서는 literal 색상보다 color resource를 참조한다.- 기존 레거시 layout(
item_home_live.xml,item_live_now.xml,item_live_now_all.xml)은 참고 대상으로만 사용하고, 이번 widget 계약에서 직접 변경하지 않는다.
10. Metrics
Simplevariant가 Figma24:4999의 주요 크기, ring, LIVE badge, 1줄 이름 표시와 일치한다.Detailvariant가 Figma24:5017의 주요 크기, 배경, border, 이미지, LIVE/time/title/name 배치와 일치한다.- 실제 이미지 URL을 호출부에서
ImageView에 로드할 수 있다. - 컴포넌트 내부에는 Coil/Glide 등 이미지 로딩 라이브러리 import나
.load()호출이 없다. - 모든 텍스트 TextView에
maxLines=1과ellipsize=end가 적용된다. - 원형 이미지 clipping과 Figma 주요 spacing/size/badge 형태는 XML/코드 속성 확인 또는 screenshot/manual QA로 확인한다.
- 관련 local unit test, Android resource merge, build가 성공한다.
11. Open Questions
Simplevariant의 이미지 URL은 기본적으로 크리에이터 프로필 이미지를 전달하는 것으로 가정한다.Detailvariant의 이미지 URL은 현재 Figma가 프로필형 원형 이미지를 사용하므로 프로필 이미지를 전달하는 것으로 가정한다. 호출 화면에서 라이브 커버를 써야 한다면 같은imageUrl계약에 다른 URL을 전달한다.liveStartTimeText포맷은 이 문서에서 계산하지 않고 호출부가 완성된 문자열로 전달한다.- Figma
get_design_context와 screenshot 확인 결과, 빈 이미지 영역은 실제 이미지 바인딩 영역으로 문서화했다.