[Chapter 5]Netflix 앱 만들기 시작

만들게 될 Netfilx 애플리케이션 소개

넷플릭스 사이트를 만들어보쟝

Create-React-App으로 리액트

npx create-react-app ./ 

으로 리액트를 설치해주자

The Movie DB API Key 생성하기

영화정보를 가져오는 API이다

https://www.themoviedb.org/?language=ko
여기로가서 API 키를 받아오자

요기에 api를 넣어서 원하는걸 가져온다
이미지는도 같은 방식으로 가져온다.

The Movie DB API 요청을 위한 Axios 인스턴스 생성 및 요청 보내기

Axios란?

  • 브라우저,노드제이에스를 위한 promise API를 활용하는 HTTP 비동기 통신 라이브러리
  • 백엔드랑 프론트엔드랑 통신을 쉽게하기 위해 Ajax와 더불어 사용

Axios 사용 방법

Instance화 하는 이유

  • 중복된 부분을 입력하는 것을 방지하기 위해

인스턴스 만드는 순서

  • 인스턴스 생성할 폴더 파일 생성 ap
  • axios.js 파일 작성
import axios from "axios";

const instance = axios.create({
    baseURL: "https://api.themoviedb.org/3/",
    params:{
        api_key:"b1e1a6c6195bd0f36adddb589e1bde7d",
        language:"ko-KR",
    },
});

export default instance; //이 파일 밖에서도 사용가능하게 함 
  • request.js
const requests={
    fetchNowPlaying: "movie/now_playing",
    fetchNetflixOriginals:"/discover/tv?with_networks=213",
    fetchTrending:"/trending/all/week",
    fetchTopRated:"/movie/top_rated",
    fetchActionMovies:"/discover/movie?with_genres=28",
    fetchComedyMovies:"/discover/movie?with_genres=35",
    fetchHorroryMovies:"/discover/movie?with_genres=27",
    fetchRomanceMovies:"/discover/movie?with_genres=10749",
    fetchDocumentaries:"/discover/movie?with_genres=99",
}

export default requests; //다른파일에도 사용 가능하게 하기 

넷플릭스 애플리케이션 전체 구조 생성하기


구조를 이런식으로 해서 파일을 생성해주자

파일 생성 완료 !

네비게이션 바 컴포넌트 생성하기

Nav.js 작성

import React from 'react';
import "./Nav.css"

export default function Nav() {
  return <nav className='nav'>
      <img
       alt="Netflix logo"
       src="https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Netflix_2015_logo.svg/2880px-Netflix_2015_logo.svg.png"
       className='nav__logo'
       onClick={()=>window.location.reload()}
       />
       <img
       alt="User logged"
       src="https://ih0.redbubble.net/image.618427277.3222/flat,1000x1000,075,f.u2.jpg"
       className='nav__avater'
       >
       </img>
  </nav>
}

네브바 표시

App.js 작성

import './App.css';
import Nav from "./components/Nav";

function App() {
  return (
    <div className="App">
      {/* nav컴포넌트 가져오기 */}
      <Nav /> 
    </div>
  );
}

export default App;

네브를 가져온다

Nav.css 작성

.nav{
    position: fixed;
    top: 0;
    width: 100%;
    height: 30px;
    z-index: 1;
    padding: 20px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    transition-timing-function: ease-in;
    transition: all 0.5s;
}

.nav__black{
    background-color: #111;
}

.nav__logo{
    position: fixed;
    left: 40px;
    width: 80px;
    object-fit: contain;
}

.nav__avater{
    position: fixed;
    right: 40px;
    width: 30px;
    object-fit: contain;
}

신기한 씨에스에스세계..

스크롤시 NavBar 색 변경법

Nav.js


import React,{useState,useEffect} from 'react';
import "./Nav.css"

export default function Nav() {
    const [show,setShow] = useState(false);
    useEffect(() => {
      window.addEventListener("scroll",()=>{
          if(window.scrollY>50){ //스크롤시 함수 확인 
            //스ㅡ롤 와이는 -> 얼마나 내린지 알려준다
              setShow(true); // 쇼가 트룰일때 클래스추가 
          }else{
              setShow(false); 
          }
      })
    
      return () => {
        window.removeEventListener("scroll",()=>{})
      }
    }, [])
    

// 만약 쇼가 트루일때 네브블랙클래스 주기
  return <nav className={`nav ${show && "nav__black"}`}> 
      <img
       alt="Netflix logo"
       src="https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Netflix_2015_logo.svg/2880px-Netflix_2015_logo.svg.png"
       className='nav__logo'
       onClick={()=>window.location.reload()}
       />
       <img
       alt="User logged"
       src="https://ih0.redbubble.net/image.618427277.3222/flat,1000x1000,075,f.u2.jpg"
       className='nav__avater'
       >
       </img>
  </nav>
}

useEffect를 주고 setShow를 scrollY를 판단하고 트루냐 폴스냐에 따라서
nav에 클래스를 추가하는데 한줄코드 작성 신기하당.......

  return <nav className={`nav ${show && "nav__black"}`}> 

이부분..

이미지 배너 생성하기

우선

export default function Banner() {
    const [movie, setMovie] = useState([]);
    useEffect(() => {
      fetchData();

    }, [])
    
    const fetchData =async ()=>{
        //현재 상영중인 영화 정보 가져오기 
        const request = await axios.get(requests);
        //await을 하지 않고 넣으면 pending 상태가 되어버린다 

        //여러 영화 중 영화 하나의 ID 가져오기 
        const movieId = request.data.results[Math.floor(Math.random()*request.data.results.length)].id;

        //특정 영화의 더 상세한 정보 가져오기(비디오 정보도 포함)
        const {data: movieDetail} = await axios.get(`movie/${movieId}`,{
            params:{append_to_respons : "videos"}, // movieDetail안에 영화정보들을 넣는다. 
        });
        setMovie(movieDetail); //안에 다 들어간당 
    }

  return <div></div>
}

기능부터 제작 후
UI부분까지 합친 banner.js는 다음과 같다

import axios from '../api/axios';
import requests from "../api/request";
import React,{useState, useEffect} from 'react'

export default function Banner() {
    const [movie, setMovie] = useState([]);
    useEffect(() => {
      fetchData();

    }, [])
    
    const fetchData =async ()=>{
        //현재 상영중인 영화 정보 가져오기 
        const request = await axios.get(requests);
        //await을 하지 않고 넣으면 pending 상태가 되어버린다 

        //여러 영화 중 영화 하나의 ID 가져오기 
        const movieId = request.data.results[Math.floor(Math.random()*request.data.results.length)].id;

        //특정 영화의 더 상세한 정보 가져오기(비디오 정보도 포함)
        const {data: movieDetail} = await axios.get(`movie/${movieId}`,{
            params:{append_to_respons : "videos"}, // movieDetail안에 영화정보들을 넣는다. 
        });
        setMovie(movieDetail); //안에 다 들어간당 
    };
    const truncate = (str,n)=>{
        return str?.length > n ? str.substr(0,n-1) + "...": str 

    }

   return <header
   className='banner'
   style={{backgroundImage: `url("https://image.tmdb.org/t/p/original/${movie.backdrop_path}")`,
   backgroundPosition : "top center",
   backgroundSize : "cover",
}}
   >
    <div className='banner__contents'>
        <h1 className='banner_title'>{movie.title || movie.name || movie.original_name}</h1>

        <div className='banner__buttons'>
            <button className='banner__button play'>Play</button>
            <button className='banner__button info'>More Information</button>
        </div>
        <h1 className='banner__description'>{truncate(movie.overview,100)}</h1>
    </div>
    <div className='banner--fadeBottom'></div>

  </header>
}

truncate만드는것도 신기하당 +_+
css를 입히면 예쁘게 나온다.

useEffect

  • 배열이 있다 -> 마운트 될 때만 실행
  • 배열 생략 -> 렌더링 될 때 마다 실행된다.
    그렇기에
useEffect(() => {
    fetchData(); 
},)

banner.js 에 위 코드를 작성하면 무한 렌더링 되서 이미지가 계속 뜬다.
이때

useEffect(() => {
    fetchData(); 
},[])

이와 같이 작성하면 이미지 하나만 뜬다.
그래서 무한 이미지 뜨는 이슈를 없앨 수 있다.

Styled Component에 대해서

Styled Component 란?

Css in JS 라고 하는 js파일 안에서 css를 처리 할 수 있게 해주는 대표적인 라이브러리

설치 방법

npm install --save styled-components // npm 
yarn add styled-components // yarn 

Styled Component를 이용한 비디오 배너 생성하기

play 버튼 클릭시 비디오로 전환

const [isClicked, setIsClicked] = useState(false);

우선 useState를 만들어주고
play버튼 클릭 상태에따라 다른값을 반환하게 해준다.
그리고 styled component를 사용하기 위해

}else{
    return(
        <Container>
            <homeContainer>
            clicked
            </homeContainer>
        </Container>
    )
}
}

const Container = styled.div`
    display: flex;
    justify-content : center;
    align-items : center;
    flex-direction : column;
    width : 100%;
    height : 100vh;
`

const homeContainer = styled.div`
    width : 100%;
    height : 100%;
`

위와같이 작성한다.

Iframe

Iframe은 HTML Inline Frame요소이며 Inline frame약자입니다.
효과적으로 다른 HTML페이지를 현재 페이지에 포함 시키는 중첩된 브라우저로 Iframe요소를 이용하면 해당 웹 페이지 안에 어떠한 제한 없이 다른 페이지를 불러와서 삽입 할 수 있다.

    return(
        <Container>
            <HomeContainer>
            clicked
            <Iframe 
                width="640"
                height="360"
                src={`https://www.youtube.com/embed/${movie.videos.results[0].key}?controls=&autoplay=1&loop=1&mute=1&playlist=${movie.videos.results[0].key}`}
                title="YouTube video player" 
                frameborder="0" 
                allow=" autoplay; fullscreen" allowfullscreen>
            </Iframe>
            </HomeContainer>
        </Container>
    )
}

이런식으로 예고편이 있는 영상은 가져온다.

그러면 이와 같이 뜨는걸 확인가능하다.

좋은 웹페이지 즐겨찾기