🕐 커밋 시간: 2025. 11. 12. 20:57:22 📊 변경 통계: • 총 파일: 2개 📁 추가된 파일: + com.twin.app.shoptime/.docs/ProductVideoV2-YouTube-Video-Type-Issue-Analysis.md + com.twin.app.shoptime/.docs/ProductVideoV2-YouTube-iframe-Event-Problem-Analysis.md 🔧 함수 변경 내용: 📄 com.twin.app.shoptime/.docs/ProductVideoV2-YouTube-Video-Type-Issue-Analysis.md (md파일): ✅ Added: useMemo(), toLowerCase() 📄 com.twin.app.shoptime/.docs/ProductVideoV2-YouTube-iframe-Event-Problem-Analysis.md (md파일): ✅ Added: postMessage(), setTimeout(), useEffect(), setInterval() 🔧 주요 변경 내용: • 타입 시스템 안정성 강화 • 개발 문서 및 가이드 개선
232 lines
6.8 KiB
Markdown
232 lines
6.8 KiB
Markdown
# ProductVideoV2 YouTube iframe 이벤트 문제 분석 및 해결 방안
|
|
|
|
## 문제 현상
|
|
|
|
YouTube 비디오가 전체화면 모드로 전환되면 **iframe 내부의 YouTube 컨트롤 오버레이**가 나타나서 키보드/마우스 이벤트를 가로채서 일반 모드로 돌아올 수 없음
|
|
|
|
## 🔥 근본 원인 분석
|
|
|
|
### 1. YouTube iframe의 독립적 이벤트 처리
|
|
|
|
#### 문제점
|
|
- YouTube iframe은 **독립적인 문서 컨텍스트**를 가짐
|
|
- iframe 내부의 YouTube 플레이어 컨트롤이 **자체적인 이벤트 핸들링**을 함
|
|
- 부모 문서의 `window.addEventListener('keydown', ...)`가 **iframe 내부까지 전파되지 않음**
|
|
|
|
#### 증거
|
|
- `window.addEventListener('keydown', handleFullscreenKeyDown, true)` (capture phase)로 설정했지만 **iframe 내부까지는 도달하지 못함**
|
|
- YouTube iframe의 **native event handling**이 더 높은 우선순위를 가짐
|
|
|
|
### 2. Spotlight 포커스 시스템의 한계
|
|
|
|
#### 문제점
|
|
- 현재 Spotlight 시스템은 React 컴포넌트 DOM 요소에만 동작
|
|
- YouTube iframe 내부의 요소는 Spotlight가 **제어할 수 없는 영역**
|
|
- `spotlightRestrict="self-only"`가 iframe 내부까지 적용되지 않음
|
|
|
|
### 3. TReactPlayer의 내부 동작 방식
|
|
|
|
#### 문제점
|
|
- TReactPlayer는 react-player 라이브러리를 사용
|
|
- YouTube iframe을 생성할 때 **내부적으로 설정을 덮어쓸 수 있음**
|
|
- YOUTUBECONFIG가 react-player에 **제대로 전달되지 않을 가능성**
|
|
|
|
### 4. webOS 환경 특성
|
|
|
|
#### 문제점
|
|
- webOS TV 환경에서는 **키코드가 다르게 동작**
|
|
- 리모컨 버튼의 키코드: Back(461), Return(10009), ArrowUp/Down(37/40) 등
|
|
- 이벤트 처리 순서가 웹 브라우저와 다를 수 있음
|
|
|
|
## 🎯 구체적인 문제 시나리오
|
|
|
|
### 시나리오 1: ESC 키 문제
|
|
1. 사용자가 ESC 키 누름
|
|
2. YouTube iframe이 이벤트를 먼저 처리
|
|
3. 부모 문서의 `handleFullscreenKeyDown`가 호출되지 않음
|
|
4. **결과:** 일반 모드로 돌아갈 수 없음
|
|
|
|
### 시나리오 2: Back 버튼(리모컨) 문제
|
|
1. 리모컨 Back 버튼 누름 (keyCode: 461)
|
|
2. YouTube iframe이 이벤트를 가로챔
|
|
3. **결과:** 포커스를 벗어나지 못함
|
|
|
|
### 시나리오 3: Spotlight 포커스 문제
|
|
1. Spotlight가 전체화면 컨테이너에 포커스 설정
|
|
2. YouTube iframe이 포커스를 훔쳐감
|
|
3. **결과:** Spotlight 제어 불가
|
|
|
|
### 시나리오 4: 클릭/터치 이벤트 문제
|
|
1. 전체화면에서 사용자가 화면 클릭
|
|
2. YouTube iframe이 클릭 이벤트를 처리
|
|
3. **결과:** 전체화면 해제 불가
|
|
|
|
## 🛠️ 해결 방안 분석
|
|
|
|
### 방안 1: YouTube 컨트롤 완전 제거 (현재 시도 중)
|
|
|
|
#### 구현 내용
|
|
```javascript
|
|
const YOUTUBECONFIG = {
|
|
playerVars: {
|
|
controls: 0, // ✅ 플레이어 컨트롤 완전 숨김
|
|
disablekb: 1, // ✅ 키보드 입력 완전 비활성화 (핵심)
|
|
fs: 0, // ✅ 전체화면 버튼 비활성화
|
|
rel: 0, // ✅ 관련 동영상 비활성화
|
|
// ... 기타 설정
|
|
},
|
|
};
|
|
```
|
|
|
|
#### 예상 효과
|
|
- YouTube iframe이 내부 이벤트를 처리하지 않음
|
|
- 부모 문서가 완전히 이벤트 제어
|
|
- Spotlight 포커스 시스템 정상 동작
|
|
|
|
#### 현재 문제점
|
|
- YOUTUBECONFIG가 react-player에 제대로 전달되지 않을 수 있음
|
|
- TReactPlayer가 내부적으로 설정을 덮어쓸 가능성
|
|
|
|
### 방안 2: YouTube PostMessage API 활용
|
|
|
|
#### 구현 방식
|
|
```javascript
|
|
const sendYouTubeCommand = (command, args = []) => {
|
|
const iframe = document.querySelector('iframe[src*="youtube"]');
|
|
if (iframe) {
|
|
iframe.contentWindow.postMessage({
|
|
event: 'command',
|
|
func: command,
|
|
args: args
|
|
}, '*');
|
|
}
|
|
};
|
|
|
|
// ESC 키 처리
|
|
sendYouTubeCommand('pauseVideo');
|
|
setTimeout(() => setIsFullscreen(false), 100);
|
|
```
|
|
|
|
#### 장점
|
|
- YouTube iframe과 직접 통신 가능
|
|
- 더 정교한 제어 가능
|
|
|
|
#### 단점
|
|
- 복잡성 증가
|
|
- iframe 로드 타이밍 이슈
|
|
|
|
### 방안 3: 강제 포커스 회수
|
|
|
|
#### 구현 방식
|
|
```javascript
|
|
useEffect(() => {
|
|
if (isFullscreen && isYoutube) {
|
|
const interval = setInterval(() => {
|
|
Spotlight.focus('product-video-v2-fullscreen-portal');
|
|
}, 1000);
|
|
return () => clearInterval(interval);
|
|
}
|
|
}, [isFullscreen, isYoutube]);
|
|
```
|
|
|
|
#### 장점
|
|
- 포커스 유지 보장
|
|
- 간단한 구현
|
|
|
|
#### 단점
|
|
- 리소스 낭비
|
|
- 근본적인 해결책 아님
|
|
|
|
### 방안 4: TReactPlayer 대신 직접 제어
|
|
|
|
#### 구현 방식
|
|
- react-player 라이브러리 대신 직접 YouTube iframe 제어
|
|
- iframe 생성과 제어를 완전히 직접 관리
|
|
|
|
#### 장점
|
|
- 완벽한 제어 가능
|
|
- 의도치 않은 동작 방지
|
|
|
|
#### 단점
|
|
- 복잡성 급증
|
|
- 유지보수 어려움
|
|
|
|
## 🔍 진단을 위한 확인 사항
|
|
|
|
### 1. 로그 확인
|
|
```javascript
|
|
// reactPlayerSubtitleConfig 설정 확인
|
|
console.log('🎥 [reactPlayerSubtitleConfig] 설정 생성', {
|
|
isYoutube: isYoutube,
|
|
hasSubtitle: !!subtitleUrl,
|
|
youtubeConfig: YOUTUBECONFIG,
|
|
});
|
|
```
|
|
|
|
### 2. DOM 확인
|
|
- YouTube iframe이 실제로 생성되는지 확인
|
|
- TReactPlayer가 iframe을 제대로 감싸고 있는지 확인
|
|
- iframe에 적용된 설정 확인
|
|
|
|
### 3. 이벤트 전파 확인
|
|
```javascript
|
|
// 전체화면 키보드 이벤트 로깅
|
|
console.log('🖥️ [Fullscreen Container] 키보드 이벤트 감지', {
|
|
key: e.key,
|
|
keyCode: e.keyCode,
|
|
isYoutube: isYoutube,
|
|
});
|
|
```
|
|
|
|
## 🎯 추천 해결 순서
|
|
|
|
### 1단계: 현재 방안 1 완료
|
|
- YOUTUBECONFIG가 react-player에 제대로 전달되는지 확인
|
|
- YouTube iframe이 실제로 컨트롤이 비활성화되는지 확인
|
|
|
|
### 2단계: 강화된 이벤트 핸들링
|
|
- 리모컨 버튼 키코드 확장 (461, 10009 등)
|
|
- Capture phase 이벤트 처리 강화
|
|
|
|
### 3단계: 방안 2 전환 (필요 시)
|
|
- PostMessage API로 직접 YouTube 제어
|
|
|
|
### 4단계: 방안 3 보조
|
|
- 주기적 포커스 회수로 안정성 확보
|
|
|
|
## 🔄 롤백 계획
|
|
|
|
### 롤백 1: YOUTUBECONFIG 복원
|
|
```javascript
|
|
const YOUTUBECONFIG = {
|
|
playerVars: {
|
|
controls: 0,
|
|
autoplay: 1,
|
|
disablekb: 0, // 키보드 활성화로 복원
|
|
fs: 1, // 전체화면 버튼 활성화로 복원
|
|
// ... 기존 설정
|
|
},
|
|
};
|
|
```
|
|
|
|
### 롤백 2: 이벤트 핸들러 복원
|
|
```javascript
|
|
// Back 버튼 처리 로직 제거
|
|
// return toggleOverlayVisibility();
|
|
```
|
|
|
|
### 롤백 3: reactPlayerSubtitleConfig 복원
|
|
```javascript
|
|
// isYoutube 의존성 제거
|
|
}, [productInfo?.prdtMediaSubtitlUrl]);
|
|
```
|
|
|
|
## 결론
|
|
|
|
가장 현실적인 해결책은 **방안 1 (YouTube 컨트롤 완전 제거)**과 **방안 2 (PostMessage API)**의 조합입니다:
|
|
|
|
1. 일단 YOUTUBECONFIG를 통해 컨트롤 완전 비활성화
|
|
2. 필요시 PostMessage API로 직접 YouTube 제어
|
|
3. Spotlight 포커스 시스템 보강으로 안정성 확보
|
|
|
|
이렇게 하면 YouTube iframe이 이벤트를 가로채지 못하고, 기존의 키보드 핸들링 로직이 정상 동작할 것입니다. |