Spotify API로 내 웹사이트 안에 뮤직 플레이어 만들기 - 1편

이은지·2022년 7월 6일
20
post-thumbnail

완성물부터

이렇게 생긴 플레이어를 만들었다!
노래의 플레이 버튼을 누르면 전곡 재생도 가능하다 👍🏻
노래 재생에 처음 성공했을 때 느꼈던 감동은 아직도 잊을 수 없다 🤦🏻‍♀️

관련 내용이 한글로 정리된 게 없어서 Spotify SDK 공식 문서 보고 한땀한땀 만들었다... 우당탕탕 고뇌했던 과정을 기록하기 위해 글을 쓴다.

참고로 백엔드 분이 따로 계셨어서, 로그인은 백엔드에서 구현을 했습니다.
앱 내에 스포티파이로 로그인 기능이 구현되어 있어야 해요! 스포티파이에서 지급하는 access token이 필요합니다.
혹은 아래 링크에서 임시 토큰을 지급 받으실 수 있습니다. 유효 기간이 1시간이라 1시간 마다 버튼을 클릭해 새로운 토큰을 복사해야 합니다.
https://developer.spotify.com/documentation/web-playback-sdk/quick-start/

사용 스택

  • Next-js
  • React
  • React-query

전체 프로젝트 구조

Spotify API를 활용한 노래 추천 서비스 를 구현하는 게 우리 팀의 목표였다.

프론트가 구현해야 하는 기능은 크게 두 가지였다.

  • 유저의 취향을 파악할 수 있는 설문
    유저가 처음 로그인할 때 진행. 응답 받아 서버로 전송.
  • 백엔드로부터 추천 결과를 받아 화면에 보여주기
    보여줄 뿐만 아니라 플레이도 가능하게.

두번째 기능을 내가 맡았고, 이를 위해 spotify sdk 사용 방법을 공부했다.

https://developer.spotify.com/documentation/ 에 들어가보면 여러 종류의 APIs와 SDKs가 있는데, 이 중 WEB API와 WEB PLAYBACK SDK를 사용해야 한다.

플레이어 생성은 WEB Playback SDK로 해야 하고, 플레이어 조작(원하는 노래 재생하기, pause, resume)은 WEB API를 사용해야 했다.

Spotify for Developers 사이트에서는 WEB PLAYBACK SDK를 다음과 같이 소개하고 있다.

The Spotify Web Playback SDK is a client-side only JavaScript library that allows you to create a new player in Spotify Connect, stream and control audio tracks from Spotify inside your website application, and get metadata about the current playback.

내 웹사이트 내에서 Spotify를 사용한 뮤직 플레이어를 만들 수 있는 자바스크립트 라이브러리!

컴포넌트 구조

아래와 같이 구성했다.

  • WebPlayback: 컨테이너 컴포넌트로, 이 컴포넌트 내에서 플레이어 생성 및 플레이어 상태 관리가 이뤄진다.
  • Playlist: props로 받은 노래 정보를 SingleSong 컴포넌트로 변환한다.
  • SingleSong: props로 받은 개별 노래 정보를 화면에 나타낸다. 유저가 재생 버튼을 클릭하면 onPlay 함수를 호출한다.
  • Player: props로 현재 플레이어의 상태 정보를 받아 화면에 나타낸다. 유저가 재생 버튼을 클릭하면 onPlay/onPause 함수를 호출한다.

구현(구현 코드가 궁금하시면 바로 여기🙌🏻)

script 추가하기

Web Playback SDK를 내 앱에 설치하기 위해 script 코드를 추가해야 했다.
NextJS를 사용했기 때문에, React처럼 html의 head,body에 직접 접근할 수 없었다.
대신 NextJS에서 제공하는 Script 컴포넌트를 사용해 스크립트 코드를 추가할 수 있었다.

_app.tsx에 코드를 추가해 주었다.

import type { AppProps } from "next/app";
import Script from "next/script";

function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
  return (
    <>
        <Script src="https://sdk.scdn.co/spotify-player.js" />
        <Component {...pageProps} />
    </>
  );
}

export default MyApp;

플레이어 생성하기

https://developer.spotify.com/documentation/web-playback-sdk/quick-start/
가이드에 나와있는 플레이어 initialization 코드는 아래와 같다.

<!DOCTYPE html>
<html>
<head>
    <title>Spotify Web Playback SDK Quick Start</title>
</head>
<body>
    <h1>Spotify Web Playback SDK Quick Start</h1>
    <button id="togglePlay">Toggle Play</button>

    <script src="https://sdk.scdn.co/spotify-player.js"></script>
    <script>
        window.onSpotifyWebPlaybackSDKReady = () => {
            const token = '[My access token]';
            const player = new Spotify.Player({
                name: 'Web Playback SDK Quick Start Player',
                getOAuthToken: cb => { cb(token); },
                volume: 0.5
            });

            // Ready
            player.addListener('ready', ({ device_id }) => {
                console.log('Ready with Device ID', device_id);
            });

            // Not Ready
            player.addListener('not_ready', ({ device_id }) => {
                console.log('Device ID has gone offline', device_id);
            });

            player.addListener('initialization_error', ({ message }) => {
                console.error(message);
            });

            player.addListener('authentication_error', ({ message }) => {
                console.error(message);
            });

            player.addListener('account_error', ({ message }) => {
                console.error(message);
            });

            document.getElementById('togglePlay').onclick = function() {
              player.togglePlay();
            };

            player.connect();
        }
    </script>
</body>
</html>

문제

  • Javascript가 아닌 React와 NextJS를 썼기 때문에 약간의 코드 수정이 필요했고,
  • 어떤 컴포넌트에 해당 코드를 넣어야 잘 작동할지 의문이었다.

결론

  • 로그인 후 메인 화면이 렌더링 되었을 때부터 플레이어가 필요하므로 WebPlayback의 useEffect에 위 코드를 넣었다.
  • 코드는 아래처럼 수정했다.
  • 토큰은 로그인 시에 백엔드로부터 받아온 access token을 사용했다. (위에서 알려준 1시간 짜리 토큰을 넣어도 된다.)
    참고로 토큰을 getOAuthToken 콜백 함수에 넣어줄 때 문자열 맨 처음과 끝에 있는 ""를 벗겨서 넣어줘야 한다.
  useEffect(() => {
    const script = document.createElement("script");
    script.src = "https://sdk.scdn.co/spotify-player.js";
    script.async = true;

    document.body.appendChild(script);

    window.onSpotifyWebPlaybackSDKReady = () => {
      const player = new window.Spotify.Player({
        name: "Web Playback SDK",
        getOAuthToken: (cb: any) => {
          // Run code to get a fresh access token
          cb(token?.replace(/\"/g, "")); // 이 token은 로그인 시에 백엔드에서 받아 온 access token이다.
        },
        volume: 0.5,
      });

      player.addListener("ready", ({ device_id }) => {
        console.log("Ready with Device ID", device_id);
      });

      player.addListener("not_ready", ({ device_id }) => {
        console.log("Device ID has gone offline", device_id);
      });
      player.addListener("player_state_changed", (state) => {
        if (!state) {
          return;
        }
        console.log("state changed", state);
      });

      player.connect();
    };
  }, [token]);

플레이어를 만들긴 했는데 그래서 이걸 어떻게 사용하냐!
는 다음글에서 알아보겠다

구현 코드 궁금하면 여기 보라고까지 해놨는데 다음 글로 넘기니 민망ㅎ

4개의 댓글

comment-user-thumbnail
2022년 7월 7일

잘 보았어요 저도 시간있을때 만들어 봐야겠어요

1개의 답글
comment-user-thumbnail
2022년 7월 17일

멋집니다!

1개의 답글