youtube api로 리액트에 영상 가져오기

둘둘·2020년 6월 13일
6
post-thumbnail

api key 받는 과정은 생략!

youtube api 설치하기

npm install --save youtube-api-search

요걸 이용해서 youtube에서 api를 받아올 수 있다!
요렇게!! (혹시 몰라서 모자이크 처리했다 ㅋㅋ)

이 화면이 뜨려면 어떻게 해야하냐

const KEY = "여기에 구글에서 받은 api key를 입력하시오";
const channelID = "여기에 불러오고자 하는 유튜브 채널의 id를 입력하시오";
const epListID = "여기에 불러고고자하는 유튭 채널의 재생목록 id를 입력하시오";

export const ytPlayList = `https://www.googleapis.com/youtube/v3/playlistItems?playlistId=${epListID}&part=snippet,id&order=date&maxResults=10&channelID=${channelID}&key=${KEY}`;
// data&maxResults 다음에 쓰는 숫자를 이용해 원하는 만큼 불러올 수 있음

요걸 fetch나 axios를 이용해 특정 컴포넌트에 직접 불러올 수도 있겠지만!
나는 특정 그룹에 의해 mock data를 만들어야 했기에 일단 직접 데이터 구조를 작성해 배열을 만들었다!

구조짜는게 약해서 머리 싸매면서 만들었지만 인제 안 쓰인다는 거.. 뚀륵
쫌 더 짬이 차면 구조도 쉽게 쉽게 잘 짜게 되겠지!!?!

이제 react-youtube를 설치해주자!

react-youtube 설치하기

npm install --save react-youtube

난 이게 외부 라이브러리인줄 알고 와~~ 초반에 이 이름으로 잘 쟁취했네!! 했는데
진짜로 유튜브 꺼였다. ㅋㅋㅋㅋㅋㅋ
오리지날의 위엄... 크...~~

이렇게 youtube 영상을 불러오면 조회수도 늘고~ 비디오 데이터를 어디에 저장하지 않아도 된다는 점이 편하다!!
나는 영상을 모달 형식으로 띄워야해서 저번에 만들었던 모달창 양식을 고대로 갖다 썼다!

👉모달 만드는 과정이 궁금하다면 클릭 클릭

youtube api 받아온 영상 모달로 띄우기

적용은 아래오ㅏ 같이!!

import React, { useState } from "react";
import YouTube from "react-youtube";
import resizeLayout from "Components/Layout/ResizeLayout";
import "./VideoModal.scss";

const VideoModal = (props) => {
  const { onClose, isMobile } = props;
  const [open, setOpen] = useState(false);
  const handleModal = (flag) => {
    setOpen(flag);
    onClose();
  };

  const opts = {
    width: "640",
    height: "390",
    playerVars: {
      autoplay: 1,
    },
  };

  const mobileOpts = {
    width: "320px",
    height: "200px",
    playerVars: {
      autoplay: 1,
    },
  };

  return (
    <div
      className="video-modal-container"
      onClick={() => handleModal(false)}
      style={{ position: "fixed" }}
    >
      <div className="video-modal-wrapper">
        <span className="video-white-x" onClick={() => handleModal(false)}>
          x
        </span>

        {isMobile ? (
          <YouTube videoId={props.videoID} opts={mobileOpts} />
        ) : (
          <YouTube videoId={props.videoID} opts={opts} />
        )}
      </div>
    </div>
  );
};

export default resizeLayout(VideoModal);

opts 속성을 이용해 영상의 가로, 세로 길이 및 자동 재생여부를 결정할 수 있는데
나는 모바일과 데톱의 영상 사이즈가 달라야 했기 때문에 resize를 HOC로 불러왔다.

사실 resize 부분은 내가 만든것도 아니고, HOC도 아직 잘 모르는데 따라 쓴거라서
요 부분은 나중에 공부하고 다시 올릴 예정쓰!!

여기까진 엄청 간단했는데!
내가 적용할 페이지 구조가... (물론 간단하긴 한데..)
프롭스로 넘기는게 많아서 머리가 아팠다 ㅋㅋㅋ
아직 공개된 페이지가 아니라 공개는 못하겠고.. 일단 이렇게 생겼다

슬라이더에 들어가는 이미지를 클릭했을 때도 영상이 모달로 나와야 하고,
아래의 영상 썸네일을 눌렀을때도 해당 영상이 모달로 나와야 했다!
아주 원본 디자인에선 옵션 선택시 해당 그룹에 대한 영상만 나왔어야 했는데
기획이 조금 바뀌어서 옵션 태그와 페이지네이션은 안녕~~

import React, { Component, Suspense, lazy } from "react";
import Portal from "Components/Modal/Portal";
import Wrapper from "Components/Wrapper"; // Nav와 Footer가 있는 레이아웃임
import VideoModal from "./VideoModal";
import ImgSlider from "./ImgSlider";
import { youtubeData } from "./data"; // 유튭 데이터 
import { slides } from "./slides"; // 슬라이드에 쓰일 데이터
import "./Epilogue.scss";

const ImgCard = lazy(() => import("./ImgCard"));

class Epilogue extends Component {
  constructor(props) {
    super(props);
    this.state = {
      currentSlide: 1,
      videoID: "",
    };
  }

  setVideo = (id) => {
    this.setState({
      videoID: id || "",
    });
  };

  isCurrentSlide = (currentSlide) => {
    this.setState(currentSlide);
  };

  render() {
    const { videoID } = this.state;

    return (
      <>
        <Wrapper isWhiteBg> // Nav bar 속성 프롭스로 넘긴 것
          {videoID && ( // videoID가 존재할때 영상이 모달로 열림
            <Portal>
              <VideoModal
                onClose={() => {
                  this.setVideo();
                }}
                videoID={videoID}
              />
            </Portal>
          )}
          <div className="epilogue-container">
            <ImgSlider
              slides={slides}
              currentSlide={this.isCurrentSlide}
              onClick={(vid) => {
                this.setVideo(vid);
              }}
            />
            <div className="card-list-container content">
              <div className="card-list-top content">
                <span className="card-list-title">수강생 후기 모음</span>
              </div>
              <div className="divider" />
              <div className="img-card-list">
                {youtubeData.map((el) => (
                  <Suspense fallback={<div>loading...</div>}>
                    <ImgCard
                      thumbnail={el.thumbnail}
                      videoDesc={el.videoDesc}
                      userName={el.name}
                      onClick={() => {
                        this.setVideo(el.videoID);
                      }}
                      key={el.videoID}
                    />
                  </Suspense>
                ))}
              </div>
            </div>
          </div>
        </Wrapper>
      </>
    );
  }
}

export default Epilogue;

중간에 react의 lazy와 Suspense가 있는데...
이렇게 쓰면 레이지 로딩 된다는데 왜 안되는거 같고요...?!
다시 수정해볼 예정이고요...?! ㅠㅠ

어쨌든 좀 뿌듯하게 쓴 코드는 바로 요것

  setVideo = (id) => {
    this.setState({
      videoID: id || "",
    });
  };

처음엔 모달을 닫는 함수를 따로 만들었는데, 그럴 필요 없이
그냥 인자가 없을때 ""로 주면 모달이 닫힘
굿굿~ 코드 하나 줄였다 오예 😎

레이지 로딩 부분은 아직 손을 보고 있지만.. 왜 지금 블로그 업로드를 하냐?

지금 안 쓰면 쓸 시간이 없다. 난 무지무지 바쁘기 때문이다 ㅋㅋㅋ
쓸 수 있을때 조금씩이라도 써놓자는 마음에서 후후..
나중에 수정하면 되겠지?!!

특정 그룹별로 받던 데이터 구조가 단순하게 바뀌어서
그냥 유튜브에서 바로 데이터를 받아올까도 생각중이다!
그렇게 되려면 회사용 구글 계정 api key로 바꿔치기 하면 되겠지..?!

내 개인계정에서 과금 나가면 안돼~~~ 😂😂😂

profile
Dooreplay! 안 되면 될 때까지,

2개의 댓글

comment-user-thumbnail
2022년 1월 10일

오!! 대박 나중에 써봐야겠어요!!

답글 달기
comment-user-thumbnail
2022년 10월 20일

이 유용한 웹사이트를 알게 되어 매우 기쁩니다. 그것은 주변의 모든 것에 대한 풍부한 흥미로운 정보, 특히 앞서 언급한 기사의 정보를 제공합니다.
https://wordsfromletters.co/

답글 달기