Dev

React 공부 정리 #1

August 3, 2016

React 공부 정리 #1

교재 및 강좌 1


React란?

  • 리액트는 자바스크립트와 XML을 이용해 조합형 사용자 인터페이스를 구축하는 엔진
    • 저스틴 딜(Justin Deal)은 반응형 렌더링과 게임 엔진이 작동하는 방식의 유사성에 주목하고 리액트를 설명하는데 ‘엔진’이라는 용어를 처음 사용(https://zapier.com/engineering/react-js-tutorial-guide-gotchas/)
    • React의 경우 ‘View’ 레이어만 핸들링 하기 때문에 이외의 부분에선 다른 기술이 필요함

React 특징

VirtualDOM을 사용한 화면 조작

  • ‘diffing’ 알고리즘을 사용하여 문서의 변화를 확인하고, ‘Reconcillation’를 진행하기 때문에 부분적인 조작이 가능함
  • 그리고 문서의 DOM을 직접 조작하는 것이 아니라 ‘인-메모리’에 존재하는 DOM을 조작하는 것이기 때문에 효율적이고 빠름

컴포넌트(Components)와 단방향 데이트 흐름(UnidirectionalU)

  • React는 Component로 구성되어 있기 때문에 개발 할 때 모든 객체를 컴포넌트 단위로 고려하는 것이 좋음
  • React에선 데이터가 단방향으로 전송되기 때문에 데이터를 추적하기 쉽고 디버깅을 상대적으로 쉽게 된다는 장점이 있고, 이러한 특징을 살려서 Flux 패턴을 사용한 Redux 라이브러리를 많이 활용함

JSX

  • JSX는 필수는 아니지만 리액트 컴포넌트에서 UI를 정의하는 표준적인 방법으로 널리 이용되고 있음
  • JSX는 컴파일 되기 때문에 JS에 비해서 실행 속도가 빠르고, Type-safe(정의된 연산에 대해서만 작동하며, 정의되지 않은 연산은 결과를 제공하지 않는 것)하며 컴파일링 과정에서 에러를 감지 할 수 있음
    • Type-safe의 정의는 위키피디아 항목 중 ‘Vijay Saraswat’ 항목을 참고할 것!

Props

  • props는 컴포넌트에서 사용 할 변경 불가능한(immutable) 데이터를 지칭함
  • props는 parent 컴포넌트에서 child 컴포넌트로 데이터를 전달 때 사용함

State

  • state는 컴포넌트에서 변경 가능한 데이터를 지칭함
  • state는 외부에서 데이터를 변경할 때 this.setState()를 사용해야 함

Life Cycle

  • 컴포넌트를 생성시 constructor –> componentWillMount –> render –> componentDidMount
  • 컴포넌트를 제거시 componentWillUnmount 호출
  • 컴포넌트의 prop이 변경시 componentWillReceiveProps –> shouldComponentUpdate –> componentWillUpdate –> render –> componentDidUpdate
  • 컴포넌트의 state가 변경시 shouldComponentUpdate –> componentWillUpdate –> render –> componentDidUpdate

FLUX 패턴/아키텍처

  • Action –> Dispatcher –> Store –> View 구조로 데이터를 전달하고 업데이트 할 수 있도록 구성된 패턴
  • View에서 Dispatcher로 Action을 보낼 수 있으며, Dispatcher는 작업이 중첩되지 않도록 Action을 스케쥴링 함(사실상 대기)
  • FLUX 패턴/아키텍처를 좀 더 유연하게 사용할 수 있도록 ‘Redux’라는 라이브러리를 많이 사용함

개발환경

NPM 설치

  > npm install -g webpack webpack-dev-server
  > npm install --save react react-dom react-addons-update redux react-redux
  > npm install --save-dev babel-core babel-loader babel-preset-react babel-preset-es2015 

webpack.config.js

module.exports = {  
  entry: [
    './src/index.js'
  ],  
  output: {
    path: __dirname,
    publicPath: '/',
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      exclude: /node_modules/,
      loader: 'babel',
      query: {
        presets: ['react', 'es2015', 'stage-1']
      }
    }]
  },
  resolve: {
    extensions: ['', '.js', '.jsx']
  },
  devServer: {
    historyApiFallback: true,
    contentBase: './'
  }
};

만들어 볼 예제

React 기초 – JSX

기본 코드 작성

# index.html
<!DOCTYPE html>  
<html>  
  <head>
    <link rel="stylesheet" href="/style/style.css">
    <link rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css">
    <script src="https://maps.googleapis.com/maps/api/js"></script>
  </head>
  <body>
    <div class="container"></div>
  </body>
  <script src="/bundle.js"></script>
</html>

# src\index.js
import React from 'react';  
import ReactDOM from 'react-dom';

const App = () => {  
    return <div>Hi!</div>;
};

ReactDOM.render(<App />, document.querySelector('.container'));  
  • ReactDOM.render()를 사용해서 ‘.container’의 하위 객체로 렌더링해서 화면에 “Hi!”를 출력

컴포넌트 구조

# src\search_bar.js
import React, { Component } from 'react';

const SearchBar = () => {  
  return <input />; // React.createElement("input", null)
};

export default SearchBar;

# src\index.js
import React from 'react';  
import ReactDOM from 'react-dom';

import SearchBar from './components/search_bar';

const API_KEY = 'AIzaSyDBv1L6bjiubNh1irNE_CewqdtyfxvGfe8';

const App = () => {  
  return(
    <div>
        <SearchBar />
    </div>
  );
};

ReactDOM.render(<App />, document.querySelector('.container'));  
  • search_bar.js에서 SearchBar 함수를 만들고 export 구문을 사용해서 외부 컴포넌트로 사용할 수 있도록 하였고, index.js에서 해당 컴포넌트를 import해서 사용하고 있음
  • index.html –> index.js –> search_bar.js 를 호출하는 구조로 되어 있음

클래스 기반 컴포넌트 구조 및 사용자 이벤트 처리

# search_bar.js
...
class SearchBar extends React.Component {  
  render() {
    return <input onChange={(event) => console.log(event.target.value)} />;
  }

  onInputChange(event) {
   console.log(event.target.value);
  }
}
  • 클래스 기반의 컴포넌트의 경우 React.Component를 상속하는 형태로 구성되어 있음
  • 이벤트를 연결하는 구문이 ‘onChange’처럼 ‘낙타 표기’에 주의할 것! 즉, onclick이 아니라 onClick의 형태로 사용!
  • => 연산자를 사용해서 이벤트를 처리하고 있음

State

...

class SearchBar extends React.Component {  
  constructor(props) {
    super(props);
    this.state = { term: 'Starting Value'};
  }

  render() {
    return (
       <div>
       <input 
           value={this.sate.term}
           onChange={(event) => this.setState({ term: event.target.value })} />
       value of the input : {this.state.term}
       </div>
    );
  }
}
  • state 의 초기 값을 설정 할 때는 생성자(constructor) 메소드에서 this.state를 사용해야 함
  • state를 렌더링 할 때는 this.state.stateName을 사용
  • state를 업데이트 할 때는 this.setState() 메소드를 반드시 사용!
    • this.setState() 메소드를 사용하지 않으면 re-rendering이 되지 않음

  1. 글쓴이가 C/C++, python을 사용해서 서버쪽 개발에 특화되어있기 때문에 잘못된 정보/내용이 함유되어 있을 수 있으므로 레퍼런스로 활용하기에 약간의 문제가 있음을 사전에 알려드립니다. 그리고 틀리거나/잘못되거나/수정이 필요한 부분은 댓글에 알려주시면 즉시 반영할 수 있도록 하겠습니다.
Array