Skip to content

Commit

Permalink
feat : api 캐싱 추가 (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
cmlim0070 authored Oct 31, 2024
1 parent 70bed81 commit 2e50b5e
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 191 deletions.
3 changes: 3 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ export default [
}
],
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx']
},
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx']
Expand Down
55 changes: 32 additions & 23 deletions src/entities/music/api/fetchMusicList.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import axios from 'axios';
import { MusicItem, YouTubeResponse, SpotifyResponse } from '../model/type';
import defaultApi from '../../../shared/api/api';
import axios from 'axios';
import React from 'react';
import { useQuery } from '@tanstack/react-query';

/**
* 스포티파이 토큰 발급
Expand Down Expand Up @@ -55,13 +56,14 @@ const youtubeApi = defaultApi({
});

/**
* 음악 검색 함수
* @param query 검색어 - gpt 응답 / 사용자 직접 입력
* 검색어를 이용해 스포티파이 트랙을 검색합니다.
* @param query
* @returns
*/
export const searchMusic = async (query: string): Promise<MusicItem> => {
export const spotifySearch = async (
query: string
): Promise<SpotifyResponse> => {
try {
// 스포티파이 검색
const spotifyApi = await createSpotifyApi();
const spotifyResponse = await spotifyApi.get('/search', {
params: {
Expand All @@ -70,32 +72,39 @@ export const searchMusic = async (query: string): Promise<MusicItem> => {
limit: 1
}
});
return spotifyResponse.data.tracks.items[0] as SpotifyResponse;
} catch (error) {
console.log('스포티파이 데이터 패치 에러 : ', error);
throw new Error('스포티파이 검색 실패');
}
};

const spotifyTrack = spotifyResponse.data.tracks
.items[0] as SpotifyResponse;

// 유튜브 검색
/**
* 유튜브 ID를 검색해서 반환합니다.
* @param param0 트랙명, 가수 이름
* @returns 유튜브 ID
*/
export const youtubeSearch = async ({
trackName,
artistName
}: {
trackName: string;
artistName: string;
}) => {
try {
console.log('유튜브 검색이 실행되다.');
const youtubeResponse = await youtubeApi.get('/search', {
params: {
q: `${spotifyTrack.name} ${spotifyTrack.artists[0].name}`,
q: `${trackName} ${artistName}`,
part: 'snippet',
type: 'video',
maxResults: 1
}
});

const youtubeVideo = youtubeResponse.data.items[0] as YouTubeResponse;

return {
title: spotifyTrack.name,
artist: spotifyTrack.artists[0].name,
thumbnailUrl: spotifyTrack.album.images[0].url,
// youtubeId: 'M5aEiDSx7kI'
// api 할당량 제한으로 그냥 아무 영상 id로 고정하고 테스트 중입니다.
youtubeId: youtubeVideo.id.videoId
};
return youtubeVideo.id.videoId;
} catch (error) {
console.error('스포티파이 음악 검색 실패 :', error);
throw error;
console.log('유튜브 데이터 패치 에러 : ', error);
throw new Error('유튜브 검색 실패');
}
};
61 changes: 61 additions & 0 deletions src/entities/music/hooks/useMusicSearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useQuery } from '@tanstack/react-query';
import { spotifySearch, youtubeSearch } from '../api/fetchMusicList';
import { MusicItem } from '../model/type';

// TODO - 쿼리 유효성 검사 / 훅이 여러번 실행되는 문제 해결

/**
* 검색 훅
* @param query
* @returns
*/
export const useMusicSearch = (query: string) => {
const spotifyQuery = useQuery({
queryKey: ['spotify', query],
queryFn: () => spotifySearch(query),
enabled: !!query,
staleTime: 1000 * 60 * 5, // 5분
gcTime: 1000 * 60 * 30, // 30분
refetchOnWindowFocus: false, // 윈도우 포커스 할 때 자동 리패치 옵션 제거
retry: 1 // 1회 재시도
});

const youtubeQuery = useQuery({
queryKey: [
'youtube',
spotifyQuery.data?.name,
spotifyQuery.data?.artists[0].name
],
queryFn: () =>
youtubeSearch({
trackName: spotifyQuery.data!.name,
artistName: spotifyQuery.data!.artists[0].name
}),
enabled:
!!spotifyQuery.data?.name &&
!!spotifyQuery.data?.artists?.[0]?.name,
staleTime: 1000 * 60 * 5, // 5분
gcTime: 1000 * 60 * 30, // 30분
refetchOnWindowFocus: false, // 윈도우 포커스 할 때 자동 리패치 옵션 제거
retry: 1 // 1회 재시도
});

const combinedData =
spotifyQuery.data && youtubeQuery.data
? {
title: spotifyQuery.data?.name,
artist: spotifyQuery.data?.artists[0].name,
thumbnailUrl: spotifyQuery.data?.album.images[0].url,
// youtubeId: 'M5aEiDSx7kI' // api 호출 제한 상황용 테스트 ID
youtubeId: youtubeQuery.data
}
: undefined;

return {
data: combinedData as MusicItem,
isLoading: spotifyQuery.isLoading || youtubeQuery.isLoading,
error: spotifyQuery.error || youtubeQuery.error,
spotifyStatus: spotifyQuery.status,
youtubeStatus: youtubeQuery.status
};
};
13 changes: 0 additions & 13 deletions src/entities/music/hooks/useSearchMusic.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/entities/music/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export { MusicCard } from './ui/MusicCard';
export { EmptyMusicCard } from './ui/EmptyMusicCard';
// export { useSearchMusic } from './hooks/useSearchMusic';
export { searchMusic } from './api/fetchMusicList';
export { useMusicSearch } from './hooks/useMusicSearch';
1 change: 1 addition & 0 deletions src/features/diary-write/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { VisibilityButton } from './visibility/ui/VisibilityButton';
export { MusicCardList } from '@/features/diary-write/musicList/ui/MusicCardList';
export { ConditionButtonGroup } from './condition/ui/ConditionButtonGroup';
export { SearchModeButtonGroup } from './search-mode-selector/ui/SearchModeButtonGroup';
export { MusicSearchInput } from './music-search-input/ui/MusicSearchInput';
8 changes: 2 additions & 6 deletions src/features/diary-write/musicList/ui/MusicCardList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ export const MusicCardList = ({
}
};

// 테스트
useEffect(() => {
console.log(selectedMusic);
}, [selectedMusic]);

// TODO - iframe 유튜브 api 모듈로 변경
return (
<Container>
Expand All @@ -58,7 +53,8 @@ export const MusicCardList = ({
/>
)}
</HiddenYoutubeContainer>
{responseMusicList.length === 0 ? (
{responseMusicList.length === 0 &&
responseMusicList !== undefined ? (
<EmptyMusicCard />
) : (
responseMusicList.map((music) => (
Expand Down
Loading

0 comments on commit 2e50b5e

Please sign in to comment.