[React] 넷플릭스 클론코딩 (2)

노유성·2023년 5월 7일
0
post-thumbnail

⭐axios

🪐axios란

Axios는 JavaScript에서 사용하는 HTTP 클라이언트 라이브러리 중 하나입니다. 이 라이브러리를 사용하면 서버로 HTTP 요청을 보내고 응답을 받아오는 것이 간단하고 효율적으로 처리됩니다.
Axios는 다양한 기능을 제공합니다. 예를 들어, 다음과 같은 기능을 포함합니다.
다양한 HTTP 요청 방법(GET, POST, PUT, DELETE 등)을 지원합니다.
Promise 기반으로 작동하여 비동기적인 요청을 처리할 수 있습니다.

  • 요청과 응답을 JSON 형식으로 자동으로 변환합니다.
  • 요청에 대한 요청 헤더를 설정할 수 있습니다.
  • 요청에 대한 취소 기능을 제공합니다.
  • 요청과 응답에 대한 인터셉터(interceptor)를 사용할 수 있습니다.

이러한 기능들은 개발자가 HTTP 요청을 보내고 응답을 처리하는 과정을 간단하고 효율적으로 만들어 줍니다. 또한 Axios는 브라우저와 Node.js 모두에서 사용할 수 있으므로, 웹 어플리케이션과 백엔드 서버 모두에서 사용하기에 적합합니다. -chagGPT

🪐라이브러리 다운로드

npm install axios

🌈라이브러리 이용팁

axios 라이브러리를 import 하려고 하는데 자꾸 모듈을 찾을 수 없어서 node_modules 폴더까지 찾아봤다. 분명히 라이브러리가 있는데 에러가 떠서 왜지...? 싶었는데 알고보니 다운을 받을 때 axois 라이브러리를 다운받았다. 오타가 존재해도 라이브러리를 어떻게든 npm은 다운받고 pacakge.json파일을 남긴다. 그래서 만약에 모듈을 import하는 과정에 컴파일러가 찾을 수 없다고 하면 라이브러리를 올바르게 다운했는지부터 점검하자...

🪐axios 인스턴스화 하기

axios.js

import axios from 'axios'

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

export default instance;

axios를 인스턴스화 하는 이유는 중복된 부분을 계속 입력하지 않아도 되기 때문이라고 한다.

🌈axios.create

axios.create는 instance를 만들기 위한 함수이며 인자로 필요한 정보를 담은 Object를 받는다.

  • baseURL: 요청을 보낼 서버의 기본 URL을 설정하는 데 사용된다.
  • params: HTTP 요청의 쿼리 파라미터를 설정하는 데 사용된다.

🪐request.js

요청을 보낼 api의 앤드포인트를 저장하는 파일이다.

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",
    fetchHorrorMovies: "/discover/movie?with_genres=27",
    fetchRomanceMovies: "/discover/movie?with_genres=10749",
    fetchDocumentaries: "/discover/movie?with_genres=99",
}
export default requests;

🌈앤드포인트란?

앤드포인트(endpoint)는 API에서 클라이언트가 요청하는 서비스의 위치를 나타내는 URL입니다. 즉, 앤드포인트는 클라이언트와 서버 사이에서 데이터를 주고 받는 경로를 제공합니다. 앤드포인트는 보통 REST API에서 자주 사용됩니다. REST API는 리소스를 나타내는 URI와 HTTP 요청 메서드(GET, POST, PUT, DELETE 등)를 사용하여 데이터를 관리하는 방식입니다. 앤드포인트는 이러한 URI의 일부분으로, 클라이언트는 앤드포인트를 통해 서버의 특정 리소스에 접근하고 데이터를 요청하거나 전송할 수 있습니다.
-chatGPT

⭐Banner.js

배너 부분을 구성하는 component이다.

🪐배너로 사용할 이미지 정보 가져오기

  const [movie, setMovie] = useState([]);

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

  const fetchData = async () => {
    // 현재 상영 중인 영화 정보 가져오기
    const request = await axios.get(requests.fetchNowPlaying);

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

    const { data: moiveDetail } = await axios.get(`movie/${movieId}`, {
      params: { append_to_reponse: "videos" }
    });
    setMovie(moiveDetail);
  };

비동기 키워드 async를 이용해서 필요한 데이터를 가져오는 fetchData 함수가 있다.

사전에 정의한 앤드포인트로 현재 상영중인 영화의 정보를 요청한다. 해당 정보를 request에 담아서 사용한다.
참고로 await을 붙히지 않으면 promise 객체가 반환되므로 await을 꼭 붙혀야한다.

정보를 받아오면 request 변수에는 다음과 같은 정보가 저장된다.

우리는 이 여러가지 영화 정보 중에서 하나의 영화를 배너에 보여줄 것이기 때문에 Math 모듈의 함수들을 이용해서 임의의 영화의 ID를 가져온다.

☄️상세 정보 가져오기

const { data: moiveDetail } = await axios.get(`movie/${movieId}`, {
      params: { append_to_reponse: "videos" }
    });
    setMovie(moiveDetail);

이 부분이 상세정보를 가져오는 부분인데 변수를 구조분해할당으로 가져오는 것을 보아, 받아오는 객체에는 data property가 있는 것으로 예상된다.

axios.get 요청을 살펴보면 백틱으로 감싸서 가져오는 것을 확인할 수 있는데 params 옵션으로 query parameter를 설정하고 비디오 정보도 가져오게 해놓았다.

그 후 setter 함수를 이용해 movie state 변수의 값을 변경했다.

☄️UI

<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__button'>
          <button className='banner__button play'>play</button>
          <button className='banner__button info'>
            <div className='space'></div> More Information
          </button>
        </div>
        <h1 className='banner__description'>
          {truncate(movie?.overview, 100)}
        </h1>
      </div>
      <div className='banner--fadeBottom'/>
    </header>

반환하는 컴포넌트이다.

🌈?. (Optional chaining)

Optional Chaining은 객체의 속성에 접근할 때, 해당 속성이 없는 경우에도 에러가 발생하지 않도록 해준다.

<h1 className='banner__title'>
          {movie?.title || movie?.name || movie?.original_name }
</h1>

에서 영화의 타이틀 정보를 가져오는데 해당 정보가 title, name, original_name 셋 중 하나의 property에 저장되어있기에 존재하지 않다면 undefined를 반환하고 다음 조건문을 바라보게 설정되어있다.

언제 오류가 발생할 지 모르고 세 개중 하나에 분명히 값이 존재한다면 옵셔널 체이닝을 통해서 값에 접근하는 방식은 꽤 유용한 것 같다.

🌈truncate

일반적으로 truncate는 문자열을 자르는 함수의 이름이다.
위 예제에서도

const truncate = (str, n) => {
    return str?.length > n ? str.substr(0, n-1) + '...' : str;
  }

함수를 직접 만들어서 사용하고 있으며 두 번째 인자에 100이라는 값을 넘겨주어서 만약에 movie?.overview 의 의 길이가 100을 넘는다면 그 뒤에는 ' ... '을 붙혀서 반환하도록 설계되어있다.

🌌정리하며

banner.css

.banner {
 color: white;
 object-fit: contain; height: 448px;}
 @media (min-width: 1500px) { .banner {position: relative; height: 600px;}
 .banner--fadeBottom { position: absolute; bottom: 0;width: 100%;
 height: 40rem;
 }
 }
 @media (max-width: 768px) { .banner__contents { width: min-content !important; padding-left: 2.3rem; margin-left: 0px !important; }.banner__description { font-size: 0.8rem !important; width: auto !important; }.info {
 text-align: start; padding-right: 1.2rem; }.space {
 margin-left: 6px; }
 .banner__button { font-size: 0.8rem !important; border-radius: 4px !important; }}
 .banner__contents { margin-left: 40px; padding-top: 140px; height: 190px;}
 .banner__title {
 font-size: 3rem;
 font-weight: 800; padding-bottom: 0.5rem; }.banner__description { width: 45rem;line-height: 1.3; padding-top: 1rem; font-weight: 500; font-size: 1rem;max-width: 400px; height: 80px;}
 .banner--fadeBottom { height: 7.4rem;background-image: linear-gradient(180deg, transparent, rgba(37, 37, 37, 0.61), #111); }.banner__buttons { display: flex;flex-direction: row; }
 .banner__button { display: flex;flex-direction: row; justify-content: start; align-items: center; cursor: pointer;outline: none;
 border: none;
 font-size: 1rem;
 font-weight: 700; border-radius: 0.2vw; padding: 0.4rem 1.8rem 0.4rem 1rem; margin-right: 1rem; }.banner__button:hover { color: #000;background-color: rgba(170, 170, 170, 0.9); transition: all 0.2s; }.play {
 background-color: white; color: black;}
 .info {
 background-color: rgba(109, 109, 110, 0.7); color: white;}
 .info:hover {
 background-color: rgb(74, 74, 74); color: white;}
 .space {
 margin-left: 4px; }
profile
풀스택개발자가되고싶습니다:)

0개의 댓글