본문 바로가기

Programming

React JS 소개와 간단한 사용법 및 에제

관련 글

서론

최근까지 웹 개발을 할 때에 Python FlaskJinja Template을 이용해 간단하게 개발을 해 왔었다. 그러다보니 Flask API와 Template Jquery로 이루어진 Javascript 파일들이 난잡하게 어질러 져 있어 직접 개발을 하고도 너무 더럽다 라는 생각이 많이 들었었다.

그러다가 React JS라는 것을 알게 되었고 이를 이용해 웹 개발을 하다보니 정리가 잘되기도 하고 실제 웹을 컨트롤할 때 무척 편하다는 느낌을 받게 되었다.

아직 React JS에 대해서 잘 이해를 못하고 단순히 Doc에 나온대로 사용만 하는 수준이지만 지금까지 해왔던 것들을 정리 및 사람들에게 React JS에 대해 소개도 할 겸 해서 블로그에 글을 올리려고 한다.

또한, 이번 글에서는 간단하게 React JS에 대해 소개만 하고, 이 후 LifecycleFlux 등에 대해 정리할 예정이다. 그리고 그외에 React JS, Python FlaskWebpack을 이용해 실제 웹 개발을 할 수 있는 환경구축 방법에 대해 작성할 예정이다.

React JS

React JS는 페이스북과 인스타그램의 웹 UI를 개발할 때 사용하려고 만든 자바스크립트 라이브러리이다. 또한 Backbone.js와 Angular.js와 같이 이를 이용해 웹의 Front를 자유자재로 다룰 수 있으므로 나는 웹 프론트 프레임워크(Web Front Framework)라고도 생각한다.


React JS의 가장 큰 특징이자 사용하는 이유로는 지속해서 데이터가 변화하는 대규모 에플리케이션을 구축할 수 있다이다. React에서 Component를 사용하여 웹 UI를 구축하며 데이터가 변하는 Component만을 다시 rendering해서 변화된 데이터를 표시한다.


React JS는 영어문서한글문서가 있으며 링크에서 확인할 수 있다.


React JS의 특징은 크게 세가지가 있다.

  • JSX(JavaScript XML)
    JSX는 React JS에서 확장자 명이기도 하고, JavaScript + XML이라는 뜻을 갖고 있다. 이는 기존 XML을 허용하는 JavaScript 확장 문법으로 JavaScript에 마크업 코드(Markup Code)를 작성할 수 있게 허용한다. 예를 들어, JS 내에서 div DOM을 생성하려면 React.createElement('div', {className: "commentBox"}, "Hello World)와 같이 작성해야 하지만, JSX를 이용하면 <div className="commentBox">Hello World</div> 와 같이 사용할 수 있다.
    일반 HTML 사용하듯이 사용하면 되므로 무척 편리하다. 하지만 이러한 JSX 파일을 그냥 사용할 수는 없고 JSX Transformer를 include하거나 직접 컴파일을 해야 사용할 수 있다.

  • 가상 DOM(Virtual DOM)
    실제 HTML의 DOM이 아닌 React에서 사용하는 Virtual DOM이란 것이 존재한다. Virtual DOM에는 ReactElement, ReactElement Factory, ReactNode, ReactComponent 그리고 ReactComponent Class가 있다. 자세한 내용은 링크에서 확인 가능하다.

  • 단방향 데이터 플로우(Unidirectional Data Flow)

React JS 간단한 예제

원래 실제 React 파일인 *.jsx 파일을 사용하려면 webpack이나 browserify같은 것들을 이용해 컴파일을 한 후 로드해서 사용해야 하지만 간단한 예제이므로 babel.js를 로드하여 즉석에서 컴파일할 수 있게한다.

Example 1


첫 번째로, <head></head> 태그 내에 위의 JS 파일들은 전부 include 해야 한다. 여기서는 jsx 파일을 컴파일 하지 않기 때문에 babel은 무조건 include 해야 한다.


두 번째로, React js로 만든 DOM을 생성할 div를 하나 만든다. 물론 div가 아닌 body에다가 rendering 할 수도 있다.


세 번째로,

var CommentBox = React.createClass({})

코드를 이용해 하나의 Component를 만든다. 이 때, Component 이름은 무조건 대문자로 시작하는 Camel case로 하여야 한다.

Example 2

이번 예제는, 여러개의 component를 이용해 DOM을 구성하고 상위 component에서 데이터를 받아 this.props.*를 통해 접근하여 표시할 수 있는 예제이다. 아래 코드와 같이 React JS에서 Data Flow는 상위 component에서 하위 component로 진행된다.


코드

결과
a

위의 코드를 보면 ...this.props를 사용하고 있는데, 이는 상위 component에서 받은 props들을 그대로 하위 component로 넘기겠다는 의미이다. 전부 전달 하는 것 외에도 몇개를 현재 component에서 사용하고 나머지를 넘기는 것도 가능하다.

...
var {checked, ...other} = this.props;
return(
    <div {...other} className={test}></div>
);
...

Example 3

this.props를 이용해 데이터를 전달하고 전달 받는 방법을 알았다. 이번 예제는 this.state를 이용해 데이터를 변경하고 변경된 component만 re-rendering하는 방법을 알 수 있는 예제이다.


코드


결과
imgur


위의 코드를 실행해 보면, form 태그에 입력하는 그대로 브라우저에 표시되는 것을 볼 수 있다. 이처럼 this.state를 이용하면 데이터를 변경하고 실시간으로 이를 표시할 수 있다.


위 코드를 자세히 보면, CommentBox component 내부에 CommentList, CommentForm component가 존재한다. 그리고 이 예제에서 하려고 하는 일은 CommentForm component에서 데이터를 수정하면 그 변화가 CommentList에 나타날 수 있게 하는 것이다.


그러기 위해선 CommentListCommentForm의 데이터를 컨트롤 할 수 있는 CommentBoxstate를 두어야 한다. 먼저 getInitialState Lifecycle Method를 이용해 초기 state를 초기화 한다.

var CommentBox = React.createClass({
    getInitialState: function(){
      return {data: this.props.data};
    },


이 후 data state를 변경할 dataChange함수를 만든다. author와 text를 받아오면 기존 state에 데이터를 추가하고 this.setState() 함수를 호출하는 것을 볼 수 있다. React JS에서 this.state를 직접적으로 변경하면 데이터는 변경 되나 rendering이 되지 않아 데이터 변화를 표시할 수 없다. 하지만 this.setState() 함수를 이용하면 state 값을 변경하고 변경된 component를 re-rendering한다.

dataChange: function(author, text){
      var tmpData = this.state.data;
      tmpData.push({
        author: author,
        text: text
      });

      this.setState({data:tmpData});
    },


하지만 이 dataChange 함수는 현재 component인 CommentBox에서 사용할 함수가 아닌 CommentForm component에서 사용할 함수이다. 그러므로 이 함수를 CommentForm component에 props로 넘겨준다.

var CommentBox = React.createClass({
...
...
    render: function() {
      return (
        <div className="commentBox">
          <h1>Comments</h1>
          <CommentList data={this.state.data} />
          <CommentForm formHandler={this.dataChange} />
        </div>
      );
    }
});


이제 CommentForm에서는 form submit 이벤트가 발생하면 input 태그의 값을 가져와 this.props.formHandler 함수를 사용할 함수를 만든다.

var CommentForm = React.createClass({
  formOnChange: function(e){
    e.preventDefault();
    var author = this.refs.author.value;
    var text = this.refs.text.value;

    if(author!="" && text!=""){
      this.props.formHandler(author, text);
      this.refs.author.value = '';
      this.refs.text.value = '';
    }

    else{
      alert("Fill author and text");
    }
  },
  ...
    <form className="commentForm" onSubmit={this.formOnChange}>
        <input type="text" placeholder="Your name" ref="author"/>
        <input type="text" placeholder="Say something..." ref="text"/>
    </form>
    ...
}); 


일반 HTML에서 처럼 onSubmit 이벤트를 사용할 수 있으므로 만든 함수를 binding한다.
form이 submit이 되면, input 태그에 붙어있는 ref 값을 이용해 DOM을 선택하고 값을 가져온다. 이 후 CommentBox에서 만든 함수 dataChange를 호출하기 위해 this.props.formHandler 함수를 호출한다.


함수가 호출되면 this.setState 함수에 의해 state에 변화가 일어나고 React에서는 그 변화를 감지하여 변화된 DOM만 re-rendering한다.

요약

React JS 라이브러리를 이용해 Web 개발을 해 보니 정말 편리하다는 느낌을 받았다. 위에 서술했던대로 Front를 전부 JS로 작성하니 코드를 난잡하지 않게 할 수 있었고, 상위 component에서 하위 component 방향으로 propstate를 이용한 data-flow 방식도 정말 재밌었다. 특히 state를 변경함으로써 해당 state 값을 사용하는 component만 re-rendering 하는 방식이 마음에 든다.


또한 이 글에 나오진 않지만 Mount라는 개념과 componentDidMount, ComponentWillMount 등과 같은 Lifecycle Method도 흥미롭다.