[노마드코더] ReatJS 웹서비스 만들기

13 minute read

#0 INTRODUCTION

#0.1 Requirements

  • node, npm, npx 설치확인
  • VSC(Visual Studio Code)
  • git

#0.2 Theory Requirements

html, css, 바닐라JS

const, let, function, argument,

#0.3 Why React

리액트를 사용하기위해 별도로 프레임워크 지식을 배워야하는 것이 아니기 때문에 자바스크립트 지식만 안다면 사용할 수 있다. 앵귤러는 앵귤러 프레임워크를 사용하기위해 앵귤러를 배워야한다.

#1.0 Creating your first React App

React로 만든 코드를 브라우저가 이해하지 못하기 때문에 이 코드를 변환해줘야 한다.

이런 설정을 하기 위해 몇가지 단계가 필요하다. Webpack을 다운로드 해야하고 Babel을 다운로드 해야한다.

그리고 React코드를 Compile 하고, 다른 파일에 넣어야하고….. 등등등

create-react-app을 이용해서 이러한 과정을 할필요가 없어졌다.

기본적으로 하나의 명령을 실행해서 React Web App을 Set up할 수 있게 해준다.

[github] create-react-app

  1. create-react-app 으로 프로젝트 생성
npx create-react-app 프로젝트폴더명지정
  1. VScode로 프로젝트 열기
code 프로젝트폴더명

※ Visual Studio Code 터미널에서 실행하기

Visual Studio Code 를 켠다.
Command Palette 를 연다. [⇧⌘P ]
Shell Command 를 입력해 [ Shell Command: Install ‘code’ command in PATH command ] 를 실행한다.
터미널에서 원하는 [ code . ] 으로 실행이 가능

package.json

우리가 신경써야할 두가지 항목

  • "start": "react-scripts start"

  • "build": "react-scripts build"

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },

yarn.lock

기본적으로 따라오는 파일

(우리는 현재 쓰지 않으므로 삭제)

  1. 애플리케이션 실행
npm start

접속 주소 확인 가능

npm start

웹서버


#1 SETUP

#1.1 Creating a Github Repository

Github에 프로젝트명과 동일한 Repository생성 후 연동

git init #git 저장소 초기화
git remote add origin https://github.com/blossun/movie_app #원격 저장소 연결

커밋 후 업로드

git add .                                                 
git commit -m "#1.0 Creating your first React App"
git push origin master

#1.2 How does React work?

src 디렉토리에 App.jsindex.js 만 남겨두고 삭제

import React from 'react';

function App() {
  return (
    <div> Hello!!! </div>
  );
}

export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

index.js에는 “Hello!!!”라는 문자열이 없지만 브라우저에서 소스코드보기 개발자도구 보기를 하면 다음과 같이 만들어져 있다.

( * 소스코드에는 어느 부분에도 “Hello!!!”라는 문자열이 없다. )

<div id="root"><div> Hello!!! </div></div>

react는 우리가 쓰는 모든 요소를 생성한다는 것이다. 자바스크립트와 함께 만들어서 HTML에 넣는 것이다.

React는 이곳(xxxxx)에 element를 넣는 역할을 담당한다.

<div id="root"><div> xxxxx </div></div>

ReactDOM.render()에서 그 역할을 해준다.

  • <App />import App from './App'; 을 랜더링한다.
  • document.getElementById('root') → Element의 Id 값이 ‘root’인 부분에

⇒ app.js component를 ElementById 내부에 넣어준다.

소스코드에는 어느 부분에도 “Hello!!!”라는 문자열이 없다. 소스코드에서 우리가 보는 것은 기본적으로 빈 index.js 파일이다.

이게 바로 react를 빠르게하는 이유이다.

react는 소스코드에 처음부터 HTML을 넣지 않고, HTML에서 HTML을 추가하거나 제거하는 법을 알고 있다.

그래서 애플리케이션을 실행하면 빈 HTML을 로드한 다음에 react가 우리가 component에 작성했던 것들을 HTML에 밀어넣게 된다.

※ virtual DOM (virtual document object model)

virtual : “존재하지 않는다.”, 소스코드에 존재하지 않는다는 의미

react 가 만들어낸다.


#2.0 Creating your first React Component

index.js 의 코드를 보자.

<App /> 는 HTML 코드가 아니다. 기본적으로 이것을 component라고 부른다.

react는 component와 함께 동작한다. 모든 것은 component이다. 우리는 component를 만들고 component가 data를 보여주게 할 것이다.

ReactDOM.render(<App />, document.getElementById('root'));
※ Component 란?
  • HTML을 반환하는 함수

  • 대문자로 시작

    function App() {
      return (
        <div> <h3>하하하하</h3></div>
      );
    }
    
※ JSX
  • react는 component를 사용해서 HTML처럼 작성하려는 경우에 필요하다.
  • javascript와 HTML 사이의 조합을 jsx라고 한다.
  • react에서 나온 custom한 유일한 개념이다. (나머지 개념은 모두 Javascript)
  1. Component를 생성해보자
  • component를 작성할 때마다 추가해야함. 그래야 react가 jsx가 있는 component를 사용하는 것을 이해한다.

    import React from 'react';
    
import React from 'react'; //component를 작성할 때마다 추가해야함.

function Potato() {
    return (
        <h3>I love potato</h3>
    )
}

export default Potato;
  1. 생성한 Component를 사용해보자

잘못된 사용방식 - react application이 하나의 component만을 rendering해야하기 때문이다.

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import Potato from './Potato';

ReactDOM.render(
    <App /><Potato />,
  document.getElementById('root')
);

Potato 컴포넌트를 App 컴포넌트 내에 존재하도록 수정

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
    <App />,
  document.getElementById('root')
);
import React from 'react';
import Potato from "./Potato";

function App() {
  return (
    <div>
      <h3>하하하하</h3>
    <Potato /> //<-- 여기에 넣어줌
    </div>
  );
}

export default App;
import React from 'react'; //component를 작성할 때마다 추가해야함.

function Potato() {
    return (
        <h3>I love potato</h3>
    )
}

export default Potato;

결론

  • react application은 한 번에 하나의 component만 rendering할 수 있다.
  • 따라서 모든 것은 application 안에 들어가야한다.
  • application 안에 많은 component를 넣을 수 있다.

#2 JSX & PROPS

#2.1 Reusable Components with JSX + Props

같은 파일 내에서 컴포넌트 생성 및 사용

import React from 'react';

function Potato() {
  return <h1>I like Potato</h1>;
}

function App() {
  return (
    <div>
      <h3>하하하하</h3>
    <Potato />
    </div>
  );
}

export default App;

※ props(property)
  • component에 정보를 보낼 수 있다.

  • component를 재사용한다.

  • component에서 component(children component)로 정보를 보내는 방법

application에서 food component로 정보를 보내고, 그 후 food component에서 그 정보를 어떻게 사용하는지에 대해 배워보자

Food 컴포넌트에 “fav”라는 이름의 prop(property)를 “kimchi”라는 value로 준 것

<Food fav="kimchi" />

react는 우리가 전달한 props를 가져가서 일을 처리한다.

father component에서 children component로 원하는 많은 props를 보낼 수 있다.

<Food 
fav="kimchi" 
somethine={true}
papapa={["hello", 1, 2, 3, 4, true]}
/> 

food function component의 argument에 담아서 받는다.

function Food(props) {
  console.log(props);
  return <h1>I like Potato</h1>;
}

콘솔창에 component로 전달된 모든 props를 확인할 수 있다.

다음과 같이 특정 prop를 꺼내서 사용하거나 받을 수 있다.

function Food(props) {
  console.log(props.fav);
  return <h1>I like {props.fav}</h1>;
}
function Food({fav}) {
  console.log(fav);
  return <h1>I like {fav}</h1>;
}

여러번 호출

import React from 'react';

function Food(props) {
  console.log(props.fav);
  return <h1>I like {props.fav}</h1>;
}

function App() {
  return (
    <div>
      <h3>하하하하</h3>
      <Food fav="kimchi"/>
      <Food fav="ramen"/>
      <Food fav="cheeze"/>
      <Food fav="pasta"/> 
    </div>
  );
}

export default App;

#2.2 Dynamic Component Generation

웹사이트에 동적 데이터 추가

(API로 부터 데이터를 전달받았다고 가정)

javascript로만 object의 list를 가져옴

  • map()
  • 함수내에 각 item에 대해 실행되는 function을 정해준다.
  • array에 대해 우리가 정의한 함수를 실행한 결과로 array를 반환한다.

순수 javascript의 map을 이용해서 컴포넌트에 값을 전달해보자

import React from 'react';

function Food({name, picture}) {
  console.log(name, picture);
  return <div>
      <h1>I like {name}</h1>
      <img src={picture} />
    </div>
}

const foodILike = [{
  name: "Kimchi",
  image:
    "http://aeriskitchen.com/wp-content/uploads/2008/09/kimchi_bokkeumbap_02-.jpg"
},
{
  name: "Samgyeopsal",
  image:
    "https://3.bp.blogspot.com/-hKwIBxIVcQw/WfsewX3fhJI/AAAAAAAAALk/yHxnxFXcfx4ZKSfHS_RQNKjw3bAC03AnACLcBGAs/s400/DSC07624.jpg"
},
{
  name: "Bibimbap",
  image:
    "http://cdn-image.myrecipes.com/sites/default/files/styles/4_3_horizontal_-_1200x900/public/image/recipes/ck/12/03/bibimbop-ck-x.jpg?itok=RoXlp6Xb"
},
{
  name: "Doncasu",
  image:
    "https://s3-media3.fl.yelpcdn.com/bphoto/7F9eTTQ_yxaWIRytAu5feA/ls.jpg"
},
{
  name: "Kimbap",
  image:
    "http://cdn2.koreanbapsang.com/wp-content/uploads/2012/05/DSC_1238r-e1454170512295.jpg"
}];

function App() {
  return (
    <div>
      {foodILike.map(dish => <Food name={dish.name} picture={dish.image}/>)}
    </div>
  );
}

export default App;

  • dish 는 현재 Object를 의미한다. Food 컴포넌트에 현재 Object에 있는 name, image 2개의 prop중에 name을 선택해서 넘겨주고 있다.

    {foodILike.map(dish => <Food name={dish.name} picture={dish.image}/>)}
    
  • 이 요소하나하나가 Object이다.

    {
      name: "Kimchi",
      image:
        "http://aeriskitchen.com/wp-content/uploads/2008/09/kimchi_bokkeumbap_02-.jpg"
    }
    

#2.3 map Recap

함수로 추출해서 사용할 수 있다만 보고 넘어감

function renderFood(dish) {
  console.log(dish);
  return <Food name={dish.name} picture={dish.image} />
}

function App() {
  return (
    <div>
    	{console.log(foodILike.map(renderFood))} //-> 각각의 component
      {foodILike.map(renderFood)}
    </div>
  );
}
  1. 에러메시지 확인

각각 list 내의 child는 unique한 key prop를 가져야 한다.

react의 element는 유일해야한다. 하지만 우리가 list 안으로 집어넣을 때, 유일성을 잃는다.

⇒ 따라서 각 item들에 id값을 부여한다.

(에러해결)

const foodILike = [{
  id: 1,
  name: "Kimchi",
  image:
    "http://aeriskitchen.com/wp-content/uploads/2008/09/kimchi_bokkeumbap_02-.jpg"
},
                   ... 
}];                
                   
function App() {
  return (
    <div>
      {foodILike.map(dish => <Food key={dish.id} name={dish.name} picture={dish.image}/>)}
    </div>
  );
}

“Food 컴포넌트에서 id 값을 사용하진 않지만 기본적으로 react 내부에서 사용하기 위한 값이다.”

  1. img 태그는 alt prop가 반드시 있어야한다.고 코드 스타일 알람이 뜬다.

시각장애인을 위한 정보표시

#2.4 Protection with PropTypes

목표 : father component로 부터 전달받은 props를 체크

  1. foodILike Object에 rating(평점) prop 추가

    const foodILike = [{
      id: 1,
      name: "Kimchi",
      image:
        "http://aeriskitchen.com/wp-content/uploads/2008/09/kimchi_bokkeumbap_02-.jpg",
      rating: 5
    },...];
       
    function Food({ name, picture, rating }) {
      console.log(name, picture, rating);
      return <div>
        <h2>I like {name}</h2>
        <h4>{rating}/5.0</h4>
        <img src={picture} alt={name} />
      </div>
    }
    
  2. prop-types 설치

    npm i prop-types
    

    → 설치확인 : package.json 파일의 dependenciesprop-t]ypes가 있으면 성공

  • prop-types : 내가 전달받은 props가 내가 원하는 props인지를 확인
  1. prop-types 적용

(1) prop-types import

import PropTypes from "prop-types";

(2) 내가 얻고 싶은 props에 대한 설명을 적는다.

Object.propTypes 로 이름을 지어야 react가 인식한다.

Food.propTypes = {
  // 내가 얻고 싶은 props에 대한 설명을 적는다.
  name: PropTypes.string.isRequired,
  picture: PropTypes.string.isRequired,
  rating: PropTypes.string.isRequired
}
  1. prop-types 으로 찾아진 오류 확인

웹브라우저 페이지 상에는 보이지 않지만 콘솔을 확인하면 에러메시지를 던져주고 있다.

→ “rating의 type은 숫자로 제공됐지만 우리는 String을 기대한다.”

⇒ rating의 요구되는 타입을 number로 수정하면 에러코드 삭제됨

Food.propTypes = {
  // 내가 얻고 싶은 props에 대한 설명을 적는다.
  name: PropTypes.string.isRequired,
  picture: PropTypes.string.isRequired,
  rating: PropTypes.number //<-- numbertype OR undefined
}

PropTypes와 함께 하는 타입 확인


#3 STATE

state는 보통 우리가 동적 데이터와 함께 작업할 때 만들어진다.

  • dynamic data

    변하는 데이터, 존재하지 않는 데이터, 생기고 사라지거나 변경된 데이터, 하나 또는 두개가 되고 0이 되는 종류의 데이터

  1. Function component를 Class component로 변경
  • React.Component 를 상속받아서 render 메서드 구현
import React from 'react';
import PropTypes from "prop-types";

class App extends React.Component { //class component
  render() {
    return <h1>Im a class component</h1>
  }
}
export default App;

  • react는 자동적으로 모든 class component의 render method를 실행한다.

  • state는 object이고 component의 data를 넣을 공간이다. 그리고 이 state 값은 변경된다.

import React from 'react';
import PropTypes from "prop-types";

class App extends React.Component { //class component
  state = {
    count : 0
  }
  render() {
    return <h1>This number is : {this.state.count}</h1>
  }
}
export default App;

ES6 Javascript 코드 문법이다.

add = () => {};
minus = () => {};

react에서는 자동적으로 주어진 onClick이 있다.

import React from 'react';
import PropTypes from "prop-types";

class App extends React.Component { //class component
  state = {
    count : 0
  }
  add = () => {
    console.log("add");
  };
  minus = () => {
    console.log("minus");
  };
  render() {
    return (
      <div>
        <h1>This number is : {this.state.count}</h1>
        <button onClick={this.add}>Add</button>
        <button onClick={this.minus}>Minus</button>
      </div>
    )
  }
}
export default App;

#3.1 All you need to know about State

“절대 state를 직접 변경하지 마세요”

잘못된 코드 )

  • state가 동작하지 않는다. 에러메시지에 setState()를 쓰라고 나온다.
  • why? react는 render function을 refresh하지 않기 때문이다.
  add = () => {
    this.state.count = 1;
  };

⇒ 우리가 setState()를 호출하면, react는 우리가 언제 setState()를 호출할지를 알고, 내가 view를 refresh하길 원하는 것을 알기 때문에 render function을 재호출해준다.

  • react는 새로운 state와 함께 render function을 호출한다.
 add = () => {
    this.setState({ count: 1});
  };

⇒ react는 변화가 있는 부분만 업데이트한다.

react는 모든걸 다시 칠하지만 virtual DOM을 가지고있기 때문에 매우 빠르게 변경할 수 있고, 깜밖거리지도 않는다.

권장되지 않는 코드 )

다음 코드와 같이 수정했지만 좋은 코드는 아니다.

why? state에 의존하고 있기 때문에. (추후에 몇가지 성능 문제가 있다.)

import React from 'react';
import PropTypes from "prop-types";

class App extends React.Component { //class component
  state = {
    count : 0
  }
  add = () => {
    this.setState({ count: this.state.count + 1});
  };
  minus = () => {
    this.setState({ count: this.state.count -1});
  };
  render() {
    return (
      <div>
        <h1>This number is : {this.state.count}</h1>
        <button onClick={this.add}>Add</button>
        <button onClick={this.minus}>Minus</button>
      </div>
    )
  }
}
export default App;
  • (react) function방식으로 현재의 state를 가져오는 기능을 제공한다.

권장하는 코드)

state를 set할 때, react에서 외부의 상태에 의존하지않는 가장 좋은 방법이다.

add = () => {
  this.setState(current => ({ count: current.count + 1}));
};

우리는 현재 state를 얻고 싶고, react가 그것을 줄 것이다. 따라서 훨씬 더 나은 새로운 state를 사용할 수 있다.

#3.2 Component Life Cycle

React.Component는 life cycle method를 가지는데, life cycle method는 react가 component를 생성하고 삭제하는 방법이다.

Mounting
  • 생성
  • constructor() : Javascript에서 class를 만들 때 호출
  • component가 mount될 때, component가 screen에 표시될 때, component가 Website에 갈 때, constructor를 호출한다.
  • 그 이후에 render()가 호출된다.
  • component가 render할 때, componentDidMount() 우리에게 알려준다. “이 component는 처음 render됐다.”
Updating
  • 업데이트
  • 컴포넌트가 업데이트 될 때 호출되는 많은 function들이 있다.
  • render()이후 …. componentDidUpdate() 실행
  • (버튼을 클릭하는 등) setState를 호출하면, component를 호출하고, 먼저 render를 호출 → 업데이트가 완료되었다고 말하면 componentDidUpdate가 실행된다.
Unmounting
  • 소멸

  • 어떻게 Component가 죽나?

    다양한 방법이 있다. 페이지 전환, state를 사용해서 component를 교체

  • componentWillUnmount()

#3.3 Planning the Movie Component

페이지가 로딩되면 isLoading은 무조건 true이다.

import React from 'react';

class App extends React.Component { //class component
  state = {
    isLoading: true
  };
	//setTimeout을 입력
	com

  render() {
    const {isLoading} = this.state;
    return <did>{isLoading ? "Loading...": "We ard ready"}</did>;
  }
}
export default App;

퀴즈 ) 처음에 render를 하면 호출되는 life cycle method는 무엇일까?

componentDidMount()

처음 render할 때는 “Loading…“을 찍고, 6초뒤에 “We ard ready”를 출력해보자

class App extends React.Component { //class component
  state = {
    isLoading: true
  };
  // render이후 처음 호출되는 life cycle function
  // 6초후에 isLoading의 값을 false로 변경
  componentDidMount() {
    setTimeout(() => {
      this.setState({isLoading: false})
    }, 6000);
  }

  render() {
    const {isLoading} = this.state;
    return <did>{isLoading ? "Loading...": "We ard ready"}</did>;
  }
}
export default App;

우리가 할 일 : componentDidMount엣서 data를 fetch하는 것

API로 부터 data fetching이 완료되면 “We ard ready”를 출력하는 대신에 movie를 Render하고 map을 만들고 movie를 render하는 것이다.


#4 MAKING THE MOVIE APP

#4.0 Fetching Movies from API

  • fetch 대신 Axios(악시우스) 사용
  • YTS에서 만든 API 사용
Axios
  • fetch위에 있는 작은 layer
  1. Axios 설치
npm install axios

예제소스 - api 링크, movie list api - json 불법사이트라 url이 매번 바뀌기 때문에 nomad coder의 YTS Proxy를 이용하자

API url - https://yts.mx/api/v2/list_movies.json

import React from 'react';
import axios from "axios"; //추가

class App extends React.Component { //class component
  state = {
    isLoading: true,
    movies: []//movie state 생성
  };
  componentDidMount() {
    axios.get("https://yts.mx/api/v2/list_movies.json"); //추가
  }

  render() {
    const {isLoading} = this.state;
    return <did>{isLoading ? "Loading...": "We ard ready"}</did>;
  }
}
export default App;

페이지 reload 후, 네트워크 탭 확인

axios가 요청한 데이터 확인

image-20200721004956545

axios로 요청하여 받아온 데이터를 사용해보자

axios가 느리기 때문에, 우리는 javascript에게 componentDidMount 함수가 끝날 때까지 약간 시간이 걸릴 수 있다고 말해야한다. 그러기 위해서 우리는 componentDidMount앞에 async를 넣는다.

import React from 'react';
import axios from "axios";

class App extends React.Component { //class component
  state = {
    isLoading: true,
    movies: []//movie state 생성
  };
  getMovies = async () => {
    const movies = await axios.get("https://yts-proxy.now.sh/list_movies.json");
  };
  componentDidMount() {
    this.getMovies();
  }

  render() {
    const {isLoading} = this.state;
    return <did>{isLoading ? "Loading...": "We ard ready"}</did>;
  }
}
export default App;

asyncawait

“이 함수가 비동기 함수다. 너는 이걸 기다려야 해”라고 알려주는 것

( ⇒ ES6 수업 참고 )

#4.1 Rendering the Movies

movies 목록을 가져와서 콘솔에 출력

import React from 'react';
import axios from "axios";

class App extends React.Component { //class component
  state = {
    isLoading: true,
    movies: []//movie state 생성
  };
  getMovies = async () => {
    const movies = await axios.get("https://yts-proxy.now.sh/list_movies.json");
    console.log(movies.data.data.movies); //object구조에 따라 data내의 data내의 movies 목록을 가져옴
  };
  componentDidMount() {
    this.getMovies();
  }

  render() {
    const {isLoading} = this.state;
    return <did>{isLoading ? "Loading...": "We ard ready"}</did>;
  }
}
export default App;

⇒ ES6 문법에 따라 다음과 같이 줄일 수 있다.

  getMovies = async () => {
    const {data: {data: {movies}}} = await axios.get("https://yts-proxy.now.sh/list_movies.json");
    console.log(movies); //object구조에 따라 data내의 data내의 movies 목록을 가져옴
  };

가져온 movies 목록을 state의 movies 배열에 넣어준다.

//앞의 movies는 state의 movies이고, 뒤의 movies는 axios로 부터 받아온 movies이다.
this.setState({movies:movies})
this.setState({movies}) //위와 동일. 단축해서 쓸 수 있다.

Loading의 상태도 변경해준다.

this.setState({movies, isLoading: false}) //위와 동일. 단축해서 쓸 수 있다.

movies 를 랜더링

Movie.js는 state(상태)가 필요없기 때문에 function component로 만든다.

중요한 건 우리가 얻어 올 props를 찾기 시작하는 것이다.

import React from "react";
import PropTypes from "prop-types";

function Movie({id, year, title, summary, poster}) { // props로 바로 받는게 아니라 그 안의 값을 받는 것이므로 {}로 한번 더 묶어줘야 한다.
    return <h5>{title}</h5>;
}

Movie.propTypes = {
    id: PropTypes.number.isRequired,
    year: PropTypes.number.isRequired,
    title: PropTypes.string.isRequired,
    summary: PropTypes.string.isRequired,
    poster: PropTypes.string.isRequired
};

export default Movie;
  render() {
    const {isLoading, movies} = this.state;
    return (
      <div>
        {isLoading 
          ? "Loading..."
          : movies.map(movie => {
            console.log(movie);
           return <Movie 
              key={movie.key} //child는 유일한 key값을 가지고 있어야한다. react가 식별하기 위한
              id={movie.id} 
              year={movie.year} 
              title={movie.title} 
              summary={movie.summary} 
              poster={movie.medium_cover_image} 
            />
          })}
      </div>
    );
  }

#4.2 Styling the Movies

방법1) 태그에 style 속성지정

<h3 class="movie__title" style=>{title}</h3>

방법2) css 파일생성

모든 component에 대한 css파일을 만들 수 있고, 하나의 css파일에 모든 설정을 넣을 수도 있다.

#4.3 Adding Genres

⇒ 유효하지 않은 DOM property class

HTML처럼 보이지만 이건 JSX, javascript 이기 때문이다. 우리는 class가 아니라 className이라고 써야한다.

  render() {
    const {isLoading, movies} = this.state;
    return (
      <section class="container">
        {isLoading ? (
          <div class="loader">
            <span class="loader__text">Loading...</span>
          </div>
        ) : (
          <div class="movies">
            {movies.map(movie => (
            <Movie 
              key={movie.key} //child는 유일한 key값을 가지고 있어야한다. react가 식별하기 위한
              id={movie.id} 
              year={movie.year} 
              title={movie.title} 
              summary={movie.summary} 
              poster={movie.medium_cover_image}
              genres={movie.genres}
            />
            ))}
      </div>
    )}
    </section>
    );
  }

#5.0 Deploying to Github Pages

  1. gh-pages 설치
  • github에 업로드하는 것을 허가해주는 모듈

  • gh-pages : 웹사이트를 github의 github page 도메인에 나타나게 해준다.
  • github에서 무료 웹사이트를 제공해준다.
npm -i gh-pages
  1. package.json 설정
  • homepage추가
"homepage": "http://blossun.github.io/movie_app"
  • git remote -v으로 username, project명 확인
https://{you github username}.github.io/{the name of your project in github}
  1. deploy scripts 작성

gh-pages 호출해서 우리의 빌드된 폴더를 업로드

  • 빌드 경로 확인
npm run build

→ build 디렉토리가 생성된다.

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "deploy": "gh-pages -d build", //<-- build 경로와 함께 depoly 추가. build 폴더를 업로드
  	"predeploy": "npm run build"
  }

매 순간 우리가 deploy를 호출할 때마다 predeploy를 호출한다.

predploy로 build를 실행하고, build에서 build를 위한 스크립트를 실행한다. 그리고 생성된 build를 deploy(배포)한다.

  1. deploy 실행
npm run deploy