깊게 언어 파는거보다는 다양한 라이브러리/프레임워크 써보는게 나을 것 같다고 조언을 들었다..ㅎ
그래서 리팩토링은 잠쉬 스탑하고 프로젝트를 진행하는데, 간단하게 뮤직 플레이어 만들어볼까..? 하다 만들게 됐다.(전혀 간단하지 않다.)
처음엔 그냥 음악검색 -> 듣기 -> 플레이리스트 저장 정도로 시작해서 라이브러리도 안끼려했는데, 웹이 너무 비어보여서.. ㅎㅎㅎㅎ
이렇게 한 5~6페이지 정도 나오게 기획해봤는데, 은근 packed..
은근 컴포넌트 단계가 나뉘고 많이 들어가서 zustand설치... 그리고, 뭐만 하면 fetch라 좋다고 소문을 들은 react-query 설치..
일단 spotify open API 를 프론트로만 구현하기에 처음부터 난관에 부딪히게 되는데, 바로 인증이다.
스포티파이 open api docs를 보면 토큰없이 원하는 api만 fetch 할 수 없다.
스포티파이 개발페이지 로그인하고 앱만들어서 거기 있는 클라이언트 ID와 시크릿키로 인증하고 토큰 받아서 그 토큰을 다른 요청마다 헤더에 계속 보내줘야된다.
나는 백엔드 없이 혼자 구현하기 때문에 ..ㅋ env에 시크릿키랑 클라이언트 아이디 넣어주고 로그인 해봤다.
아마 open api라 해서 시도해보려했다가 인증부분에서 백엔드 코드로 작성된 docs뿐이라 스킵한 프론트 분들이 있을것 같아서 코드 함께 첨부해봅니다.
export const onLogin = async () => {
const authParam = {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body:
"grant_type=client_credentials&client_id=" +
import.meta.env.VITE_SPOTIFY_CLIENT_ID +
"&client_secret=" +
import.meta.env.VITE_SPOTIFY_CLIENT_SECRET,
};
const res = await fetch("https://accounts.spotify.com/api/token", authParam);
const response = await res.json();
return response;
};
이렇게 유효한 토큰을 받게 되면 로컬스토리지에 저장하던지, 상태관리 라이브러리에 저장하던지 등등 저장해서 이렇게 api 요청때마다 함께 보내주면 됩니다.
export const onRecommand = async (accessToken) => {
const categoryParams = {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + accessToken,
},
};
const RecommandID = await fetch(
"https://api.spotify.com/v1/browse/categories?country=KR&locale=sv_SE&limit=10&offset=5",
categoryParams
);
const RecommandIDRes = await RecommandID.json();
return RecommandIDRes.categories.items;
};
여기까진 데이터 잘 받아와지는지 체크정도고 이제 진짜 문제는, 어떻게 효율적으로 이 비동기들을 실행할까 이다.
1) 데이터 파이프라인
문제점은 토큰 유효시간은 1시간으로 계속 유효한 토큰을 재발급해줘야한다.
즉 데이터 파이프라인을 고려해봐야한다.
사실 이런 복잡한? 비동기작업을 다루기는 처음인데.,(예: 뭐 클릭하면 fetch된 데이터에서 받은 url과 데이터로 또 fetch해서 다른 데이터 받아야됨)
잘 호출되다가 1시간뒤 유효기간 지난 토큰으로 요청가면 에러가 나겠지요?! ^^
일단 구현 집중적으로 별 생각 다해봤는데 최상위폴더에서 interval로 받는 즉시 3550초 지나면 다시 요청해서 내려줄까? 근데 자동으로 발급해주는거면 이제 필요없어지는 때에도 (캐시된 데이터만 사용한다던가 등) 비용이 드는건데 맞는건가..? 싶기도하고.
뭔가 타이밍을 수기로 3600초 중 50초의 나의 임의의 시간을 남기고 요청하는게 좀 웃기기도 하고, 타이밍 안맞으면 숫자 계속 바꿔가면서 수기로 타이밍 맞출건지? 등 여러 생각이 들었다.
시도할때 에러나면 그때 시도해서 다시 받을까도 생각했지만 이러면 또 로딩이 너무 지연된다.
액션이 있을때마다 새로 받자니 낭비고 흠.. 그렇게 여러 고민을 하다가
react-query를 쓰기로 했다. staleTime으로 시간 지정해서 그때동안 신선한 상태로 만들어주고 정해진 시간이 넘었고, 액션이 있을때 그 시간이 지나면 다시 페칭을 해주니, 유저의 액션과 페칭이 따로 돌거 같다. 이걸로 될거같다.는 1차 생각. (아직 검증은 안됨 이제 해봐야지..)
사실 이전까지는 비동기 작업을 많이 안다뤄봐서 이게 어떤 이점?이 있는지 체감이 잘 안됐는데, docs 읽으면서 해보니까 여태 왜 안썼지??? 라는 생각 뿐이다. 뭐가 이렇게 되는게 많아? 로고도 귀여움 ㅋ
예전에 리덕스 사가의 늪에 헤매던거에 비하면.. 러닝커브가 높진 않다(?), 그리고 물론 리액트 라우터로 loader로 프레패치 가능하긴하지만 로더에는 캐시 기능이 없다. 여튼 둘이 환상의 짝궁(참고링크)이라고 한다. 이 부분은 좀 더 배워봐야되겠다. 오늘 docs 읽기 시작해서..
2) css 관련
초반엔 y2k 감성으로 좀 각지고 테두리 있고 약간은 촌스럽게? 이런거
만들고 싶었는데, 감성이 그게 아닌가보다.
y2k하려면 기본적으로 색깔 파레트가 화려한데 그게 안되더라.. 여튼
마음은 y2k 레퍼는 애플뮤직을 보며 혼란스럽게 작업중에 문제가 있었다.
일단 애플 뮤직 처럼 이렇게 플레이바 뒤로 뒤에 컨텐츠가 blur되고, 스크롤은 플레이바 밑으로 안넘어가는걸 볼 수 있다. 즉 스크롤되는 범위와, 스크롤 바의 높이가 다르다.
이거 대체 어떻게 한거지..?
헤더랑, 풋터 고정하고 내용물만 스크롤이 생기게 하는것도 잡는데 너무 오래걸렸다. 그렇게 이것저것 해보면서 겨우 잡은 이후에 풋터 위로만 스크롤이 돌아서 풋터 포지션 fixed로 바꾸니 뒤에 내용물 비치는데 대신 스크롤이 풋터까지 내려왔다.
별거 아니긴 한데.. 스크롤 자체가 어차피 투명도 조절되어있어서 안보이긴 하는데.. 뭔가 애플뮤직처럼 스무스하게 자연스럽게 스크롤이 딱봐도 플레이바 위에서 돌았으면 좋겠다.
그렇게.. 해결방안을 찾는 ing....
추가로 된다면 애플뮤직처럼 컨텐츠가 없어도 어느정도까지 스크롤떰브줄어들면서 스크롤이 당겨졌으면 좋겠다. 앱이라 가능한건가..? 웹에서는 못본거 같기도하고
무한스크롤 비슷한걸로 어떻게 될거같은데.