본문 바로가기
매일 해내는 개발/Develog

[Develog] 유튜브 API 요청 후 파이어베이스에 저장하는 방법2

by 해야지 2023. 1. 29.
반응형

1탄

 

[Develog] 타입스크립트 + 유튜브 API로 데이터 요청 후 파이어베이스로 저장하는 방법

첫 번째로 했던 작업은 타입스크립트로 유튜브 API를 요청하고 요청한 데이터를 가공해서 파이어베이스에 저장하는 방법이었다. 이 때는 API 사용법이 아직 익숙하지 않아 플레이리스트를 요청

subtlething.tistory.com

저번시간에 유튜브 API를 이용해 데이터를 받아 오는 것 까진 했는데

생각해보니 우리 프로젝트에서는 플레이리스트가 필요했다.

우리가 짠 와이어 프레임 상 대시보드 페이지에 아래처럼 강의 리스트를 보여줘야 하기 때문이다..

근데 이미 데이터를 단일 데이터로 넣었는뎅...... 힝 대시보드 없애버릴까 싶었지만

개발자로서 그럴 쑨 없쥐

플레이리스트 가져오기? 그게 왜 안되겠어. 바로 도전

 

트러블 슈팅 순서

  1. 문제 정의
  2. 사실 수집
  3. 원인 추론
  4. 조치 및 방안 검토
  5. 결과 관찰
  6. (만약 문제가 다시발생한다면 4번으로 다시)

 

1. 문제 정의

현재 들어가 있는 데이터 상태는 이런식이다. 이걸 각 항목별로 리스트화 시켜줘야한다.

지금은 videoId로만 돼 있는 데이터를 가져왔었는데 

이걸 카테고리, 채널ID, 채널Title 빼고는 리스트화 해줘야 한다.

 

2. 원인 추론

현재 요청 API주소

`https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=10&q=리액트&order=relevance&key=${API키}`

1. 플레이리스트를 받아오려면 어떻게 해야할까?

2. 플레이리스트 데이터를 파이어베이스에 배열로 저장하려면 어떻게 해야할까?

 

3. 조치 및 방안 검토

1. 플레이리스트를 받아오려면 어떻게 해야할까?

1) 유튜브 API에 대한 공부가 더 필요했다.

2) YouTube API에 Playlist 항목이 따로 있길래 시도해봤다.

잘 나온다. 각 리스트 내부의 비디오 별로 videoId 값이 다 있어서 사용할 수 있을 것 같다.

그런데 문제는 얘는 q 속성이 없어서 검색어로 거를 수 없고 플레이리스트의 ID가 필요하다는 것이다.

그래서 먼저 q 항목이 있는 seach를 사용해서 검색을 거친 후에 플레이 리스트를 얻을 수가 있었다.

기존의 API url에서 type 속성을 추가해 playlist만 거를 수가 있다.

`https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=10&q=리액트&order=relevance&type=playlist&key=${API키}`

 

 

로직

1) search로 플레이리스트 데이터를 요청해서 플레이리스트 id를 얻어 addDoc으로 문서를 만들어둔다. 

2) 얻은 플레이리스트 데이터를 리스트로 변환한다.

3) 변환한 데이터를 반복문을 돌려 문서 id와 일치하는 데이터는 updateDoc, arrayUnion으로 배열데이터로 저장한다.

 

과정

1탄에서 작성했듯이 axios로 API를 요청 후 파이어베이스에 addDoc을 통해 데이터를 추가할 수 있다.

1) search로 플레이리스트 데이터를 요청해서 플레이리스트 id를 얻어 addDoc으로 문서를 만들어둔다. 

 const getPlaylistIdHandler = (e: React.MouseEvent) => {
    e.preventDefault();
    axios
      .get(
        //플레이리스트용
        `https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=10&q=리액트&order=relevance&type=playlist&key=${API키}`
      )
      .then((res) => {
        setPlaylist(res.data.items);
      })
      .catch((err) => {
        console.log('API 요청 실패', err);
      });

    {
      playlist &&
        playlist.map((i: any, idx) => {
          if (i?.id?.playlistId) {
            //플레이리스트일때
            addDoc(collection(dbService, 'CLASS'), {
              category: 'react',
              channelId: i?.snippet?.channelId,
              channelTitle: i?.snippet?.channelTitle,
              title: i?.snippet?.title,
              playlistId: i?.id?.playlistId,
              thumbnail: i?.snippet?.thumbnails.high.url,
            });
          } 
        });
    }
    return null;
  };

그리고 이전에 포스팅했던 Promise 객체를 배열로 받는 방법을 통해 데이터를 받아온다.

 

[Error] 타입스크립트 라우터 오류 'Page'은(는) JSX 구성 요소로 사용할 수 없습니다. 해당 반환 형

오류내용 'Page'은(는) JSX 구성 요소로 사용할 수 없습니다. 해당 반환 형식 'Promise'은(는) 유효한 JSX 요소가 아닙니다. 'Promise' 형식에 'ReactElement' 형식의 type, props, key 속성이 없습니다. 타입스크립

subtlething.tistory.com

2) 얻은 플레이리스트 데이터를 리스트로 변환한다.

const getData = async () => {
    let list: object[] = [];
    const q = query(collection(dbService, 'CLASS'));
    const querySnapshot = await getDocs(q);
    querySnapshot.forEach((doc) => {
      const obj = {
        id: doc.id,
        ...doc.data(),
      };
      list.push(obj);
    });
    return list;
  };

  //promise 데이터 리스트로 변환
  const promise = getData();
  const [playlistIdList, setPlaylistIdList] = useState<any[]>([]);
  const getPlaylistId = async () => {
    await promise.then((data: any) => {
      setPlaylistIdList(data);
    });
  };

3) 변환한 데이터를 반복문을 돌려 문서 id와 일치하는 데이터는 updateDoc, arrayUnion으로 배열데이터로 저장한다.

 const getVideoDataHandler = async (e: React.MouseEvent) => {
    e.preventDefault();
    let k = 0;
    while (k < playlistIdList.length) {
      await axios
        .get(
          //플레이리스트 아이디를 통해 videoId가 있는 데이터 가져오기
          `https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=${playlistIdList[k]?.playlistId}&key=AIzaSyBInemS4UAbNOJHtXpG0OW1neY96YqyGmQ`
        )
        .then((res) => {
          console.log('API요청 완료', k, res?.data?.items);
          res?.data?.items?.map((i: any) => {
            const docRef = doc(dbService, 'CLASS', playlistIdList[k].id);
            console.log('1 통과');
            if (playlistIdList[k]?.playlistId === i?.snippet?.playlistId) {
              console.log('2통과');
              updateDoc(docRef, {
                videotitle: arrayUnion(i?.snippet?.title),
                description: arrayUnion(i?.snippet?.description ?? '없음'),
                videoId: arrayUnion(i?.snippet?.resourceId?.videoId),
                thumbnail: arrayUnion(
                  i?.snippet?.thumbnails.high.url ?? '없음'
                ),
              });
            }
          });
        })
        .catch((err) => {
          console.log('API 요청 실패', err);
        });

      k++;
    }

    return null;
  };



4. 결과 관찰

데이터가 잘 들어가는걸 확인 할 수 있다!

이 작업은 개발자 페이지에서 이루어졌고, 이를 통해 YouTube API 요청 및 데이터 저장을 사전에 처리하기 때문에 API 사용량을 최소화 시킬 수 있었다.

 

반응형

댓글