안녕하세요

youtube playlist로 노래 플레이어 만들기 본문

유튜브컨텐츠탐색-StelLife

youtube playlist로 노래 플레이어 만들기

sakuraop 2023. 3. 13. 06:22

[렌더링할 데이터 불러오기]

1. App을 실행하면 노래 정보를 불러와 reducer에 저장합니다.


function App() {
  const dispatch = useDispatch();

  useEffect(() => {
    (async () => {
      const songsResult = await axios.get("/api/songs");
      dispatch(setSongs(songsResult.data));
    })();
  }, [dispatch]);
 

2. 노래 정보를 useSelector로 불러오고 이를 저장할 state를 만듭니다.


 
const singerData = useSelector((state) => state.songs);
 const [playlist, setPlaylist] = useState([]);
 

3. 노래를 담은 배열을 생성합니다.


 
const allSongs = singerData
    .map((singer) => {
      return singer.songList;
    })
    .flat();
 

=> 저는 복수의 플레이리스트로부터 받아왔기 때문에 .flat()함수로 노래 배열을 1차원 배열로 만들었습니다.

4. singerData를 useSelector로 불러오면 노래배열을 playlist state에 저장합니다.


 
// useSelector로 데이터를 불러오면 모든 노래 playlist에 저장하기
  useEffect(() => {
    setPlaylist(allSongs);
  }, [singerData]);
 

=> singerData는 1회만 불러오기 때문에 component가 동작을 하는 최초 1회만 실행됩니다.

 

이것으로 노래 데이터를 렌더링하기 위한 준비는 끝입니다.


[React-Player로 기능 구현하기]

5. 렌더링할 플레이리스트와 현재 재생중인 노래를 담을 state를 만듭니다.


 
const [showList, setShowList] = useState([]);
  const [currentSong, setCurrentSong] = useState({});
 

6. playlist 배열 안에 요소가 존재하면 재생할 노래와, 렌더링용 플레이리스트에 저장합니다.


  // playlist가 저장되면 최초에 보여줄 노래와 모든 노래 리스트 출력
  useEffect(() => {
    if (playlist.length) {
      setCurrentSong(playlist[0]);
      setShowList(playlist);
    }
  }, [playlist]);
 

=> playlist 또한 데이터를 바꾸지 않고 showList를 통해서 렌더링 할 것이기 때문에 1회만 실행됩니다.

7. ReactPlayer를 설치합니다. 편하게 youtube 동영상을 다룰 수 있습니다.

$ npm i react-player

8. 현재 재생중인 영상: 재생할 노래 state가 있다면 보여주도록 합니다.


     
<div className="current-song">
        {Object.keys(currentSong).length ? (
          <>
            <h3>{currentSong.snippet.title}</h3>
            <ReactPlayer
              className="videoPlayer"
              url={`https://www.youtube.com/embed/${currentSong.snippet.resourceId.videoId}`}
              muted={false}
              playing={true}
              width="100%"
              height="100%"
              onEnded={handleEnded}
            />
          </>
        ) : (
          <h3>노래를 찾는 중입니다.</h3>
        )}
      </div>
 

=> onEnded 프로퍼티는 현재 재생중인 영상이 끝나면 수행할 동작을 지정할 수 있습니다. 

9. 연속재생, 반복재생: onEnded 프로퍼티에 handleEnded 함수를 전달합니다.


 
const handleEnded = () => {
    const currentIndex = showList.indexOf(currentSong);
    const nextIndex = (currentIndex + 1) % showList.length;
    setCurrentSong(showList[nextIndex]);
  };
 

=> handleEnded 함수는 재생할 영상의 정보를 담은 배열에 indexOf 메서드를 활용하여 다음 인덱스의 영상을 재생합니다.

show.List.length 로 나눈 나머지를 통해 마지막 곡까지 재생이 끝났다면 첫번째 곡으로 되돌아가 반복재생을 할 수 있습니다.

10. 재생목록 셔플


 
const handleClickShuffle = () => {
    const shuffledList = [...showList].sort(() => Math.random() - 0.5);
    setShowList(shuffledList);
  };

  return (
    <div className="player">
      <div onClick={handleClickShuffle}>[셔플하기]</div>
 // ......

=> sort 메서드와 random 함수를 이용하여 순서를 무작위로 섞습니다.


복사된 배열을 sort() 메소드를 사용해 정렬합니다. 

sort() 메소드에 인자로 함수를 전달하면 배열의 요소를 정렬하는데 사용할 기준을 정할 수 있습니다.


Math.random() 함수를 사용하여 무작위 숫자를 생성한 후 0.5를 뺀 값을 반환합니다.

이렇게 반환된 숫자가 음수이면 요소의 순서를 바꿉니다. 따라서 배열이 무작위로 섞이게 됩니다.

정렬된 배열을 shuffledList 변수에 할당합니다. 

이제 shuffledList 배열은 showList 배열의 복사본이며, 요소들이 무작위로 섞이게 됩니다.


11. 플레이리스트의 각 항목을 클릭하여 현재 재생중인 영상을 바꿉니다.

 
      <ul className="playlist">
        {showList.length ? (
          showList.map((song) => {
            return (
              <li key={song.etag} onClick={() => setCurrentSong(song)}>
                {song.snippet.title}
              </li>
            );
          })
        ) : (
          <div>로딩중</div>
        )}
      </ul>