음악 재생 기능은 유저가 로그인한 경우에만 기능을 사용할 수 있다. 그래서 Spotify를 결제했다
로그인할 때 유저의 playback 상태에 접근할 수 있도록 하기 위해 scope를 추가해 주어 권한을 설정해야 한다.
scope 설정
스포티파이 로그인 페이지로 리다이렉트 할 때 scope를 아래와 같이 설정하자.
'user-read-private user-read-email user-read-playback-state user-modify-playback-state streaming'
유저의 playback state를 읽고 수정할 수 있도록 하고, 스트리밍까지 할 수 있도록 권한 설정을 했다.
SDK 세팅
window에서 onSpotifyWebPlaybackSDKReady 메서드를 인식하기 위해 먼저 type을 추가해 주었다.
yarn add -D @types/spotify-web-playback-sdk
그다음 useEffect를 통해 동적으로 sdk를 추가한 후 SDK 초기 세팅을 진행한다.
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) => {
cb(getToken());
},
volume: 0.5,
});
}, []);
Spotify Player에서 제공하는 이벤트는 4가지가 있다.
- 'ready'
- 'not_ready'
- 'player_state_changed'
- 'autoplay_failed'
나는 'ready'일 때 Web API의 Transfer Playback을 사용하여 새 장치를 인식시켜 주었다.
그리고 'player_state_changed'는 말 그대로 player의 상태가 바뀔 때 콜백 함수가 실행된다. 재생, 정지, 다음 또는 이전 노래 재생 같은 경우를 상태가 바뀌는 경우로 볼 수 있다.
player.addListener('ready', ({ device_id }) => {
console.log('Ready with Device ID', device_id);
api.put('https://api.spotify.com/v1/me/player', {
device_ids: [device_id],
play: false,
});
});
player.addListener('not_ready', ({ device_id }) => {
console.log('Device ID has gone offline', device_id);
});
player.addListener('player_state_changed', (state) => {
if (!state) {
return;
}
setTrack(state.track_window.current_track);
setPaused(state.paused);
setPosition(state.position);
setDuration(state.duration);
player.getCurrentState().then((state) => {
!state ? setActive(false) : setActive(true);
});
});
에러 1 : 400 에러?
Transfer Playback api를 'ready'일 때 호출하고 있다. 그런데 만약 device_ids에 여러 개의 id가 들어가면 400 에러가 뜨게 된다.
api 문서를 자세히 보면 body에 들어가는 device_ids는 비록 array 형태지만, 하나의 id만 들어가야 한다고 명시하고 있다. 두 개 이상을 넣게 되면 400 에러가 뜬다고 하니 조심하자.
에러 2 : 502 에러?
Transfer Playback api를 사용할 때 502 에러가 뜨는 경우도 있다.
네트워크 탭에서 응답을 보면 이렇게 오는 걸 알 수 있다.
{
"error" : {
"status" : 502,
"message" : "Bad gateway."
}
}
동일한 문제로 올린 이슈도 있었다. 내 생각으로는 React.StrictMode가 true인 상태인 경우 렌더링이 두 번 되기 때문에 api 호출 또한 두 번이 되어 에러가 띄워진 것 같았다.
그래서 next.config.js에서 reactStrictMode를 false로 바꾸니 에러가 뜨지 않았다.
+ 스포티파이가 어느 기기에서도 사용하지 않을 때 Transfer Playback api 호출하면 502 에러가 뜨는 문제
이 문제는 스포티파이 내부적인 문제인듯 하다. 여러 사람들도 동일한 이슈가 발생한 것 같지만 해결책은 없어보인다. 번거롭지만 스포티파이가 활성화되어있는 상태에서만 502 에러가 뜨지 않는다.
재생 기능 추가
Web Playback SDK에서 지원하는 기능을 사용하면 간단하게 구현할 수 있다.
play/pause는 togglePlay()
이전 노래는 previousTrack()
다음 노래는 nextTrack()
위에서 state가 변경될 때마다 position이 수정되고 노래가 현재 재생 상태인지 아닌지도 파악할 수 있으므로 useEffect과 setInterval을 사용하여 재생 시 position을 변경해 주었다.
useEffect(() => {
if (is_paused) {
return;
}
const interval = setInterval(() => {
setPosition((prev) => prev + 100);
}, 100);
return () => clearInterval(interval);
}, [is_paused]);
볼륨을 조절하는 기능, position을 움직이는 기능 또한 api에서 제공하고 있으므로 문서를 참고하여 커스텀하면 된다.
Spotify API 사용 후기
API 문서에 자세하고 친절하게 설명되어 있어 어렵지 않게 사용할 수 있었다. 개인 프로젝트를 진행할 때 백엔드가 없어서 걱정인 분들이라면, 이렇게 open API를 사용하여 혼자 프로젝트를 진행해 보는 것을 추천한다. 이번에 처음 open API를 사용해 보았는데 고민한 부분들도 많았고 배웠던 점들도 많았다.
내가 만든 프로젝트는 Next.js를 익히기 위해 진행했기 때문에 가볍게 기본 기능만 들어가 있는 정도이지만, Spotify API를 활용하여 제대로 기획해서 목적이 뚜렷한 프로젝트를 한다면 더욱 멋진 서비스를 만들 수 있을 것이라고 생각한다. 다들 사용해 보는 걸 추천!
'React' 카테고리의 다른 글
[사이드 프로젝트] 우당탕탕 리액트로 크롬 익스텐션 만들기 (Gachon-Tools) (0) | 2023.06.01 |
---|---|
[React] 우당탕탕 라이브러리 배포해보기 (2) | 2023.04.24 |
Spotify API 사용기 (2) - SSR에서의 React Query (0) | 2023.03.26 |
Spotify API 사용기 (1) - 앱 생성 및 로그인 기능 구현 (with Next.js) (0) | 2023.03.24 |
[React] 상태 관리 라이브러리의 이해 - Redux 동작 원리 (1) | 2023.02.02 |