먼저 구글 클라우드 서비스로 접속한 뒤 API 및 서비스 탭에서 '새 프로젝트' 버튼을 눌러
새로운 프로젝트를 생성합니다.
프로젝트를 생성했다면 라이브러리 탭으로 들어가 'YouTube Data API v3'를 선택하여 접속합니다. 사용 버튼을 누르면 위의 이미지와 같이 사용자 인증 정보를 만들라는 메세지와 함께 API 세부 정보창이 뜹니다. '사용자 인증 정보 만들기' 버튼을 눌러 들어가줍시다.
그럼 이렇게 폼 박스가 뜨는데, 단계별로 정보를 입력하는 과정을 거칩니다. 여기서 '공개 데이터'를 선택하고 다음으로 넘어가줍시다.
그럼 API 키가 생성됩니다. 유튜브 API 키는 구글 클라우드의 내 프로젝트로 들어오면 혹시 까먹게 되어도 다시 확인할 수 있습니다. 당연히 다른 오픈 API 키나 액세스 키와 마찬가지로 API를 사용할 때 http 통신에 키를 사용해야 한다면 소스 코드에 그대로 저장하지 말고 반드시 환경변수에 저장하여 클라이언트 노출을 방지해야 합니다.
여기서 GET 방식을 사용하는 http 요청으로 데이터를 받아올 수 있습니다. 현재 유튜브 데이터는 키워드 검색 결과 영상 목록, 서비스 지역 기반 영상 목록, 라이브 스트리밍 영상 목록, 내 영상 목록 등의 데이터를 사용할 수 있도록 API를 제공중입니다. 저는 이 중에서 list by keyword를 사용하여 개발중인 프로젝트의 영상 자료 목록 데이터로 사용했습니다. 해당 API는 다음과 같은 경로의 구조를 가지고 있습니다.
https://youtube.googleapis.com/youtube/v3/search?part=snippet&maxResults=18&q=coin&key={{key}}
그럼 해당 API의 요청 성공시 응답 데이터를 한 번 봅시다.
JSON 형태의 데이터가 body에 들어옵니다.
이 중에서 items 배열안에 들어있는 객체 하나가 비디오 하나의 데이터를 담고 있습니다.
여기서 원하는 정보를 선택하여 사용하면 됩니다.
저는 useContext로 생성한 컨텍스트에서 유튜브 말고도 네이버, 업비트의 API 호출 함수를 모두 관리하는 방식으로 구현을 했습니다. 그래서 클래스 안에 axios의 인스턴스를 하나 만들고 그 인스턴스를 사용하여 실제 API를 호출하는 메서드 하나와 미리 포스트맨으로 받아온 데이터를 mock data로 json 파일에 저장해둔 걸 호출하는 메서드를 하나 만들었습니다. 물론 유튜브 API는 하루에 호출할 수 있는 횟수 10,000회라서 부족할 일은 없을 것입니다.
import * as React from 'react';
import { useQuery } from '@tanstack/react-query';
import { useOpenApi } from '../context/OpenApiContext';
import PropTypes from 'prop-types';
import Grid from '@mui/material/Grid';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import Skeleton from '@mui/material/Skeleton';
function VideoCard(props) {
const { loading = false } = props; // 기본적으로 loading = false
const { youtube } = useOpenApi();
const {
isPending,
isError,
data: videos,
error,
} = useQuery({
queryKey: ['videos'],
queryFn: () => {
return youtube.useMock('코인 추천');
},
staleTime: 1000 * 60 * 10,
});
if (isPending) {
// 로딩 애니메이션으로 교체
return <span>Loading...</span>;
}
if (isError) {
// 에러 메세지
return <span>에러 발생 : {error}</span>;
}
return (
<>
<Grid container spacing={1}>
{(loading ? Array.from(new Array(3)) : videos).map((video) => (
<Grid item xs={4} key={video.id}>
<Box key={video.id} sx={{ width: 210, marginRight: 0.5, my: 3 }}>
{video ? (
<img
style={{ width: 210, height: 130 }}
alt={video.snippet.title}
src={video.snippet.thumbnails.default.url}
/>
) : (
<Skeleton variant="rectangular" width={210} height={130} />
)}
{video ? (
<Box sx={{ pr: 2 }}>
<Typography gutterBottom variant="body2">
{video.snippet.title}
</Typography>
<Typography
display="block"
variant="caption"
color="text.secondary"
>
{video.snippet.channelTitle}
</Typography>
<Typography variant="caption" color="text.secondary">
{`${video.snippet.publishTime}`}
</Typography>
</Box>
) : (
<Box sx={{ pt: 0.5 }}>
<Skeleton />
<Skeleton width="60%" />
</Box>
)}
</Box>
</Grid>
))}
</Grid>
</>
);
}
VideoCard.propTypes = {
loading: PropTypes.bool,
};
export default function Videos() {
return (
<>
<Typography>최신 트렌드🔥</Typography>
<VideoCard />
</>
);
}
데이터 캐시를 위해서 리액트 쿼리도 사용중입니다.
실제로 유튜브 데이터의 경우 매번 재요청과 렌더링이 일어나게 할 필요는 없습니다.
그래서 useEffect보다는 리액트 쿼리를 사용하였습니다.
이렇게 유튜브 데이터 API를 사용하여 영상 데이터를 활용하여 비디오 카드 리스트를 구현해봤습니다.