Skip to content

Commit d931589

Browse files
authored
Merge pull request #322 from prgrms-web-devcourse-final-project/fix/temp
[fix] youtube 임시처리
2 parents 391eb6a + b5f1c94 commit d931589

File tree

1 file changed

+138
-50
lines changed

1 file changed

+138
-50
lines changed
Lines changed: 138 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,162 @@
1+
// import React, { useEffect, useRef } from 'react';
2+
// // import YouTube from 'react-youtube';
3+
// import { useYouTubeStore } from '@/store/youtubeStore';
4+
// import { createPortal } from 'react-dom';
5+
// // import { twMerge } from 'tailwind-merge';
6+
7+
// // YouTube Player Props 정의
8+
// //1: MusicCard 2: chat 3: post
9+
// interface YouTubeAudioPlayerProps {
10+
// playerId: '1' | '2' | '3';
11+
// }
12+
13+
// const YouTubeAudioPlayer: React.FC<YouTubeAudioPlayerProps> = ({ playerId }) => {
14+
// const { isApiReady, players, setIsPlaying } = useYouTubeStore();
15+
16+
// const playerRef = useRef<YT.Player | null>(null);
17+
// const videoId = players[playerId]?.videoId || null;
18+
// const isPlaying = players[playerId]?.isPlaying || false;
19+
20+
// // 플레이어 생성
21+
// const createPlayer = () => {
22+
// if (!isApiReady || !videoId) {
23+
// if (playerRef.current && playerRef.current.seekTo) {
24+
// playerRef.current.seekTo(0, false);
25+
// playerRef.current.pauseVideo();
26+
// }
27+
// return;
28+
// } // API 준비되지 않았거나 videoId가 없으면
29+
30+
// if (!playerRef.current) {
31+
// playerRef.current = new window.YT.Player(`player-${playerId}`, {
32+
// height: '1px',
33+
// width: '1px',
34+
// videoId: videoId,
35+
// playerVars: {
36+
// autoplay: 0,
37+
// controls: 0,
38+
// playsinline: 1,
39+
// origin: window.location.origin, // 현재 페이지의 origin을 전달
40+
// },
41+
// });
42+
// } else {
43+
// playerRef.current.loadVideoById(videoId); // 이미 플레이어가 있으면 비디오를 새로 로드
44+
// playerRef.current.pauseVideo();
45+
// setIsPlaying(playerId, false);
46+
// }
47+
// };
48+
49+
// // isPlaying 변경 시 실행
50+
// useEffect(() => {
51+
// if (!playerRef.current) return; // 플레이어가 초기화되지 않았으면 실행 안 함
52+
53+
// if (isPlaying) {
54+
// playerRef.current.playVideo?.();
55+
// } else {
56+
// playerRef.current.pauseVideo?.();
57+
// }
58+
// }, [isPlaying]);
59+
60+
// useEffect(() => {
61+
// createPlayer();
62+
// }, [videoId, isApiReady]);
63+
64+
// useEffect(() => {
65+
// const playerElement = document.getElementById(`player-${playerId}`);
66+
// if (playerElement) {
67+
// playerElement.style.position = 'absolute';
68+
// playerElement.style.top = '0px';
69+
// }
70+
// }, []);
71+
// return createPortal(<div id={`player-${playerId}`}></div>, document.body);
72+
// };
73+
74+
// export default YouTubeAudioPlayer;
75+
176
import React, { useEffect, useRef } from 'react';
2-
// import YouTube from 'react-youtube';
3-
import { useYouTubeStore } from '@/store/youtubeStore';
477
import { createPortal } from 'react-dom';
5-
// import { twMerge } from 'tailwind-merge';
78+
import { useYouTubeStore } from '@/store/youtubeStore';
679

780
// YouTube Player Props 정의
8-
//1: MusicCard 2: chat 3: post
81+
// 1: MusicCard, 2: chat, 3: post
982
interface YouTubeAudioPlayerProps {
1083
playerId: '1' | '2' | '3';
1184
}
1285

1386
const YouTubeAudioPlayer: React.FC<YouTubeAudioPlayerProps> = ({ playerId }) => {
87+
// 1. 스토어에서 필요한 상태와 함수를 가져옵니다.
1488
const { isApiReady, players, setIsPlaying } = useYouTubeStore();
15-
1689
const playerRef = useRef<YT.Player | null>(null);
17-
const videoId = players[playerId]?.videoId || null;
18-
const isPlaying = players[playerId]?.isPlaying || false;
1990

20-
// 플레이어 생성
21-
const createPlayer = () => {
91+
// players 객체에서 현재 playerId에 맞는 videoId와 isPlaying 상태를 안전하게 추출합니다.
92+
const { videoId, isPlaying } = players[playerId] || { videoId: null, isPlaying: false };
93+
94+
// 2. 플레이어 생성, 파괴를 관리하는 메인 useEffect
95+
useEffect(() => {
96+
// API가 준비되지 않았거나 재생할 videoId가 없으면 플레이어를 생성하지 않습니다.
2297
if (!isApiReady || !videoId) {
23-
if (playerRef.current && playerRef.current.seekTo) {
24-
playerRef.current.seekTo(0, false);
25-
playerRef.current.pauseVideo();
26-
}
2798
return;
28-
} // API 준비되지 않았거나 videoId가 없으면
29-
30-
if (!playerRef.current) {
31-
playerRef.current = new window.YT.Player(`player-${playerId}`, {
32-
height: '1px',
33-
width: '1px',
34-
videoId: videoId,
35-
playerVars: {
36-
autoplay: 0,
37-
controls: 0,
38-
playsinline: 1,
39-
origin: window.location.origin, // 현재 페이지의 origin을 전달
40-
},
41-
});
42-
} else {
43-
playerRef.current.loadVideoById(videoId); // 이미 플레이어가 있으면 비디오를 새로 로드
44-
playerRef.current.pauseVideo();
45-
setIsPlaying(playerId, false);
4699
}
47-
};
48100

49-
// isPlaying 변경 시 실행
50-
useEffect(() => {
51-
if (!playerRef.current) return; // 플레이어가 초기화되지 않았으면 실행 안 함
101+
// 새 플레이어 인스턴스를 생성합니다.
102+
playerRef.current = new window.YT.Player(`player-${playerId}`, {
103+
height: '0', // 플레이어는 보이지 않도록 처리합니다.
104+
width: '0',
105+
videoId: videoId,
106+
playerVars: {
107+
playsinline: 1,
108+
origin: window.location.origin,
109+
},
110+
events: {
111+
// 플레이어가 준비되면 호출됩니다.
112+
onReady: (event: any) => {
113+
// isPlaying 상태가 true이면 비디오를 재생합니다.
114+
if (isPlaying) {
115+
event.target.playVideo();
116+
}
117+
},
118+
// 플레이어의 상태가 변경될 때마다 호출됩니다. (재생, 일시정지 등)
119+
onStateChange: (event: any) => {
120+
// 실제 플레이어 상태를 스토어(전역 상태)에 반영합니다.
121+
if (event.data === window.YT.PlayerState.PLAYING) {
122+
setIsPlaying(playerId, true);
123+
} else if (event.data === window.YT.PlayerState.PAUSED) {
124+
setIsPlaying(playerId, false);
125+
}
126+
},
127+
},
128+
});
52129

53-
if (isPlaying) {
54-
playerRef.current.playVideo?.();
55-
} else {
56-
playerRef.current.pauseVideo?.();
57-
}
58-
}, [isPlaying]);
130+
// 3. Cleanup 함수 (매우 중요)
131+
// useEffect가 다시 실행되기 전(즉, videoId가 바뀔 때) 또는 컴포넌트가 사라질 때 호출됩니다.
132+
return () => {
133+
if (playerRef.current && typeof playerRef.current.destroy === 'function') {
134+
playerRef.current.destroy(); // 기존 플레이어를 완전히 제거하여 메모리 누수를 방지합니다.
135+
playerRef.current = null;
136+
}
137+
};
138+
// isApiReady, videoId가 변경될 때마다 이 로직을 다시 실행합니다.
139+
}, [isApiReady, videoId, playerId, isPlaying, setIsPlaying]);
59140

141+
// 4. 스토어의 isPlaying 상태가 바뀔 때 플레이어를 제어하는 useEffect
60142
useEffect(() => {
61-
createPlayer();
62-
}, [videoId, isApiReady]);
143+
// 플레이어 인스턴스가 없거나, 아직 제어할 준비가 안 됐으면 아무것도 하지 않습니다.
144+
if (!playerRef.current || typeof playerRef.current.getPlayerState !== 'function') {
145+
return;
146+
}
63147

64-
useEffect(() => {
65-
const playerElement = document.getElementById(`player-${playerId}`);
66-
if (playerElement) {
67-
playerElement.style.position = 'absolute';
68-
playerElement.style.top = '0px';
148+
const playerState = playerRef.current.getPlayerState();
149+
150+
// 스토어 상태와 실제 플레이어 상태를 동기화합니다.
151+
if (isPlaying && playerState !== window.YT.PlayerState.PLAYING) {
152+
playerRef.current.playVideo();
153+
} else if (!isPlaying && playerState !== window.YT.PlayerState.PAUSED) {
154+
playerRef.current.pauseVideo();
69155
}
70-
}, []);
71-
return createPortal(<div id={`player-${playerId}`}></div>, document.body);
156+
}, [isPlaying]); // isPlaying 상태가 변경될 때만 실행합니다.
157+
158+
// 5. 플레이어를 body 최상단에 렌더링합니다.
159+
return createPortal(<div id={`player-${playerId}`} />, document.body);
72160
};
73161

74162
export default YouTubeAudioPlayer;

0 commit comments

Comments
 (0)