> For the complete documentation index, see [llms.txt](https://shhn0509.gitbook.io/react/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://shhn0509.gitbook.io/react/react-study/start/jsx-react.md).

# JSX → React

## Virtual DOM

```markup
<body>
  <!-- <p>Actual DOM</p> -->
  <script src="./index.js"></script>
</body>
```

### 실제 DOM model 컨트롤

```javascript
// Actual DOM
var actual_dom = document.createElement('p')
actual_dom.innerHTML = 'Actual DOM'
document.body.appendChild(actual_dom)
```

![실제 텍스트가 렌더링 되고 index.js파일도 잘 불러와 진 것을 확인 할 수 있다. ](/files/-MSb_QKxWrOC9t0SbkAd)

### 가상 DOM model 컨트롤

[virtual-hyperscript](https://github.com/Matt-Esch/virtual-dom/blob/master/virtual-hyperscript/README.md)은 실제 virtual tree를 만들어주는 역할을 한다. vdom은 실제 DOM에 렌더링하고 알고리즘을 통해 붙이는(patch)작업을 한다.&#x20;

```javascript
h('요소', 'innerHTML')
React.createElement('a', {href: './', className: 'link'}, '클릭')
```

{% hint style="info" %}
React.createElement()

```javascript
React.createElement('a', {href: './', className: 'link'}, '클릭')
```

{% endhint %}

먼저 h, createElement를 생성한다.&#x20;

```javascript
var h = require('virtual-dom/h')
var createElement = require('virtual-dom/create-element')
```

#### 예시&#x20;

\<p> 요소에 텍스트 'virtual dom'를 넣는다.  &#x20;

```javascript
var tree = h('p', 'virtual dom')
var rootNode = createElement(tree)
document.body.appendChild(rootNode)
```

![실제 렌더링 되는 결과 ](/files/-MSdSCwLokDyYo8ugP9N)

요소 안에 여러 요소를 추가 할 때는 `[]`배열로 전달할 수 있다. 또한 배열의 순서대로 출력이 되기 때문에 마크업의 순서를 설정할 수 있다.&#x20;

```javascript
var tree = h('div.foo#some-id', [
  '입력해주세요 ',
  h('span', 'some text'),
  h('input', { type: 'text', value: 'foo' }),
])
var rootNode = createElement(tree)
document.body.appendChild(rootNode)
```

![실제 렌더링 되는 결과 ](/files/-MSdRu2lKTy1SbYAAbs5)

**클래스와 아이디 추가하기**

&#x20;태그 안에 속성을 넣고 싶을 때 `{}`를 사용해서 넣는 방법도 있지만 아이디와 클래스를 넣을 때는 요소에 바로 입력해서 넣을 수 있다.&#x20;

```javascript
h('div.container', list)
h('div', { className: 'container' }, list)

// 위 둘의 결과 값은 같다. 
<div class="container"></div>

h('div#container', list)
h('div', { id: 'container' }, list)

// 위 둘의 결과 값은 같다. 
<div id="container"></div>
```

### &#x20;중간 정리&#x20;

`h`, `create-element`를 사용해서 가상 요소를 생성하고 가상 tree를 만들 수 있다.&#x20;

```javascript
var h = require('virtual-dom/h')
var createElement = require('virtual-dom/create-element')

// Virtual DOM
var tree = h('p', 'virtual dom')
var rootNode = createElement(tree)
document.body.appendChild(rootNode)


console.log(typeof h)             // function
console.log(typeof createElement) // function
console.log(tree)                 // VirtualNode (가상노드)
```

### 가상 DOM 가상 트리 비교 후, 패치

`diff()`를 사용해서 기존의 `tree`와 `newtree`의 변화를 감지하고 변화된 내용을 변수 `patches`에 담는다. 그리고 `patch()`는 변화된 내용을 변수 `rootNode`에 담아 `<body>`에 붙인다. &#x20;

```javascript
var patches = diff(tree, newTree)
patch(rootNode, patches)
```

```javascript
var h = require('virtual-dom/h')
var createElement = require('virtual-dom/create-element')
var diff = require('virtual-dom/diff')
var patch = require('Virtual-dom/patch')

var count = 0

function render(n) {
  return h('p', 'virtual dom ' + n)
}


function update() {
  // 새로운 가상 트리를 생성
  var newTree = render(++count) // 1, 2, 3, ...
  // 기존 가상 트리, 새로운 가상 트리하고 변경점이 있는지 확인
  var patches = diff(tree, newTree)
  // 변경사항이 발생하면 rootNode에 패치(붙인다)
  patch(rootNode, patches)
}

// Virtual DOM
var tree = render(count)
var rootNode = createElement(tree)
document.body.appendChild(rootNode)

window.setInterval(function () {
  update()
}, 1400)
```

![위의 코드에서 각 변수가 가리키는 것을 이미지로 확인 ](/files/-MSdX2T81DOCHKpufOxp)

### 가상 DOM 배열 데이터 순환 처리

```javascript
var h = require('virtual-dom/h')
var createElement = require('virtual-dom/create-element')
var diff = require('virtual-dom/diff')
var patch = require('Virtual-dom/patch')

var data = ['vue.js', 'angular', 'react']

function render(data) {
  var lists = data.map(function (item, index) {
    return h('li', item)
  })
  return h('ul', lists)
}

// Virtual DOM
var tree = render(data)
var rootNode = createElement(tree)
document.body.appendChild(rootNode)
```

![실제 렌더링 되는 결과 ](/files/-MSdYg8aVPdur2LEHybZ)

### 가상 DOM 제거버튼

```javascript
var data = ['vue.js', 'angular', 'react']

function render(data) {
  var lists = data.map(function (item, index) {
    return h('li', [
      item,
      h(
        'button',
        {
          type: 'button',
          onclick: function (e) {
            data.splice(index, 1)
            console.log(data)
            update()
          },
        },
        'delete'
      ),
    ])
  })
  return h('ul', lists)
}

function update() {
  var newTree = render(data) 
  var patches = diff(tree, newTree)
  patch(rootNode, patches)
}

// Virtual DOM
var tree = render(data)
var rootNode = createElement(tree)
document.body.appendChild(rootNode)
```

### 가상 DOM 추가버튼

버튼을 클릭 했을 때 클릭 할 때마다 1, 2, 3, 4, ... 개씩 추가되는 오류를 방지하기 위해 `tree=newTree` 구문으로 `diff()`가 비교하는 값을 바꿔줌&#x20;

```javascript
function update() {
  var newTree = render(data)
  var patches = diff(tree, newTree)
  patch(rootNode, patches)
  // tree 변수 값 업데이트
  tree = newTree
}
```

```javascript
var h = require('virtual-dom/h')
var createElement = require('virtual-dom/create-element')
var diff = require('virtual-dom/diff')
var patch = require('Virtual-dom/patch')

var data = ['vue.js', 'angular', 'react']

function render(data) {
  var lists = data.map(function (item, index) {
    return h('li', [
      item,
      h(
        'button',
        {
          type: 'button',
          onclick: function (e) {
            data.splice(index, 1)
            console.log(data)
            update()
          },
        },
        'delete'
      ),
    ])
  })

  var list = h('ul', lists)

  var input = h('input.add-content', {
    type: 'text',
    placeholder: 'Add Favorite Framework',
  })

  var add_button = h(
    'button.add-button',
    {
      type: 'button',
      onclick: function (e) {
        var input = document.querySelector('.add-content')
        // 모델 데이터 업데이트
        data.push(input.value)
        // 화면 뷰 업데이트
        update()
        // 콘솔 변경된 데이터 출력
        input.value = ''
      },
    },
    'Add'
  )

  var container = h('div.container', [input, add_button, list])
  return container
}

function update() {
  var newTree = render(data)
  var patches = diff(tree, newTree)
  patch(rootNode, patches)
  // tree 변수 값 업데이트
  tree = newTree
}

// Virtual DOM
var tree = render(data)
var rootNode = createElement(tree)
document.body.appendChild(rootNode)
```

### JSX와 Virtual DOM&#x20;

```javascript
// JSX
const reactElement = 
  <h1 lang='en' className='headline'>
    <strong>React</strong>{' '}
    <abbr title='Application Programming Interfaces'>APIs</abbr>
  </h1>
  
ReactDOM.render(reactElement, document.getElementById('root'))
  
// Virtual DOM
var h = require('virtual-dom/h')
var createElement = require('virtual-dom/create-element')

var abbr = h('abbr', { title: 'Application Programming Interfaces' }, 'APIs')
var strong = h('strong', 'React')

var head = h('h1. headline', { leng: 'en' }, [strong, abbr])

var rootNode = createElement(head)
document.body.appendChild(rootNode)
```

## JSX&#x20;

### JSX란?&#x20;

XML과 유사한 JS 문법(구문) 확장이다. 또는 XML 문법을 가진 JS 표현 식으로 말하기도 한다.&#x20;

### JSX가 하는 일&#x20;

JSX가 하는 일은 React 요소(Element)를 만드는 것이다.  [React.createElement()](https://ko.reactjs.org/docs/react-api.html#createelement)로 요소를 생성하고 추가하는 것은 그 과정이 복잡하다 이때, JSX를 사용해서 요소를 생성하면 가독성도 높아지고 손쉽게 요소를 추가할 수 있다.&#x20;

React 요소는 실제 DOM 요소가 아니라, JavaScript 객체이다.&#x20;

### React 요소를 만드는 2가지 방법

React 요소를 만들 때, JSX를 사용하거나 [React.createElement()](https://ko.reactjs.org/docs/react-api.html#createelement)를 사용해서 만들 수 있다. 하지만 [React.createElement()](https://ko.reactjs.org/docs/react-api.html#createelement)를 사용하는 방법은 복잡하기 때문에 대부분 JSX를 사용하여 작업한다.&#x20;

```javascript
const app = (
  <div className="app">
    <h1>React 앱</h1>
  </div>
)
```

```javascript
const appHeading = React.createElement(
  'h1',
  null,
  'React.createElement() 메서드'
)

const appElement = React.createElement('div', { class: 'app' }, appHeading)
```

## DOM vs 가상 DOM

ReactDOM 모듈은 가상 DOM을 실제 DOM에 장착(Mount)시켜 렌더링(Rendering)한다.&#x20;

### 가상 DOM을 사용하는 이유?

UI는 수시로 변경되는데 변경될 때마다 DOM이 변경되면 업데이트된 요소를 다시 렌더링 하는데 이 과정이 UI의 속도를 느리게 한다. 만약 렌더링 해야하는 요소의 수가 많을 수록 비용은 더 많이 들고 속도는 더 느려진다.&#x20;

가상 DOM은 실제 DOM에 직접적으로 조작하는 것이 아니라, 이전/이후 상태를 비교하여 변경 사항이 발생할 때 변경된 부분만 실제 DOM에 업데이트(patch) 하므로 UI 속도를 대폭 향상시킬 수 있다. &#x20;

## Babel's Compile

Babel은 JSX를 React.createElement()로 컴파일 한다. &#x20;

![Babel를 사용해서 React.createElement()로 컴파일 한다. ](/files/-MSe-nV3Bs6UAgdbreEM)

## &#x20;참고&#x20;

* [npm budo ](https://www.npmjs.com/package/budo)
* [virtual-dom](https://github.com/Matt-Esch/virtual-dom)
* [vtree](https://github.com/Matt-Esch/virtual-dom/tree/master/vtree)&#x20;
