# JSX 활용

JSX는 [JavaScript 표현식(expression) (opens new window)](https://mzl.la/2V7eeEx)을 중괄호(`{}`)로 묶어 데이터를 바인딩(Binding) 한다. 쉽게 말해 HTML 코드에서 데이터를 빼내 변수에 등록한 후, 변수를 HTML 코드에 바인딩(binding)할 수 있다는 말이다.&#x20;

> **상태가 변경되면 JSX 요소가 반환되고 반환된 요소를 렌더링 한다.**&#x20;

## 1. 데이터 바인딩 하기 &#x20;

Data는 곧 상태(State)가 된다. 해당 데이터를 요소 내부에 바인딩 시키는 작업을 해보자&#x20;

```javascript
const app = (
  <div className="app">
    <h1 className="app-title">
      <span lang="en"></span>
    </h1>
  </div>
)
```

위의 `app`의 요소 내부의 콘텐츠를 분리시키는 작업을 한다.&#x20;

```javascript
// Data === State
const state = {
  appClassName: 'app',
  apptitleClassName: 'app-title',
  appHeadlineContents: ['React', '앱'],
}
```

분리한 데이터를 요소 내부에 바인딩 할 때 아래와 같이 중괄호(`{}`, Curly Brackets)를 사용해서 바인딩 할 수 있다. 이 방식을 사용하면 동적으로 콘텐츠 변경이 가능하다.&#x20;

```javascript
const app = (
  <div className={state.appClassName}>
    <h1 className={state.appTitleClassName}>
      <span lang="en">{state.appHeadlineContents[0]}</span>{' '}
      {state.appHeadlineContents[1]}
    </h1>
  </div>
)
```

#### 1-(1) 결과&#x20;

```javascript
import React from 'react'
import ReactDOM from 'react-dom'

// Data === State
const state = {
  appClassName: 'app',
  appTitleClassName: 'app-title',
  appHeadlineContents: ['React', '앱'],
}

const app = (
  <div className={state.appClassName}>
    <h1 className={state.appTitleClassName}>
      <span lang="en">{state.appHeadlineContents[0]}</span>{' '}
      {state.appHeadlineContents[1]}
    </h1>
  </div>
)

ReactDOM.render(app, document.getElementById('root'))

```

![데이터가 들어가는 위치 확인 ](/files/-MSgjLxBk4pol9Kkm8p2)

## 2. 콘텐츠 컴파일

JSX 코드의 `{}`는 JavaScript 표현식의 연산된 결과 값을 처리하여 콘텐츠를 컴파일 한다. 아래의 데이터를 요소에 바인딩 해보자&#x20;

```javascript
const bindingContents = {
  number: 909,
  string: '콘텐츠 바인딩',
  howCanIuseJSexpressionInsideJSX() {
    return 'JavaScript 식(Expression)은 항상 값을 반환함으로 {}안에 바인딩이 가능하다'
  },
}
```

`{}`내부에서 `+ 1` 연산자를 사용할 수 있고 템플릿 리터럴을 사용할 수도 있다.&#x20;

```javascript
const app = (
  <div className="app">
    {bindingContents.number + 1} {`${bindingContents.string} hi!!`}
  </div>
)
```

또는 아래와 같은 방식으로도 자바 스크립트 식을 바인딩 할 수 있다. &#x20;

```javascript
const app = (
  <div className="app">{bindingContents.howCanIuseJSexpressionInsideJSX()}</div>
)
```

`replace()` 메서드를 사용해서 공백을 `-`기호로 변경할 수 있다.&#x20;

```javascript
const app = (
  <div className="app">
    {bindingContents.howCanIuseJSexpressionInsideJSX().replace(/\s/g, ' - ')}
  </div>
)
```

{% hint style="info" %}
`\s` 공백, `/g` 여러개를 선택&#x20;

[정규표현식 공부하기 ](https://ko.javascript.info/regular-expressions)&#x20;
{% endhint %}

단, 식이 아닌 문은 사용이 불가능하다 (오류 발생)&#x20;

```javascript
const app = (
  <div className="app">
    {if (true) {'hi'} else {'oops'}}
  </div>
)
```

![문을 사용했을 때 오류가 발생한다. ](/files/-MSgqozhVxKU4kY-7P6t)

#### 2-(1) 결과&#x20;

```javascript
import React from 'react'
import ReactDOM from 'react-dom'

const bindingContents = {
  number: 909,
  string: '콘텐츠 바인딩',
  howCanIuseJSexpressionInsideJSX() {
    return 'JavaScript 식(Expression)은 항상 값을 반환함으로 {}안에 바인딩이 가능하다'
  },
}

const app = (
  <div className="app">
    {bindingContents.number + 1} {`${bindingContents.string} hi!!`}
    <div>{bindingContents.howCanIuseJSexpressionInsideJSX()}</div>
  </div>
)

ReactDOM.render(app, document.getElementById('root'))

```

### 2.1 정리&#x20;

#### **2.1-(1) 문자 값**

```javascript
<h1>{`${headline}(${abbrs.jsx})`}</h1>
```

#### **2.1-(2) 숫자 값**

```javascript
<span>{number % 4}</span>
```

#### **2.1-(3) 함수 (또는 메서드) 결과 값**

```javascript
<p>{formatCount()}</p>
```

## 3. 속성 컴파일&#x20;

속성 값으로 큰 따옴표(`""`) 대신 중괄호(`{}`)로 묶어 JavaScript 표현식을 사용해 동적으로 속성에 데이터를 바인딩할 수 있다.&#x20;

```markup
const app = <abbr title={abbrs.jsx}>{headline}</abbr>
```

#### **3-(1) 스타일 속성 (인라인)**

스타일 코드를 JavaScript 객체(`{}`)로 표기하여 사용한다.&#x20;

```markup
const app = <li style={{ color: '#ea6666', fontWeight: 900 }}>스타일 속성(인라인)</li>
```

#### **3-(2) 스타일 속성 (객체)**

스타일 코드를 설정한 객체를 변수에 분리하여 처리할 수도 있다.&#x20;

```markup
const liStyle = { color: '#ea6666', fontWeight: 100 }

const app = <li style={liStyle}>스타일 속성(객체)</li>
```

#### **3-(3) 클래스 속성**&#x20;

CSS 클래스 속성을 React 요소에 설정하고자 한다면? JavaScript 예약어 `class` 대신 `className`을 사용해야 한다.&#x20;

```
const app = <li className="bordered rounded">클래스 속성</li>
```

#### **3-(4) 클래스 속성 (동적 처리)**

동적으로 CSS 클래스 이름을 변경해야 할 경우, 아래와 같이 `{}`를 사용해 처리합니다.

```markup
const borderColor = 'blue' / 'red', 'green'  

const app = <li className={`rounded bordered bordered-${borderColor}`}>
```

{% tabs %}
{% tab title="React " %}

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

const state = {
  appClass: 'app',
}

const borderColor = 'blue'

const liStyle = { color: '#ea6666', fontWeight: 100 }

const app = (
  <div className={state.appClass}>
    <h1 className="a11y-hidden">속성 컴파일</h1>
    <ul>
      {/* 직접 스타일 추가 */}
      <li style={{ color: '#ea6666', fontWeight: 900 }}>스타일 속성(인라인)</li>
      {/* 영역 외부에서 설정한 스타일 추가 */}
      <li style={liStyle}>스타일 속성(객체)</li>
      <li className="bordered rounded">클래스 속성</li>
      <li className={`rounded bordered bordered-${borderColor}`}>
        클래스 속성(동적 처리)
      </li>
    </ul>
  </div>
)

ReactDOM.render(app, document.getElementById('root'))

```

{% endtab %}

{% tab title="CSS " %}

```css
.a11y-hidden {
  position: relative;
  clip: rect(0 0 0 0);
  overflow: hidden;
  width: 1px;
  height: 1px;
  margin: -1px;
  white-space: nowrap;
}

.bordered {
  padding: 1rem;
  border: 1px solid currentColor;
}

.bordered-red {
  background-color: #ff1744;
}
.bordered-green {
  background-color: #1de9b6;
}
.bordered-blue {
  background-color: #039be5;
}

.rounded {
  border-radius: 6px;
}

```

{% endtab %}
{% endtabs %}

## 4. 조건부 렌더링

#### 4-(1) if 문&#x20;

아래와 같은 조건문을 만들어 요소에 바인딩 할 수 있다. `Math.random()` 메서드를 사용해서 값이 랜덤으로 나올 수 있도록 추가적으로 설정할 수 있다.&#x20;

**조건문** &#x20;

```javascript
// 조건부 처리할 함수
function conditionaRendering(usingList = false) {
  // 조건문 if, switch
  if (usingList) {
    return (
      <ul>
        <li>조건 문 사용</li>
        <li>조건 식 (3항식, 논리곱/합 연산자) 활용</li>
      </ul>
    )
  } else {
    return <p>"조건 문 활용" 또는 "조건 식 (3항식, 논리곱/합 연산자) 활용"</p>
  }
}

function randomBoolean() {
  return Math.random() < 0.5 ? true : false
}
```

**데이터 바인딩**&#x20;

이때도 마찬가지로 중괄호(`{}`)를 사용해서  값을 넣어준다.&#x20;

```javascript
const app = (
  <div className="app">
    <h1>조건부 렌더링</h1>
    {conditionaRendering(randomBoolean())}
  </div>
)
```

#### 4-(2) switch 문&#x20;

**조건문**&#x20;

```javascript
// 조건부 처리할 함수
function conditionaRendering(count = 0) {
  // 조건문 switch
  switch (count) {
    case 1:
      return (
        <ul>
          <li>조건 문 사용</li>
          <li>조건 식 (3항식, 논리곱/합 연산자) 활용</li>
        </ul>
      )
      break
    case 2:
      return <p>"조건 문 활용" 또는 "조건 식 (3항식, 논리곱/합 연산자) 활용"</p>
      break
    default:
      return (
        <p>
          React의 <abbr title="JavaScript Syntax eXtension">JSX</abbr>는
          JavaScript 객체(React 요소)를 반환합니다.
        </p>
      )
  }
}

// 숫자를 전달하면 항상 0, 1, 2 중에 하나인 값을 반환하도록 만든다.
function randomCount(number) {
  return number % 3
}
```

{% hint style="info" %}
**참고**&#x20;

`randomCount()` 함수에 사용된 [나머지 연산자 (%)](https://shhn0509.gitbook.io/javascript/javascript/es5/conditional-operator/operator-condition-processing#remainder)\
가위, 바위, 보 게임을 만들 수 있다.&#x20;
{% endhint %}

**데이터 바인딩**&#x20;

```javascript
const app = (
  <div className="app">
    <h1>조건부 렌더링</h1>
    {conditionaRendering(randomCount(Math.floor(100 * Math.random())))}
  </div>
)
```

![인자가 전달되는 함수 그림으로 이해하기 ](/files/-MSikcCeaoLPGthiPKnQ)

#### 4-(3) 3항식 &#x20;

```javascript
// 목록 또는 단락을 조건부 렌더링 하기 위한 조건 상태
let usingList = true
let usingBorderColor = true

const app = (
  <div className="app">
    <h1>조건부 렌더링</h1>
    {/* JSX 내부의 주석 처리 */}
    {/* 조건에 따라 목록을 렌더링 */}
    {usingList ? (
      <ul>
        <li>조건 문 활용</li>
        <li
          className={`bordered ${
            usingBorderColor ? 'bordered-red' : ''
          }`.trim()}
        >
          조건 식 (3항식, 논리곱/합 연산자) 활용
        </li>
      </ul>
    ) : (
      <p>"조건 문 활용" 또는 "조건 식 (3항식, 논리곱/합 연산자) 활용"</p>
    )}
  </div>
)
```

#### 4-(4) 논리 연산자&#x20;

```javascript
// 목록 또는 단락을 조건부 렌더링 하기 위한 조건 상태
let usingList = true
let usingBorderColor = true

const a11y = {
  hiddenClass: 'a11y-hidden',
}

const app = (
  <div className="app">
    <h1 className={a11y.hiddenClass || null}>조건부 렌더링</h1>
    {/* JSX 내부의 주석 처리 */}
    {/* 조건에 따라 목록을 렌더링 */}
    {usingList ? (
      <ul>
        <li>조건 문 활용</li>
        <li
          className={`bordered ${
            usingBorderColor ? 'bordered-red' : ''
          }`.trim()}
        >
          조건 식 (3항식, 논리곱/합 연산자) 활용
        </li>
      </ul>
    ) : (
      <p>"조건 문 활용" 또는 "조건 식 (3항식, 논리곱/합 연산자) 활용"</p>
    )}
  </div>
)
```

### 4.1 코드 정리&#x20;

{% tabs %}
{% tab title="if 문" %}

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

// 조건부 처리할 함수
function conditionaRendering(usingList = false) {
  // 조건문 if, switch
  if (usingList) {
    return (
      <ul>
        <li>조건 문 사용</li>
        <li>조건 식 (3항식, 논리곱/합 연산자) 활용</li>
      </ul>
    )
  } else {
    return <p>"조건 문 활용" 또는 "조건 식 (3항식, 논리곱/합 연산자) 활용"</p>
  }
}

function randomBoolean() {
  return Math.random() < 0.5 ? true : false
}

const app = (
  <div className="app">
    <h1>조건부 렌더링</h1>
    {conditionaRendering(randomBoolean())}
  </div>
)

ReactDOM.render(app, document.getElementById('root'))

```

{% endtab %}

{% tab title="switch 문" %}

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

// 조건부 처리할 함수
function conditionaRendering(count = 0) {
  // 조건문 switch
  switch (count) {
    case 1:
      return (
        <ul>
          <li>조건 문 사용</li>
          <li>조건 식 (3항식, 논리곱/합 연산자) 활용</li>
        </ul>
      )
      break
    case 2:
      return <p>"조건 문 활용" 또는 "조건 식 (3항식, 논리곱/합 연산자) 활용"</p>
      break
    default:
      return (
        <p>
          React의 <abbr title="JavaScript Syntax eXtension">JSX</abbr>는
          JavaScript 객체(React 요소)를 반환합니다.
        </p>
      )
  }
}

// 숫자를 전달하면 항상 0, 1, 2 중에 하나인 값을 반환하도록 만든다.
function randomCount(number) {
  return number % 3
}

ReactDOM.render(app, document.getElementById('root'))

```

{% endtab %}

{% tab title="3항식 " %}

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

// 목록 또는 단락을 조건부 렌더링 하기 위한 조건 상태
let usingList = true
let usingBorderColor = true

const app = (
  <div className="app">
    <h1>조건부 렌더링</h1>
    {/* JSX 내부의 주석 처리 */}
    {/* 조건에 따라 목록을 렌더링 */}
    {usingList ? (
      <ul>
        <li>조건 문 활용</li>
        <li
          className={`bordered ${
            usingBorderColor ? 'bordered-red' : ''
          }`.trim()}
        >
          조건 식 (3항식, 논리곱/합 연산자) 활용
        </li>
      </ul>
    ) : (
      <p>"조건 문 활용" 또는 "조건 식 (3항식, 논리곱/합 연산자) 활용"</p>
    )}
  </div>
)

ReactDOM.render(app, document.getElementById('root'))

```

{% endtab %}

{% tab title="논리 연산자 " %}

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

// 목록 또는 단락을 조건부 렌더링 하기 위한 조건 상태
let usingList = true
let usingBorderColor = true

const a11y = {
  hiddenClass: 'a11y-hidden',
}

const app = (
  <div className="app">
    <h1 className={a11y.hiddenClass || null}>조건부 렌더링</h1>
    {/* JSX 내부의 주석 처리 */}
    {/* 조건에 따라 목록을 렌더링 */}
    {usingList ? (
      <ul>
        <li>조건 문 활용</li>
        <li
          className={`bordered ${
            usingBorderColor ? 'bordered-red' : ''
          }`.trim()}
        >
          조건 식 (3항식, 논리곱/합 연산자) 활용
        </li>
      </ul>
    ) : (
      <p>"조건 문 활용" 또는 "조건 식 (3항식, 논리곱/합 연산자) 활용"</p>
    )}
  </div>
)

ReactDOM.render(app, document.getElementById('root'))

```

{% endtab %}
{% endtabs %}

## 5. 리스트 렌더링

#### 5-(1) 들어가기 전&#x20;

리스트를 레더링하여 JSX 요소에 데이터를 바인딩 할 때 아래와 같이 배열 데이터를 순환하여 사용한다.&#x20;

![](/files/-MSj6H2l6cc6gijCKwqm)

{% hint style="warning" %}
forEach() 메서드는 왜 사용하지 않는가?&#x20;

사용을 못하는 것은 아니지만`forEach()` 메서드는 값을 반환하지 않기 때문에 JSX에서 사용하기에 적합하지 않다.&#x20;
{% endhint %}

![forEach() 메서드는 값을 반환하지 않는다. ](/files/-MSj6h3EmobwdfdYUD38)

#### 실습 (1)&#x20;

아 위에서 먼저 콘솔 패드에서 `map()` 메서드를 사용해서 배열 데이터를 바인딩 한 것처럼 JSX에서도 아래와 같이 배열 데이터를 요소에 바인딩 했다.&#x20;

사용 방법은 이전의 데이터 바인딩 방법과 똑 같다. `{}` 로 묶어주고 그 안에서 `map()` 메서드를 사용하고 JSX 요소를 작성해서 순환되는 데이터가 어디에 들어가야 할지 설정한다.&#x20;

```javascript
const numbers = [500, 50, 5, 0.5]

const app = (
  <div className="app">
    <h1>리스트 렌더링</h1>
    <ul>
      {numbers.map((n) => (
        <li>{n * 2}</li>
      ))}
    </ul>
  </div>
)
```

[**⚠️ 오류**](https://shhn0509.gitbook.io/react/react-study/undefined/jsx/error#list)&#x20;

React에서는 리스트를 렌더링 할 때, 각 아이템을 구분 할 수 있도록 고유한 key 값을 부여해야한다. 오류를 해결하기 위해 고유한 식별자(id) 값을 설정하자&#x20;

아래와 같이 `index`를 `key` 값으로 해서 각 아이템의 식별자로 만들었다. (오류 해결)&#x20;

```javascript
const app = (
  <div className="app">
    <h1>리스트 렌더링</h1>
    <ul>
      {numbers.map((n, i) => (
        <li key={i}>{n * 2}</li>
      ))}
    </ul>
  </div>
)
```

#### 실습 (2)&#x20;

실습(1)과 같은 간단한 예제 말고 복잡한 배열 데이터 바인딩 해보자 아래의 강사의 정보를 담고 있는 배열 데이터가 있다.&#x20;

```javascript
const FEML_lecturers = [
  {
    id: 'lecturer-az081871',
    name: '김데레사',
    module: 'A',
    facebook: 'http://facebook.com/seulbinim',
    image: 'http://yamoo9.github.io/images/photo-deresa@2x.png',
  },
  {
    id: 'lecturer-az081872',
    name: '야무',
    module: 'B, C',
    facebook: 'http://facebook.com/yamoo9',
    image: 'http://yamoo9.github.io/images/photo-yamoo9@2x.png',
  },
]
```

#### 5-(2) 데이터 바인딩&#x20;

```jsx
const app = (
  <div className="app" role="main" aria-labelledby="main-title">
    <h1 id="main-title">Front-End Masters League 강사진</h1>
    <ul className="lecturers">
      {FEML_lecturers.map((lecturer) => (
        <li className="lecturers" key={lecturer.id}>
          <a href={lecturer.facebook} rel="noreferer nopener">
            <figure className="lecturer-info">
              <img src={lecturer.image} alt="" className="lecturer-photo" />
              <figcaption>
                {lecturer.module} 모듈을 담당 할 {lecturer.name} 강사 Facebook
                바로가기
              </figcaption>
            </figure>
          </a>
        </li>
      ))}
    </ul>
  </div>
)
```

### 5.1 리스트 조건부 처리&#x20;

#### 5.1-(1) 정리&#x20;

배열 데이터를 순환 처리 해서 사용하도록 `map()`메서드를 사용하고 각 아이템을 데이터 바인딩을 한다. 그리고 리스트에는 고유한 key를 가지고 있어야만 오류가 표시되지 않는다.&#x20;

## 6. 주의할 점&#x20;

#### 6-(1) 속성 이름은 camelCase 표기법으로 사용하기&#x20;

JSX는 HTML이 아닌 JavaScript 식이다. 그래서 React DOM은 HTML 표준 속성 이름 중 일부는 그대로 이름을 사용할 수 없다. 예를 들어 `class`는 `className`으로, `tabindex`는 `tabIndex`로 사용해야 한다. 즉, 음절이 2개 이상인 경우 camelCase로 표기하기!&#x20;

{% hint style="warning" %}
단, [접근성 속성](https://ko.reactjs.org/docs/accessibility.html#wai-aria)은 그대로 사용해도 괜찮다.&#x20;

`aria-*` 접두사가 붙거나, `role`과 같은 접근성 관련 속성은 기존에 HTML에서 사용하던 그래도 사용한다.&#x20;

```javascript
const app = (
  <div className="app" role="main" aria-labelledby="main-title">
    <h1 id="main-title">Front-End Masters League 강사진</h1>
    </ul>
  </div>
```

{% endhint %}

#### 6-(2) 콘텐츠가 없는 요소는 항상 닫아야 한다.&#x20;

JSX는 XML 문법에 따라 콘텐츠가 없는 빈 요소(empty element)는 반드시 닫아(`/>`) 줘야 한다. (예: `<img/>`, `<br/>`, `<area/>`, `<meta/>`, `<link/>`등)&#x20;

#### 6-(3) 기본적으로 루트 요소는 하나만 사용한다.&#x20;

root 요소 `<div>`위에 root 요소를 하나 더 생성하니 오류가 발생한다.&#x20;

![루트 요소를 또 추가하니 오류가 발생한다. ](/files/-MSiy8wYtjyGK80b4rfi)

`<div>`요소로 감싸줘서 root 요소가 하나만 있을 수 있도록 해야한다. (단, 이 경우는 의미없는 요소를 사용했기 때문에 시멘틱 마크업이라고 할 수 없다.)&#x20;

![](/files/-MSiyiVvgmao551e3btC)

또는 `<React.Fragment>` 요소를 사용해서 랩핑할 수 있다. (단, React를 불러와야 사용할 수 있다.)

```javascript
const app = (
  <React.Fragment>
    <header>앱 헤더</header>
    <div className="app" role="main" aria-labelledby="main-title">
      <h1 id="main-title">Front-End Masters League 강사진</h1>
      <ul className="lecturers">{**}</ul>
    </div>
  </React.Fragment>
)
```

`<React.Fragment>`를 `<></>`로 작성해줘도 적용된다. `<React.Fragment>`의 별칭 같은 거라고 생각면 좋다.&#x20;

```javascript
const app = (
  <>
    <div className="app"></div>
    <h1>조건부 렌더링</h1>]
  </>
)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://shhn0509.gitbook.io/react/react-study/start/jsx.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
