또 다시 시작된 팀프로젝트..!
최종 프로젝트 들어가기 전 마지막 팀프로젝트이다. 시간이 참 빠른 것 같으면서 아직 두 달 정도 남은거 보면 느린 것 같다.
이번 팀프로젝트는 Next.js 기반으로 그동안 배운 기술을 모두 활용해서 프로젝트를 하게 되었다. 주제도 자유, api 쓰는 것도 자유, 전부 자유여서 주제 선정하고 기획하는데 시간이 평소보다 더 오래 걸렸다.
다양한 후보가 있었는데 api
도 찾아야하고 주어진 시간 + 실력을 고려해서 주제를 정했다.
Pokétify | Spotify api 를 활용한 음악 추천 사이트
01. 사이트 소개
사용자는 앨범명, 가수명 등의 키워드로 관련된 곡을 검색할 수 있으며, 자신의 취향이 담긴 플레이리스트를 만들고 링크를 공유할 수 있다.
커뮤니티 사이트에서 해당 링크에 대한 댓글을 남기며 소통할 수 있다.
02. 페이지 구성
내가 맡은 부분은 검색부분이었다. Supabase
사용하는거랑 고민하긴 했는데 개인과제때도 그렇고 늘 query
값을 받아오는 부분이 헷갈려서 이번에 제대로 알고 최종프로젝트로 넘어가는게 좋을 것 같다는 생각이 들어서 선택했다.
Spotify api
받아오는 방법은 구글링해도 글이 정말 많고 docs
설명이 자세하게 나와있어서 나같은 api
입문자들도 어떤 데이터 값이 들어있는지 이해하기 쉬웠다. 이 부분이 우리가 많은 음원 api
중에서 Spotify api
를 선택한 이유였다.
api
를 발급받고 작업을 하려고 했는데 Spotify api는 무조건 Token
이 필요하다. 클라이언트 ID
와 시크릿키
로 인증 후에 받은 토큰을 요청마다 헤더에 계속 보내줘야 한다... (왜..?)
뿐만 아니라 1시간 마다 만료가 되기 때문에 만료 이슈를 생성하지 않으려면ㅋㅋㅋㅋㅋ 그 전에 새 Token
을 발급받아야하는.. 예...
일단 이런 내용을 참고해서 코드를 작성해보았다.
따라서 해야할 일...
1. Token 받아오는 로직 작성
2. Spotify API에서 검색 요청
3. GET 요청하기
let accessToken: string | null = null;
let expireToken: number | null = null;
// Access Token 받기
export async function getAccessToken() {
if (accessToken && expireToken && Date.now() < expireToken) {
return accessToken;
}
const authParam = {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body:
"grant_type=client_credentials&client_id=" +
process.env.NEXT_PUBLIC_SPOTIFY_API_KEY +
"&client_secret=" +
process.env.NEXT_PUBLIC_SPOTIFY_CLIENT_SECRET
};
// 새로운 토큰 요청
const res = await fetch("https://accounts.spotify.com/api/token", authParam);
if (!res.ok) {
const errorData = await res.json();
throw new Error(`토큰 요청 실패: ${res.status} - ${errorData.error_description}`);
}
const data = await res.json();
console.log("토큰 응답 데이터:", data);
// 새로운 토큰 저장
accessToken = data.access_token;
expireToken = Date.now() + data.expires_in * 1000;
return accessToken;
}
처음에 내가 작성한 코드랑 많이 달라지긴 했다...ㅎ
api
를 받아오는데 자꾸 오류가 났는데 스포티파이 docs
코드가 잘은 모르지만 백엔드 기반 코드여서 혼자 해보려니까 쉽지 않았따... 구글링 해서 어떤.. 천사분을 만나서 그 코드를 기반으로 작성했고 다행히 api
를 잘 받아올 수 있었다!! 👍 (참고코드)
콘솔로 확인했을 때 docs
에 있는 데이터랑 똑같이 잘 넘어와졌다.
이제 추가할 건 바로 만료되기 전에!! 새로운 Token
으로 바꿔주기!
expires_in
저게 뭘까 했는데 저게 바로 1시간 기준으로 만료되는 시간이었다. 저걸 써먹어보자!! 해서 코드를 추가했다.
let accessToken: string | null = null;
let expireToken: number | null = null;
//Token 만료 확인하기
export async function getAccessToken() {
if (accessToken && expireToken && Date.now() < expireToken) {
return accessToken;
}
Date.now()
메소드로 토큰을 발급받은 그 시간을 기점으로 3600밀리초(1시간)이 지날 때를 측정하도록 만들었다. 만료되었다면 토큰을 발급받는 로직이 실행된다.
쓰다보니 코드가 꽤 길어지고 복잡해진 것 같아서 정리할 수 있는 방법은 없을지 고민중이다. 또 localStorage
에 저장하는게 좋을지, 그냥 서버쪽에서 알아서 업데이트하고 관리하는게 좋을지도 좀 더 생각해봐야할 것 같다.
개인 토큰이라 보안만 따진다면 현재 코드로 가는게 좋겠지만 새로고침을 했을 때도 동일한 토큰을 사용하게 하려면 localStorage
에 저장하는게 낫지 않을까 하는게 내 생각...
일단 주말동안 기능 최대한 구현해보고 튜터님께 질문해봐야쥐..껄껄