본문 바로가기

잡부생활/프로그래밍

리액트 기초 강좌 시작하기(Getting Started with React - An Overview and Walkthrough Tutorial

[너무 헷갈리는 React 기본을 정리할 겸, 개(dog)발 번역]

https://www.taniarascia.com/getting-started-with-react/

 

Getting Started with React - An Overview and Walkthrough Tutorial

I've been hearing about React since I first started learning JavaScript, but I'll admit I took one look at it and it scared me. I saw what…

www.taniarascia.com

나는 JavaScript를 시작한 이래로 쭉 React에 대해 들어왔다. 그러나 처음 React를 본 순간 당황했다. 

HTML에 JavaScript가 섞여있는 끔찍한 혼종 문법을 보고 놀란 뒤 다신 쳐다도 보지 않았다.

 

대신 Vanilla JavaScript와 jQuery에 집중했다.

React를 시작하는데 어려움에 좌절감을 느꼈고, 마침내 vanilla JS 또는 jQuery 대신에 왜 React를 써야 하는지 이해되기 시작했다.

 

그리고 그 동안 배웠던 것들과 좋은 정보를 님들에게 공유하려고 글을 쓴다.

 

 

[글 읽기 전 전제 조건]

React를 시작 전에 몇 가지 전제 조건이 있다. 만약 당신이 JavaScript와 DOM에 대해서 모른다면 뒤로 가기를 눌러라.

  • 기본적인 HTML & CSS 지식
  • 기본적인 JavaScirpt 지식
  • DOM 기본 이해
  • ES6 문법 기본 이해
  • Node.js와 npm이 설치되어 있을 것

 

[목적]

  • terms, Babel, Webpack, JSX, 컴포넌트, props, state 그리고 생명주기와 같은 필수 React 컨셉을 배운다. 
  • 위 개념을 익히며 토이 프로젝트를 만들어본다.

[React란 무엇인가?]

  • React는 JavaScript의 가장 유명한 라이브러리 중 하나다. (Github에서 별 만 개를 받음)
  • React는 프레임워크가 아니다. (Angular는 프레임워크)
  • React는 페이스북에서 개발된 오픈소스다.
  • React는 Front의 UI를 빌드한다.
  • React는 MVC 중에서 view 레이어에 해당한다.

React 중에서 가장 중요한 것은 컴포넌트(components)다. 컴포넌트는 커스텀하게 만들 수 있으며, HTML 재사용성을 높여서 좀 더 빠르고 효율적으로 UI를 만들 수 있다. React는 또한 state, props를 통해 데이터를 저장하고 핸들링 할 수 있다.

 

 

[설치와 구성]

https://codesandbox.io/s/new

 

React - CodeSandbox

React example starter project

codesandbox.io

이 방법은 대중적이진 않은 방법이다. (c.f npx create-react-app my-app는 다음 장에서 설명)

 

그러나 jQuery와 같은 라이브러리를 사용하곤 했으면 쉽게 이해할 수 있다. 그리고 만약 Webpack, Babel 그리고 Node.js에 익숙하지 않다면 어려울 수 있다.

 

index.html 파일을 만들고, 헤더 값들은 CDN을 이용하자. (React, React DOM, Babel)

 

우리는 div를 하나 만들 거고 id 값을 root로 지정한다. 그리고 마지막으로 script 태그를 만들자.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />

    <title>Hello React!</title>

    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
  </head>

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

    <script type="text/babel">
      // React code will go here
    </script>
  </body>
</html>

d<!DOCTY=

위 CDN URL은 가장 최신의 라이브러리 버전을 사용할 수 있다.

  • React - the React top level API
  • React DOM - adds DOM-specific methods
  • Babel - a JavaScript compiler that lets us use ES6+ in old browsers

HTML에서 최초 포인트는 root div 엘리멘트다. 또한 script type에 text/babel를 주목하자. (babel을 사용하기 위한 조건)

 

그럼 첫 번째로 React 코드를 작성하자. ES6 문법을 통해 App이라는 React component 클래스를 생성한다.

class App extends React.Component {
  //...
}

render() 함수를 추가하자. render()는 오직 컴포넌트 클래스 안에서 DOM nodes를 사용하기 위한 방법이다.

class App extends React.Component {
  render() {
      return (
          //...
      );
  }
}

return 안에 간단한 HTML 엘리먼트를 입력한다. 이것을 JSX라고 부르고 우리는 이걸 좀 더 배워본다.

class App extends React.Component {
  render() {
    return <h1>Hello world!</h1>
  }
}

마지막으로 root div에 DOM render를 위해  React DOM render() 함수를 사용한다. 

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

전체 코드는 아래와 같다.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />

    <title>Hello React!</title>

    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
  </head>

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

    <script type="text/babel">
      class App extends React.Component {
        render() {
          return <h1>Hello world!</h1>
        }
      }

      ReactDOM.render(<App />, document.getElementById('root'))
    </script>
  </body>
</html>

 

위 코드를 수행하면 아래와 같은 Hello world!를 볼 수 있다.

 

 

단지 몇 가지 JavaScript 라이브러리를 통해 React 페이지를 쉽게 로딩해봤다.

 

이제 "Create React App" 명령어를 사용해보자.

 

 

[Create React App]

정적페이지 안에 JavaScript 라이브러리 실시간적으로 React와 Babel를 이용하여 랜더링 하는 것은 효율적이지 못하다.

 

다행히 페이스북에서는 "Create React App"을 사용하고 있다. 이것은 미리 React App을 빌드하기 위한 설정을 하는 것이다. 이 명령어를 통해 Webpack을 사용하여 자동적으로 React, JSX, ES6, CSS를 빌드하고 테스트를 위한 ESLint를 사용할 수 있다.

 

create-react-app을 셋팅하기 위해 터미널에서 아래 커맨드를 입력하자. (npx는 최신 버전의 React 패키지를 사용하기 위한 명령어)

npx create-react-app react-tutorial
cd react-tutorial
npm start

그럼 아래와 같이 브라우저로 http://localhost:3000에 접속하면 생성된 React app을 볼 수 있다.

 

React App

 

Create React App은 비기너뿐 아니라 엔터프라이즈 어플리케이션을 시작하기에도 좋은 커맨드이다. 그러나 언제나 모든 것이 완벽할 순 없기 때문에 자신만의 Webpack 구성을 통해 React App을 시작하기도 한다.

 

만약 당신이 프로젝트 구조를 본다면, 당신은 /public과 /src 디렉터리를 볼 수 있다. 그리고 node_modules, .girignore, READEME.md와 package.json 도 확인할 수 있다.

 

/public 안에는 div에 root가 있는 index.html 파일을 확인할 수 있다. index.html 파일 안에는 어떤 라이브러리와 스크립트도 로드되어 있지 않다.

/src 디렉터리는 당신의 모든 React code가 들어갈 것이다.

 

어떻게 자동적으로 React 코드가 컴파일 되고 업데이트 되는지 보기 위해 IDE 터미널에서 아래와 같은 응답 줄을 찾아보자.

To get started, edit `src/App.js` and save to reload.

/src/파일들을 저장할 때마다 당신은 http://localhost:3000이 새로운 데이터로 갱신되는 것을 볼 수 있다.

 

/src 디렉터리에서 index.css와 index.js만을 남겨두고 모든 파일을 지우자.

 

index.css에는 초기화 CSS 파일을 복붙한다. 만약 너가 Boostrap이나 다른 CSS 프레임워크를 사용한다면 써도 된다. 

 

index.js 안에서 React, ReactDOM, 그리고 CSS 파일을 import 했다.

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'

다시 App 컴포넌트를 생성하자. 

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './index.css'

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Hello, React!</h1>
      </div>
    )
  }
}

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

그럼 http://localhost:3000에서 "Hello React!" 메시지를 확인할 수 있을 것이다.

 

[React Developer Tools]

React Developer Tools(extension)을 이용해서 더 쉽게 React 작업을할 수 있다.

아래와 같이 Component, Porps 등 React에 대한 정보를 확인할 수 있다.

 

 

그럼 실제 React 개발에 필요한 구성과 Tool들을 갖췄다.

 

 

[JSX: JavaScript+XML]

React 코드 안에 HTML 처럼 보이는 것을 어떻게 사용하는지 알아보자. 이거슨 JSX라 부른다. (JavaScript XML)

 

아래와 같이 JSX 코드를 생성하자.

const heading = <h1 className="site-heading">Hello, React</h1>

꼭 JSX가 React 사용을 위해 필수 요소는 아니지만(실제로는 다 쓰지 않나;;) 태그를 달거나, 오브젝트 프로퍼티, 자식 정보를 갖춘 엘리먼트 생성할 수 있다. 

 

아래 코드와 위 코드는 동일한 결과를 만든다.

const heading = React.createElement('h1', { className: 'site-heading' }, 'Hello, React!')

JSX는 HTML이 아니라 JavaScript의 클로저다. 그래서 아래와 같이 몇 가지 다른 점이 있다.

  • class 대신에 claaName을 사용한다. (class는 JavaScript의 예약어이기 때문)
  • JSX 안에 프로퍼티나 함수의 경우 카멜케이스를 사용한다. (e.g onclick -> onClick)
  • Self-closing 태그들은 "/"로 끝내야 한다. (e.g <img />)

JSX 안에서 JavaScript를 사용하기 위해서는 "{}"를 사용한다(변수, 함수, 프로퍼티)

const name = 'Tania'
const heading = <h1>Hello, {name}</h1>

JSX는 vanilla JavaScirpt보다 더 사용하고 이해하기 쉽게 엘리먼트들을 사용할 수 있다. 이것도 React를 많이 사용하는 이유 중 하나다.

 

 

[Components]

React는 컴포넌트들로 구성되어 있다. class components 혹은 simple components가 될 수 있다. 

 

대부분 React app들은 매우 작은 컴포넌트들을 갖고 있다. 그리고 모든 것은 mail App 컴포넌트에서 로드된다. 

 

따라서 index.js의 App class를 제거하고 컴포넌트를 쪼개보자.

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './index.css'

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

클래스 App을 이용해서 App.js 파일을 생성하자.

import React, { Component } from 'react'

class App extends Component {
  render() {
    return (
      <div className="App">
        <h1>Hello, React!</h1>
      </div>
    )
  }
}

export default App

App에서 App 클래스를 Export하고, index.js에서 로드했다. 이렇게 꼭 분리를 할 필요는 없지만, 쪼개라 그냥

 

 

[Class Components]

그럼 Table.js를 생성하고 table 컴포넌트를 만들어보자.

import React, { Component } from 'react'

class Table extends Component {
  render() {
    return (
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Job</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>Charlie</td>
            <td>Janitor</td>
          </tr>
          <tr>
            <td>Mac</td>
            <td>Bouncer</td>
          </tr>
          <tr>
            <td>Dee</td>
            <td>Aspiring actress</td>
          </tr>
          <tr>
            <td>Dennis</td>
            <td>Bartender</td>
          </tr>
        </tbody>
      </table>
    )
  }
}

export default Table

App.js에 Table 컴포넌트를 import 한다.

import React, { Component } from 'react'
import Table from './Table'

class App extends Component {
  render() {
    return (
      <div className="container">
        <Table />
      </div>
    )
  }
}

export default App

 

그러면 아래와 같이 Table 엘리먼트들을 확인할 수 있다.

 

Table Component

 

 

[Simple Components]

React의 다른 컴포넌트 타입은 simple component이다. 이 컴포넌트는 class 키워드를 사용하지 않는다. 두 가지 컴포넌트들을 만들어보자. (table Header와 table Body)

 

이 컴포넌트 생성을 위해서는 ES6 arrow functions를 사용한다.

 

첫 번째 table header(Table.js)

const TableHeader = () => {
  return (
    <thead>
      <tr>
        <th>Name</th>
        <th>Job</th>
      </tr>
    </thead>
  )
}

그리고 body(Table.js)

const TableBody = () => {
  return (
    <tbody>
      <tr>
        <td>Charlie</td>
        <td>Janitor</td>
      </tr>
      <tr>
        <td>Mac</td>
        <td>Bouncer</td>
      </tr>
      <tr>
        <td>Dee</td>
        <td>Aspiring actress</td>
      </tr>
      <tr>
        <td>Dennis</td>
        <td>Bartender</td>
      </tr>
    </tbody>
  )
}

TableHeader와 TableBody 컴포넌트들은 같은 파일 안에 들어있다. 그리고 Table class compont에 의해 사용된다.

const TableHeader = () => { ... }
const TableBody = () => { ... }

class Table extends Component {
  render() {
    return (
      <table>
        <TableHeader />
        <TableBody />
      </table>
    )
  }
}

그럼 동일한 결과를 확인할 수 있을 것이다. 컴포넌트들은 다른 컴포넌트들 안에 들어갈 수 있다. 위 두 방식을 조합해서 사용할 수도 있다.

 

class 컴포넌트는 꼭 중요한 것은 render()를 포함해야 하고, return 안에는 오직 하나의 부모 엘리먼트만 존재해야 한다.

 

간단히 simple과 class 컴포넌트를 비교해보자.

const SimpleComponent = () => {
  return <div>Example</div>
}
class ClassComponent extends Component {
  render() {
    return <div>Example</div>
  }
}

return이 한 줄이라면 {}는 필요없다. (이건 굳이 react가 아니더라도...)

 

 

[Props]

멋진(?) Table을 생성했다. 그러나 데이터는 하드코딩 되어 있죠. React에서 가장 중요한 것은 props와 state를 이용해서 데이터를 다루는 것이죠. 

그럼 props를 통해 데이터를 다뤄봅시다.

 

첫 번째로 TableBody 컴포넌트를 제거합시다.(Table.js)

const TableBody = () => {
  return <tbody />
}

그리고 나서 아래와 같이 데이터를 옮겨봅시다. (App.js)

class App extends Component {
  render() {
    const characters = [
      {
        name: 'Charlie',
        job: 'Janitor',
      },
      {
        name: 'Mac',
        job: 'Bouncer',
      },
      {
        name: 'Dee',
        job: 'Aspring actress',
      },
      {
        name: 'Dennis',
        job: 'Bartender',
      },
    ]

    return (
      <div className="container">
        <Table />
      </div>
    )
  }
}

프로퍼티와 함께 자식 컴포넌트인 Table을 통해서 Data를 넘깁니다. 어떤 데이터는 프로퍼티를 불러와서 Data를 넘길 수 있습니다.

return (
  <div className="container">
    <Table characterData={characters} />
  </div>
)

데이터를 Table를 통해 옮겨집니다. 

class Table extends Component {
  render() {
    const { characterData } = this.props

    return (
      <table>
        <TableHeader />
        <TableBody characterData={characterData} />
      </table>
    )
  }
}

그럼 아래와 같이 가상 DOM으로 알려진 곳에 데이터가 저장됩니다.

 

React DevTools

 

데이터는 아직 DOM에는 있지 않습니다. Table 에서 우리는 모든 props를 this.props를 통해 접근할 수 있습니다.

 

App.js 전체코드

import React, { Component } from "react";
import Table from "./Table";

class App extends Component {
  render() {
    const characters = [
      {
        name: "Charlie",
        job: "Janitor"
      },
      {
        name: "Mac",
        job: "Bouncer"
      },
      {
        name: "Dee",
        job: "Aspring actress"
      },
      {
        name: "Dennis",
        job: "Bartender"
      }
    ];
    return (
      <div className="container">
        <Table characterData={characters} />
      </div>
    );
  }
}

export default App;

Table.js 전체코드

import React, { Component } from "react";
const TableHeader = () => {
  return (
    <thead>
      <tr>
        <th>Name</th>
        <th>Job</th>
      </tr>
    </thead>
  );
};
const TableBody = props => {
  const rows = props.characterData.map((row, index) => {
    return (
      <tr key={index}>
        <td>{row.name}</td>
        <td>{row.job}</td>
      </tr>
    );
  });

  return <tbody>{rows}</tbody>;
};

class Table extends Component {
  render() {
    const { characterData } = this.props;
    return (
      <table>
        <TableHeader />
        <TableBody characterData={characterData} />
      </table>
    );
  }
}

export default Table;

 

결과

 

Props는 컴포넌트들끼리 데이터를 통과시키는 효율적인 방법이다. 그러나 props를 변경할 순 없습니다. 오직 읽을 수만 있습니다. 다음 섹션에서는 State를 이용해서 Data를 핸들링 하는 방법을 알아봅시다.

 

[State]

State를 통해 props의 데이터를 변경할 수 있습니다.

데이터베이스 수정 없이 아이템을 삭제하거나 추가하거나 하는 방법을 알아봅시다.

 

계속 정리 중...

https://www.taniarascia.com/getting-started-with-react/

 

Getting Started with React - An Overview and Walkthrough Tutorial

I've been hearing about React since I first started learning JavaScript, but I'll admit I took one look at it and it scared me. I saw what…

www.taniarascia.com

 

태그