Javascript/React

Movie App 배포 및 라우팅

leeeee.yeon 2021. 7. 25. 22:32
배포

 

npm install -s gh-pages

우선 gh-pages를 설치하자.

gh-pages는 웹사이트를 깃허브의 도메인에 나타나도록 해준다.

도메인의 형식은 (사용자 이름).github.io/(프로젝트 이름)이다. 기억이 나지 않는다면 'git remote -v'로 확인할 수 있다.

나의 경우는 https://leeeeeyeon.github.io/yeonmovie_frontend/이다.

 

그 다음에 package.json에 들어가 맨 아래 코드를 추가해주자.

,
  "homepage": "https://leeeeeyeon.github.io/yeonmovie_frontend"

 

그리고 'npm run build' 명령어를 통해 build 폴더를 만들어주었다.

 

이름은 다르지만, css&js 폴더에 있는 코드들이 우리가 코딩한 코드들이다.

 

scripts 부분에 들어가 deploy를 추가해주자.

,
    "deploy": "gh-pages -d build",
    "predeploy": "npm run build"

** build 폴더의 이름과 deploy의 -d 뒤에 이름이 같아야 한다!

 

predeploy는 deploy 전에 호출되어 build를 한다.

deploy는 gh-pages를 호출하여 build 폴더를 업로드한다.

 

이제 'npm run deploy'를 하여 배포를 마무리해보자.

https://leeeeeyeon.github.io/yeonmovie_frontend/ 쨔잔~!~!

 

만약 수정사항이 생기면 'npm run deploy, npm run build'를 하여 업데이트를 해주자.

 

 

라우팅

 

react-router dom을 이용하여 라우팅을 해줄 것이다.

npm install -s react-router-dom

 

그리고 라우팅을 위해 우리의 디렉토리 구조를 바꿔보자. src 폴더를 아래와 같이 구성하였다.

그리고 App.js의 내용을 Home.js로 옮기고, 웹사이트에 에러가 나지 않게 파일들의 경로를 바꿔주고, index.js에서 App > Home으로 바꾸는 등 세세한 수정을 해주었다.

 

그리고 App.js에는 함수형 컴포넌트를 만들어 App.js에서 라우팅을 할 것이다.

import React from "react";
import { HashRouter, Route } from "react-router-dom";
import Home from "./routes/Home";
import About from "./routes/About";

function App(){
  return(
    <HashRouter>
      <Route path="/" component={Home}/> 
      <Route path="/about" component={About}/>
    </HashRouter>
  );
}

export default App;
  • react-router-dom에는 여러 router이 있는데, 그 중 HashRouter을 사용하고 Route도 함께 import 해주었다.
  • Router에는 중요한 두 가지 props가 있다. 하나는 어디로 랜더링할지(path), 또 하나는무엇을 랜더링 할지(component)이다.
  • import { Home as mySweetHome } 이런 방식으로 이름을 다르게 할 수도 있다는 것을 알아두자.

하지만 ! 이렇게 코드를 짜면 /와 /about이 '/'이 공통되어 /about에 들어갔을 때 두 개의 컴포넌트가 중복되는 문제가 발생한다. 이를 해결하기 위해 exact={true} 속성을 추가하자.

import React from "react";
import { HashRouter, Route } from "react-router-dom";
import Home from "./routes/Home";
import About from "./routes/About";

function App(){
  return(
    <HashRouter>
      <Route path="/" exact={true} component={Home}/> 
      <Route path="/about" component={About}/>
    </HashRouter>
  );
}

export default App;

컴포넌트 중복 문제 해결

 

내비게이션

 

이제 Home과 About에 대한 내비게이션을 만들자.

 

< App.js >

import React from "react";
import { HashRouter, Route } from "react-router-dom";
import Home from "./routes/Home";
import About from "./routes/About";
import Navigation from './components/Navigation';

function App(){
  return(
    <HashRouter>
      <Navigation />
      <Route path="/" exact={true} component={Home}/> 
      <Route path="/about" component={About}/>
    </HashRouter>
  );
}

 

< Navigation.js >

import React from "react";

function Navigation(){
    return (
        <div>
            <a href="/">Home</a>
            <a href="/about">About</a>
        </div>
    );
}

export default Navigation;

 

하지만 이렇게 하면 링크를 클릭할 때마다 리액트가 죽고, 새로고침이 된다.

이를 해결하기 위해 react-router-dom의 Link를 사용하자.

< Navigation.js >

import React from "react";
import { Link } from "react-router-dom";

function Navigation(){
    return (
        <div>
            <Link to="/">Home</Link>
            <Link to="/about">About</Link>
        </div>
    );
}

export default Navigation;

** Link는 Router(우리의 앱에서는 HashRouter) 밖에서 쓸 수 없다 !! Navigation 컴포넌트가 Router 밖에 있으면 안된다.

 

+ Link가 html로 갈 때 a 태그로 바뀌어 들어가니까 css를 할 때는 a 태그로 진행하면 된다.

+ 니꼬 쌤의 Navigation.css: https://github.com/nomadcoders/movie_app_2019/commit/3ebfa6c16dd4ad07d1d58772cfb0ad08a958ec1e

 

그리고 라우터를 HashRouter에서 BrowserRouter로 바꾸면 '#'이 붙지 않아 깔끔하다.

하지만 BrowserRouter로 하면 gh-pages 설정이 번거로워진다...

BrowserRouter 사용 시,

https://medium.com/@_diana_lee/react-react-router-%EC%A0%81%EC%9A%A9%ED%95%9C-react-%EC%95%B1%EC%9D%84-github-pages%EB%A1%9C-%EB%B0%B0%ED%8F%AC%ED%95%98%EB%8A%94-%EB%B2%95-5f6119c6a5d9 를 참고하자.

 

나는 BrowserRouter을 택했다.

 

 

라우트 간의 props 공유

 

이번에는 영화 박스를 클릭했을 때, 영화에 대한 상세정보를 띄우도록 할 것이다.

그렇기 위해서는 route 간의 props 공유가 필요하다.

 

About에 대한 Link 태그를 아래와 같이 수정해보자.

<Link to={{
  pathname: "/about",
  state: {
    fromNavigation: true
  }
}}>About</Link>

그리고 About.js을 아래와 같이 수정하면,

import React from "react";
import "./About.css";

function About(props){
    console.log(props);
    return (
        <div className="about__container">
            <span>
                "Hi"
            </span>
            <span>- leeeeeyeon, 2021</span>
        </div>
    );
}

export default About;

state가 전달되는 것을 볼 수 있다.

 

이를 활용하여 Movie.js를 아래와 같이 바꾸자.

function Movie({year, title, summary, poster, genres}){
    return (
        <Link to={{
            pathname: "/movie-detail",
            state: {
                year,
                title,
                summary,
                poster,
                genres
            }
        }}>
            <div className="movie">
                <img src={poster} alt={title} title={title} />
                <div className="movie_data">
                    <h3 className="movie_title">{title}</h3>
                    <ul className="movie__genres">
                        {genres.map((genre, index) =>
                            <li key={index} className="genres_genre">{genre}</li>
                        )}
                    </ul>
                    <h5 className="movie_year">{year}</h5>
                    <p className="summary">{summary.slice(0, 180)} ...</p>
                </div>
            </div>
        </Link>
    );
}

 

영화 박스를 클릭할 때 해당 영화에 대한 state가 전달되는 것을 볼 수 있다.

 

 

리다이렉트

 

state를 사용하기 위해 Detail.js를 class 컴포넌트로 바꿔주자.

import React from "react";

class Detail extends React.Component{
    componentDidMount(){
        const {location} = this.props;
    }
    render(){
        return (
            <span>Hello</span>
        );
    }
}

export default Detail;

 

근데 만약 우리가 영화 박스를 클릭하지 않고 그냥 /movie-detail로 들어갔을 시 undefined 객체가 뜬다.

props 중 history의 push를 이용하여 undefined일 시 (= 링크로 접속) 홈으로 리다이렉트하도록 하자.

import React from "react";

class Detail extends React.Component{
    componentDidMount(){
        const {location, history} = this.props;
        if(location.state === undefined){
            history.push("/");
        }
    }
    render(){
        return (
            <span>Hello</span>
        );
    }
}

export default Detail;

 

그리고 movie-detail의 URL을 더 예쁘게 하기 위해

App.js에서는,

<Route path="/movie/:id" component={Detail}/>

Movie.js에서는,

 

이렇게 바꿔주었다.

그러면 URL이 아래와 같이 바뀐 것을 확인할 수 있다.

 

 

노마드 코더 리액트 끗 ~~!~!~