React 노드 만들기

대부분의 경우에 React 개발자분들은 JSX를 사용해 React 노드 만드는 것을 선호할 것 같습니다. 하지만 그렇다 하더라도 이번 챕터에서 우리는 어떻게 JSX 없이 오로지 JavaScript만으로 어떻게 React 노드가 만들어질 수 있는지 살펴볼 것입니다. 물론 다음 챕터에서는 JSX를 이용해서 React 노드를 만드는 방법에 대해서 다룹니다.

JavaScript를 이용해 React 노드를 만드는 것은 간단합니다. React.createElement(type,props,children) 함수를 호출하고 실제 DOM 노드를 정의하는 인수 묶음(예: type = an html element, <li> or custom element, <my-li>)을 전달하는 것이 전부입니다.

React.createElement()의 인수는 아래와 같습니다:

  • type (string | React.createClass()): HTML 요소나 React 컴포넌트 인스턴스를 대표하는 문자열이 될 수 있음. (예: React.createClass()의 인스턴스)

  • props (null | object):

    null 또는 속성/props와 값을 담고 있는 오브젝트일 수 있음.

  • children (null | string | React.createClass() | React.createElement()):

    Children은 null, 텍스트 노드로 바뀌는 문자열, React.createClass() 또는 React.createElement()의 인스턴스일 수 있음.

아래를 보시면, React.createElement() 함수를 사용해 one(React 텍스트)이라는 텍스트 노드와 li1이라는 id를 포함하고 있는 <li> 요소 노드의 가상 DOM의 표현을 만들었습니다.

var reactNodeLi = React.createElement('li', {id:'li1'}, 'one');

첫번째 인수는 제가 표현하고 싶었던 HTML 요소를 정의하고 있습니다. 두번째 인수는 <li>에 대한 속성/props를 정의하고 있고, 세번째 인수는 요소 안에 어떤 노드가 되어야 할지를 정의하고 있습니다. 위의 경우에는, 간단하게 <li> 안에 자식 텍스트 노드(예: 'one')를 넣었습니다. 앞으로 만들어 질 노드의 자식이 될 마지막 인수는 이런 것들이 올 수 있습니다.

  • A React 텍스트 노드
  • A React 요소 노드 또는
  • A React 컴포넌트 인스턴스

위에서 저는 React 텍스트 노드를 포함한 React 요소 노드를 만들어 변수 reactNodeLi 안에 저장했습니다. 가상 DOM을 만들기 위해서는 React 요소 노드를 실제 DOM에 정말로 렌더해야 합니다. 이걸 위해 우리는 ReactDOM.render() 함수를 사용합니다.

ReactDOM.render(reactNodeLi, document.getElementById('app'));

위의 코드는 분명하게 정리하면 아래와 같은 일들을 호출합니다:

  1. (reactNodeLi)로 전달된 React 요소 노드로 구성된 가상 DOM 생성
  2. 가상 DOM을 이용해 실제 DOM 브랜치를 재구조화
  3. 실제 DOM 브랜치(예: <li id="li1">one</li>)를 <div id="app"></div>의 자식 노드로 DOM에 주입

다른 말로 하면, HTML 돔은 원래 이러했지만:

<div id="app"></div>

이렇게 변합니다:

<div id="app">
    //React가 react의 data-reactid 속성을 추가했다는 점을 짚고 넘어가세요.
    <li id="li1" data-reactid=".0">one</li>
</div>

이것은 꽤나 단순한 예제입니다. React.createElement()를 사용하면 복잡한 구조도 당연히 만들 수 있습니다. 예를 들어 아래의 코드에서 저는 React.createElement()를 이용해 HTML의 정렬되지 않은 텍스트 단어 리스트(예: <ul>)를 보여주는 덩어리의 React 노드를 만들고 있습니다.

// React 요소인 <li>들 만들기
var rElmLi1 = React.createElement('li', {id:'li1'}, 'one'),
    rElmLi2 = React.createElement('li', {id:'li2'}, 'two'),
    rElmLi3 = React.createElement('li', {id:'li3'}, 'three');

// <ul>이라는 React 요소를 만들고 자식으로 React <li> 요소 추가하기
var reactElementUl = React.createElement('ul', {className:'myList'}, rElmLi1, rElmLi2, rElmLi3);

정렬되지 않은 리스트를 DOM에 렌더하기 전에, 변수 자리에 React.createElement()를 사용하면 위의 코드가 훨씬 간단하게 될 수 있다는 점을 보여드리는게 좋을 것 같습니다. 이 코드는 JavaScript를 이용해 계층 구조나 DOM 브랜치가 어떻게 정의될 수 있는지도 보여줍니다.

var reactElementUl = React.createElement(
    'ul', {
        className: 'myList'
    },
    React.createElement('li', {id: 'li1'}, 'one'),
    React.createElement('li', {id: 'li2'}, 'two'),
    React.createElement('li', {id: 'li3'}, 'three')
);

위의 코드가 DOM에게 렌더되면, 이런 HTML이 나오게 됩니다:

<ul class="myList" data-reactid=".0">
    <li id="li1" data-reactid=".0.0">one</li>
    <li id="li2" data-reactid=".0.1">two</li>
    <li id="li3" data-reactid=".0.2">three</li>
</ul>

아래의 JSFiddle을 이용해 여러분 스스로 확인해볼 수도 있습니다:

source code

이쯤되면 React 노드가 가상 DOM 트리 안에 있는 실제 DOM 노드를 표현한 트리 속의 JavaScript 오브젝트에 지나지 않는다는 점이 이해될 것입니다. 가상 DOM은 그 후 HTML 페이지에서 실제 DOM 브랜치로 구성될 때 사용됩니다.

메모

  • React.createElement(type, props, children)에 넘겨지는 type 인수는 이런 것들이 될 수 있습니다:
    • 표준 HTML 요소를 나타내는 문자열(예: 'li' = <li></li>)
    • 커스텀 요소(예: 'foo-bar' = <foo-bar></foo-bar>)
    • React 컴포넌트 인스턴스(예: React.createClass()의 인스턴스)
  • 이런 것들은 React가 지원하는 표준 HTML 요소들입니다. (이런 요소들은 createElement()에게 문자열 type처럼 넘겨집니다.) 이들은 DOM 안에서 연관된 표준 HTML 요소를 만들어냅니다.
a abbr address area article aside audio b base bdi bdo big blockquote body br
button canvas caption cite code col colgroup data datalist dd del details dfn
dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
h6 head header hgroup hr html i iframe img input ins kbd keygen label legend li
link main map mark menu menuitem meta meter nav noscript object ol optgroup
option output p param picture pre progress q rp rt ruby s samp script section
select small source span strong style sub summary sup table tbody td textarea
tfoot th thead time title tr track u ul var video wbr

results matching ""

    No results matching ""