diff --git a/com.twin.app.shoptime/.docs/player-panel/TabContainerV2-Divider-Problem-Analysis.md b/com.twin.app.shoptime/.docs/player-panel/TabContainerV2-Divider-Problem-Analysis.md new file mode 100644 index 00000000..85ce3586 --- /dev/null +++ b/com.twin.app.shoptime/.docs/player-panel/TabContainerV2-Divider-Problem-Analysis.md @@ -0,0 +1,175 @@ +# TabContainerV2 구분선 문제 분석 및 해결 방안 + +## 문제 개요 + +PlayerPanel의 TabContainerV2에서 ShopNowContents와 YouMayLikeContents 사이에 세로 구분선을 표시해야 하지만, 현재 TVirtualGridList 구조의 한계로 인해 올바르게 동작하지 않음 + +## 현재 구조 분석 + +### 1. TabContainerV2 구조 +- 위치: `src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx` +- 3개의 tabIndex로 구성 (0: ShopNow, 1: LiveChannel, 2: ShopNowButton) +- version=2에서 ShopNow와 YouMayLike 통합 표시 + +### 2. ShopNowContents 구조 +- 위치: `src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx` +- ShopNow 아이템 < 3개일 때 YouMayLike 아이템을 통합하여 표시 +- combinedItems 배열로 ShopNow + YouMayLike 통합 관리 +- TVirtualGridList로 가로 방향 렌더링 (itemWidth: 310px, itemHeight: 445px, spacing: 30px) + +### 3. 현재 구분선 구현 로직 +```javascript +// YouMayLike 시작 지점 여부 (구분선 표시) +const isYouMayLikeStart = shopNowInfo && index === shopNowInfo.length; + +return ( + <> + {isYouMayLikeStart &&
} + + +); +``` + +## 문제 상세 + +### 1. TVirtualGridList 구조적 한계 +- TVirtualGridList는 각 아이템이 고정된 크기를 가짐 (itemWidth: 310px) +- renderItem 함수 내에서 추가적인 요소(divider)를 렌더링하면 레이아웃 충돌 발생 +- divider가 TItemCard와 같은 공간을 차지하려고 하여 빈 TItemCard가 표시되는 현상 + +### 2. 포커스 이동 문제 +- divider가 포커스를 받거나 포커스 이동을 방해하는 현상 +- 실제 상품과 포커스 위치가 불일치하는 문제 + +### 3. 간격 문제 +- 구분선으로 인해 상품들 간의 간격이 넓어짐 +- 사용자 경험 저하 + +## 해결 방안 분석 + +### 방안 1: TItemCard Wrapper 방식 ❌ +**구현:** +```javascript +
+ +
+``` + +**CSS:** +```css +.itemWrapper::before { + content: ''; + width: 2px; + opacity: 0; +} + +.itemWrapper.showDivider::before { + opacity: 1; + background: rgba(234, 234, 234, 0.3); +} +``` + +**문제점:** +- itemWidth를 310px → 327px로 증가시켜야 함 +- 상품 간 간격이 넓어짐 +- 포커스와 상품 위치 불일치 +- 전체 레이아웃 변경 필요 + +### 방안 2: Divider 아이템 추가 방식 ❌ +**구현:** +```javascript +// combinedItems에 divider 추가 +items.push({ _type: 'divider' }); + +// renderItem에서 처리 +if (item._type === 'divider') { + return
; +} +``` + +**문제점:** +- divider가 TVirtualGridList 아이템으로 인식되어 TItemCard만큼 공간 차지 +- ShopNow와 YouMayLike 사이 포커스 이동이 막힘 +- 빈 공간이 생기는 문제 여전히 존재 + +### 방안 3: 두 개의 TVirtualGridList 분리 방식 ✅ +**구현:** +```javascript +
+ + [ShopNow1][ShopNow2] + +
+ +
+
+
+ +
+ + [YouMayLike1][YouMayLike2] + +
+``` + +**장점:** +- 구분선을 완벽하게 제어 가능 +- 각 TVirtualGridList가 독립적으로 동작 +- 빈 TItemCard 문제 해결 +- 레이아웃 깨짐 없음 +- 기존 기능 모두 유지 가능 + +**고려사항:** +- 포커스 이동 핸들러 구현 필요 + - ShopNow 마지막 아이템 → 구분선 → YouMayLike 첫 아이템 + - YouMayLike 첫 아이템 → 구분선 → ShopNow 마지막 아이템 +- Spotlight 컨테이너 간 이동 수동 처리 필요 + +**포커스 이동 구현 예시:** +```javascript +// ShopNow 마지막 아이템 +onSpotlightRight={() => Spotlight.focus('divider-element')} + +// 구분선 SpottableDiv + Spotlight.focus('shop-now-last')} + onSpotlightRight={() => Spotlight.focus('you-may-like-first')} +> +
+ + +// YouMayLike 첫 아이템 +onSpotlightLeft={() => Spotlight.focus('divider-element')} +``` + +## 추천 해결책 + +**방안 3: 두 개의 TVirtualGridList 분리 방식**을 추천합니다. + +### 이유 +1. **근본적인 해결**: TVirtualGridList 구조적 한계를 완전히 회피 +2. **레이아웃 안정성**: 각 컴포넌트가 독립적으로 동작하여 예측 가능한 결과 +3. **유지보수성**: 기존 로직을 최소한만 수정하며 명확한 분리 +4. **사용자 경험**: 포커스 이동이 더 명확하고 직관적 + +### 구현 우선순위 +1. ShopNow TVirtualGridList 분리 +2. YouMayLike TVirtualGridList 분리 +3. 구분선 SpottableDiv 추가 +4. 포커스 이동 핸들러 구현 +5. 테스트 및 디버깅 + +### 영향 범위 +- **수정 필요 파일**: `ShopNowContents.jsx` 1개 +- **기존 기능**: 모두 유지 가능 +- **성능 영향**: 미미 (VirtualGridList 인스턴스 1개 추가) +- **사용자 영향**: 없음 (개선된 경험 제공) + +## 관련 파일 + +- `src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx` +- `src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx` +- `src/views/PlayerPanel/PlayerTabContents/TabContents/YouMayLikeContents.jsx` +- `src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.v2.module.less` +- `src/components/TVirtualGridList/TVirtualGridList.jsx` \ No newline at end of file diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx index 57bd741a..95521275 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx @@ -1,5 +1,6 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import classNames from 'classnames'; import { useDispatch, useSelector } from 'react-redux'; import { Job } from '@enact/core/util'; @@ -160,7 +161,7 @@ export default function ShopNowContents({ return ( <> - {isYouMayLikeStart &&
} + {/* {isYouMayLikeStart &&
} */}