[유데미x스나이퍼팩토리] 10주 완성 프로젝트 캠프 22일차 - React 무비앱 만들기 과제

계정봇·2023년 6월 27일
0

스나이퍼팩토리

목록 보기
10/15

과제소개

React와 React-router-dom 그리고 비동기 통신을 사용하여 영화 리스트 앱을 만들어보세요.

React-router-dom

과제에 들어가기 전에 React-router-dom에 대해 간단히 알고 넘거가는게 좋을 것 같다.
일반적으로 HTML, CSS, JS로 작성된 웹 사이트와 다르게 작동한다.
먼저 React는 가상 DOM으로 구현되어 있으며 필요한 부분만 그때그때 DOM을 다시 그리고 만든다.
또 모든 내용이 자바스크립트로만 구현 되어있기 때문에 페이지를 이동하면 모든 페이지를 새로 받아야하는 일반적인 웹 사이트와는 다르게 필요한 부분만 교체할 수 있다.
React-router-dom은 그런 React의 페이지 이동을 편하게 해주는 라이브러리다.

React-router-dom을 사용하는 큰 이유는 React의 가장 큰 장점인 상태관리를 그대로 이어서 할 수 있다는 장점을 가지고 있다.
기본적인 a태그를 사용해서 하는 경우 모든 상태가 날아가기 때문에 리액트에선 치명적으로 작동할 수 있다.
아예 외부 태그로 나가는 경우라면 상관은 없다.

과제 결과


과제 코드

//Home.jsx

import { useEffect, useState } from "react";
import styles from "../styles/Home.module.css";
import MovieList from "../components/MovieList";
const Home = () => {
  const [movies, setMovies] = useState();
  const dataFetch = async () => {
    await fetch(
      `https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&sort_by=year`
    )
      .then((response) => response.json())
      .then((response) => {
        setMovies(response.data);
      });
  };

  useEffect(() => {
    dataFetch();
  }, []);
  return (
    <div className={styles}>
      <MovieList data={movies} />
    </div>
  );
};

export default Home;

가장 먼저 화면에 출력되는 홈 화면이다.
이곳에서 영화 리스트를 받고 자식 컴포넌트에 데이터들을 넘겨준다.

// 

import styles from "../styles/MovieList.module.css";
import { useNavigate } from "react-router-dom";

const MovieList = (props) => {
  console.log(props.data);
  const navigate = useNavigate();

  return (
    <div className={styles.movieList}>
      <div className={styles.totalMovieCount}>
        {props.data && props.data.movie_count}개의 영화
      </div>
      <ul>
        {props.data &&
          props.data.movies.map((e) => (
            <li key={e.id}>
              <button
                onClick={() => {
                  navigate("/movie", {
                    state: { ...e },
                  });
                }}
              >
                <img src={e.medium_cover_image} alt="영화 썸네일" />
                <div className={styles.movieInfo}>
                  <h3 className={styles.singleLine}>
                    {e.title} ({e.title_english})
                  </h3>
                  <div className={styles.score}>
                    <p>평점 {e.rating}</p>
                    <p className="year">({e.year})</p>
                  </div>
                  <p className={styles.genres}>
                    {Object.keys(e.genres).map((elements, i) => (
                      <div key={i}>{e.genres[elements]}</div>
                    ))}
                  </p>
                </div>
              </button>
            </li>
          ))}
      </ul>
    </div>
  );
};

export default MovieList;

무비 리스트에선 받은 데이터들을 map을 사용하여 화면에 리스트로 출력해준다.
이곳에서 원하는 목록 중 하나 선택하여 상세페이지로 이동하도록 한다.
목록을 받아올때 상세페이지에 필요한 정보들이 다 들어있기 때문에 navigate를 사용하고 state에 집어넣어서 이동 했을 때도 계속 활용할 수 있도록 하였다.

import { useLocation } from "react-router-dom";
import styles from "../styles/MovieDetail.module.css";
import StarRating from "../components/StarRating";

const MovieDetail = () => {
  const data = useLocation().state;
  console.log(data);
  return (
    <div className={styles.detailContentWrapper}>
      <div className={styles.backgroundOverlay}>
        <div className={styles.backgroundImage}>
          <img
            className={styles.background}
            src={data.background_image_original}
            alt="배경화면 이미지"
          ></img>
        </div>
      </div>
      <div className={styles.contentWrapper}>
        <img
          src={data.large_cover_image}
          alt="영화 포스터"
          className={styles.images}
        ></img>
        <div className={styles.detailInfo}>
          <h2>
            제목: {data.title_long} {data.title_english}
          </h2>
          <div className={`${styles.severalLines} ${styles.moviePlot}`}>줄거리: {data.description_full}</div>
          <div className={styles.ratingScore}>
            평점: <StarRating rating={data.rating} />
          </div>
          <div>언어: {data.language}</div>
          <div>
            장르{" "}
            {Object.keys(data.genres).map((elements, i) => (
              <span key={i}>{data.genres[elements]} </span>
            ))}
          </div>
          <a
            href={`https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=${data.title}`}
          >
            네이버에 이 영화 검색하러 가기
          </a>
        </div>
      </div>
    </div>
  );
};

export default MovieDetail;

영화 상세보기 페이지에서는 방금 이동하기 전에 받아온 데이터들을 가지고 화면에 출력하도록 하였으며 추가적으로 네이버에 영화에 대한 것들을 검색할 수 있도록 하였다.

과제 후기

이번 과제는 리액트로 간단하게 router를 사용하여 페이지 전환하고 api 통신을 하는 정도로 끝냈다.
간단하지만 나름대로 리액트의 핵심이 담긴 프로젝트 아니었을까 싶다.


본 후기는 유데미-스나이퍼팩토리 10주 완성 프로젝트캠프 학습 일지 후기로 작성 되었습니다.

#프로젝트캠프 #프로젝트캠프후기 #유데미 #스나이퍼팩토리 #웅진씽크빅 #인사이드아웃 #IT개발캠프 #개발자부트캠프 #리액트 #react #부트캠프 #리액트캠프

profile
난 코드를 작성할땐 언제나 최선을 다한다. 그게 비록 console.log 일지라도 말이야.

0개의 댓글