06. 구조의 등장, Router

Gardener·2024년 1월 15일
0

ReactStudy

목록 보기
7/7
post-thumbnail

저번에는 단위 변환과 관련된 코드를 클론코딩하며 따라쳐보는 시간을 가졌다면, 오늘 부터는 영화에 대한 목록을 만드는 시간이다.

이전까지의 React 실습시간에서는 App.js에서 모든 화면을 구성하도록 처리했지만, 그렇다. 이제 드디어 프론트의 꽃 구조화 (개인적인 내 생각, 사실 Vue 했을 때도 구조화가 제일 재밌었음) 의 시간이 온 것이다.

Router
: 라우터를 사용하면 단일 페이지 애플리케이션(SPA)에서 사용자가 다른 URL로 이동할 때 페이지를 새로고침하지 않고도 콘텐츠를 동적으로 렌더링할 수 있다.

import React from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Home from "./routes/Home";
import Detail from "./routes/Detail";

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/movie/:id" element={<Detail />} />
        <Route path="/" element={<Home />} />
      </Routes>
    </Router>
  );
}

export default App;

먼저 Router를 사용하여 변화된 App.js 창의 모습이다. 기존에 이 페이지에 모든 정보를 다 입력했다면 Component화 시키고, 직관적으로 이 부분에 어떤 페이지가 들어오는지 보여주게 된다.

import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
  1. BrowserRouter 는 Router를 HTML5 히스토리 API (pushState, replaceState, 그리고 popstate 이벤트)를 사용하여 URL과 UI를 동기화하는 라우터 구현체이다. 이것 말고도, HashRouter가 있긴한데, 직관적이지 않더라.
  2. Routes는 현재 위치와 일치하는 첫 번째 라우트를 렌더링하는 React 컴포넌트이다.
  3. Route는 위 2번의 경로가 현재 URL과 일치할 때 UI의 일부를 렌더링하는 컴포넌트라고 이해하면 좋을 듯.

아래 사진과 같이 components, routes로 폴더를 나누어 해당하는 부분을 구현했다. 라고 생각하면 좋을 듯. (이전에는 App.js에 한꺼번에 다 박았음.) 조금 더 자세히 볼 것은 Home과 Movie이다.

Home에서는 2가지를 설명해야한다.

1. async / await

...
  const getMovies = async () => {
    const json = await (
      await fetch(
        `https://yts.mx/api/v2/list_movies.json?minimum_rating=8.5&sort_by=year`
      )
    ).json();

  useEffect(() => {
    getMovies();
  }, []);
    
  1. async 함수 정의: async 키워드는 함수가 비동기적인 동작을 수행한다는 것을 의미합니다. async 함수는 항상 Promise를 반환한다.

  2. 첫 번째 await 사용: fetch 함수는 네트워크 요청을 보내고 응답을 받기까지 시간이 걸린다. fetch는 Promise를 반환하며, 이 Promise는 네트워크 응답이 완료되었을 때 해결된다. await 키워드는 fetch 함수가 완료될 때까지 코드 실행을 잠시 멈추고, 네트워크 응답이 완료되면 계속 진행하게 한다.

  3. 두 번째 await 사용: fetch의 결과는 Response 객체다. 이 객체의 .json() 메서드는 응답 본문을 JSON 형식으로 변환하는 작업을 수행한다. 이 메서드 또한 Promise를 반환하므로, 여기에도 await를 사용하여 JSON 변환 작업이 완료될 때까지 기다린다.

  4. 결과 처리: JSON으로 변환된 데이터는 json 변수에 저장되며, 이후 console.log(json)을 통해 콘솔에 출력된다.

2. 분리된 파일에서 props로 요소 전달하기

// Home.js
import Movie from "../components/Movie"

 return (
   <div>
     {loading ? (
       <h1>Loading... </h1>
     ) : (
       <div>
         {movies.map((movie) => (
           <Movie
             key={movie.id}
             id={movie.id}
             coverImg={movie.medium_cover_image}
             title={movie.title}
             summary={movie.summary}
             genres={movie.genres}
           />
         ))}
       </div>
     )}
   </div>
 );

Home.js에서 movies.map 안에 movie를 담아 Movie 컴포넌트에 아래와 같은 값 (key,id,coverImg...) 들을 담아서 전달한다.

//Movie.js
import PropTypes from "prop-types";
import { Link } from "react-router-dom";

function Movie({ id,coverImg, title, summary, genres }) {
return (
 <div>
   <img src={coverImg} alt={title} />
   <h2>
     <Link to={`/movie/${id}`}> {title}</Link>
   </h2>
   <p>{summary}</p>
   <ul>
     {genres.map((g) => (
       <li key={g}>{g}</li>
     ))}
   </ul>
 </div>
);
}

Movie.propTypes = {
id : PropTypes.number.isRequired,
coverImg: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
summary: PropTypes.string.isRequired,
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
};

export default Movie;

props 받아온 정보들 (id, coverImg 등등..)을 function함수에 넣어놓고, 자유롭게 사용할 수 있다.
또한 PropTypes를 통해, 자료형을 미리 설정해놓고, 사용할 수 있다.

마치며,

겪었던 시행착오
: react-router-dom과 react app의 버젼차이 때문에 Router, Link가 올바르게 연결되지 않았던 문제가 있었다.

function App() {
  return <Router>
    <Switch>
      <Route path="/movie">
        <Detail/>
      </Route>
      <Route path="/">
        <Home/>
      </Route>
    </Switch>      
  </Router>
}
function App() {
  return (
    <Router>
      <Routes>
        <Route path="/movie/:id" element={<Detail />} />
        <Route path="/" element={<Home />} />
      </Routes>
    </Router>
  );
}

클론코딩하고 있던 강의는 react-router-dom v5의 설정을 따라하고 있었는데, 나의 경우 react-router-dom v6을 사용하고 있었다.

(현재 나의 react-router-dom의 버젼을 확인하는 방법은 pacakage.json 파일에서 확인 가능하다.)

그렇기에 기존의 스위치 태그로 화면을 전환 하는것이 아닌 Route 태그 안에서 모든 것을 처리하게 변했다. 훨씬 더 간단하게 보여지기 때문인 듯. 위에서 아래로 라우터의 구조가 바뀌었다고 생각하면 편할 듯.

이제 기본적인 인강을 통한 클론 코딩은 마무리 되었다. 다른 지식으로 찾아올 예정.

profile
영혼의 정원수

0개의 댓글