> 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/getting-started/react-1.md).

# React 시작하기

## 리액트 환경

리액트를 사용할 수 있는 환경인지 확인한다.&#x20;

```javascript
!!React    // true
!!ReactDOM // true
```

## 컴포넌트 시스템

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

```javascript
// [설계] React Component (Functional)
function App() {
  return <div>React Element</div>
}

// [인스턴스 생성] React Element (JSX)
// 마치 HTML 문법인 것 처럼 보인다. 
var app = <App/>

// ReactDOM (rendering)
// ReaetDOM.render(가상DOM(React 요소), 실제 DOM 요소)
// ReaetDOM.render()에 의해서 실제 돔 요소에 붙여지게 된다. 
ReactDOM.render(app, document.querySelector('#app'))
```

![컴포넌트가 브라우저에 렌더링 되기 까지 거치는 과정 ](/files/-MSZMUDrp_L-9okXhvAj)

{% embed url="<https://codepen.io/hanna244/pen/KKNpyxR?editors=0011>" %}

## 컴포넌트 시스템&#x20;

`App()`, `AppMain()`, `MenuList()`, `MenuListItem()` 과 같은 컴포넌트를 만들어 사용한다. 마치 HTML `<tag>`처럼 보인다.&#x20;

{% tabs %}
{% tab title="컴포넌트 연결 " %}
각 컴포넌트가 연결되는 것을 그림으로 볼 수 있다.&#x20;

`MenuListItem()`은 `MenuList()`에 불러와지고 \
`MenuList()`는 `AppMain()`에 불러와지고 \
`Appmain()`은 `App()`에 불러와지고 \
`App()`은 `app`이라는 변수에 담아진다.&#x20;

그리고 담아진 가상DOM은 `render()`과정을 거쳐서 `<div id="app"></div>`에 바인딩 된다.&#x20;

![](/files/-MSZcu5GcPEKQc2hQ-kd)
{% endtab %}

{% tab title="JS " %}

```javascript
// React Component (Functional)
function MenuListItem() {
  return (<li class="ediya-menu__item">
      <a href="#" role="button" aria-haspopup="dialog" aria-pressed="false">
        <figure>
          <img src="//raw.githubusercontent.com/yamoo9/assets/master/images/ediya/iced-cherry-blossoms-latte.png" alt="" width="323" height="323" />
          <figcaption>ICED 벚꽃라떼</figcaption>
        </figure>
      </a>
      <div role="dialog" aria-modal="false" aria-labelledby="dialog-1-label">
        <h3 id="dialog-1-label" class="a11y-hidden">ICED 벚꽃라떼</h3>
      </div>
    </li>
    )
}
function MenuList() {
  return <ul className="ediya-menu reset-list">
    <MenuListItem/>
    <MenuListItem/>
    <MenuListItem/>
    <MenuListItem/>
  </ul>
  
}
function AppMain() {
  return <main className="app-main">
    <h2 class="a11y-hidden">이디야 음료</h2>
    <MenuList/>
  </main>
}
function App() {
  return <AppMain/>
}

// React Element (JSX)
var app = <App/>

// ReactDOM (rendering)
ReactDOM.render(app, document.querySelector('#app'))
```

{% endtab %}

{% tab title="렌더링 결과" %}
정적 데이터를 갖고 있는 `MenuListItem()`을 4번 불러왔기 때문에 같은 4개의 콘텐츠가 그려진다.&#x20;

```javascript
function MenuList() {
  return <ul className="ediya-menu reset-list">
    <MenuListItem/>
    <MenuListItem/>
    <MenuListItem/>
    <MenuListItem/>
  </ul>
}
```

![](/files/-MSZPYcYYVlxSlM8FaTt)
{% endtab %}
{% endtabs %}

## React 컴포넌트와 전달 속성 (Props)

* MenuList()에 설정한 속성을 MenuListItem()의 첫번째 매개변수인 props의 인자로 받는다.
  * 함수형 컴포넌트의 첫번째 인자는 연결한 컴포넌트의 데이터를 받아온다. &#x20;
* props.image, props.caption으로 속성에 접근할 수 있다.&#x20;
* MenuLietItem()의 HTML코드를 개행해서 보려면 괄호(`()`)로 묶어준다.&#x20;

{% tabs %}
{% tab title="컴포넌트의 속성 " %}
![컴포넌트의 속성에 접근하여 데이터를 불러온다.  ](/files/-MSZdUie7niXK8a3Q5Eu)
{% endtab %}

{% tab title="JS" %}

```javascript
// React Component (Functional)
// props는 함수형 프로그래밍의 첫 번째 매개변수가 된다.
// props는 사용자가 속성을 통해 전달한 데이터를 인자로 받는다. 
function MenuListItem(props) {
  var imagePath = '//raw.githubusercontent.com/yamoo9/assets/master/images/ediya/' + props.image
  return (<li class="ediya-menu__item">
      <a href="#" role="button" aria-haspopup="dialog" aria-pressed="false">
        <figure>
          <img 
            src={imagePath} 
            alt="" 
            width="323" 
            height="323" />
          <figcaption>{props.caption}</figcaption>
        </figure>
      </a>
      <div role="dialog" aria-modal="false" aria-labelledby="dialog-1-label">
        <h3 id="dialog-1-label" class="a11y-hidden">ICED 벚꽃라떼</h3>
      </div>
    </li>
    )
}
function MenuList() {
  return <ul className="ediya-menu reset-list">
    <MenuListItem image="iced-cherry-blossoms-latte.png"
      caption="ICED 벚꽃라떼ᅦ" />
    <MenuListItem         image="hot-cherry-blossoms-latte.png"
      caption="HOT 벚꽃라떼" />
    <MenuListItem image="iced-brownie-chocolate.png"
      caption="ICED 브라우니 쇼콜라"/>
    <MenuListItem image="hot-brownie-chocolate.png"
      caption="HOT 브라우니 쇼콜라"/>
    <MenuListItem image="jeju-green-tangerine-tea.png"
      caption="제주청귤 오리지널"/>
    <MenuListItem image="jeju-green-tangerine-blossom.png"
      caption="제주청귤 블라썸"/>
    <MenuListItem image="pomegranate-tea.png"
      caption="석류 오리지널"/>
    <MenuListItem image="pomegranate-apple-lime.png"
      caption="석류 애플라임"/>
  </ul>
  
}
function AppMain() {
  return <main className="app-main">
    <h2 class="a11y-hidden">이디야 음료</h2>
    <MenuList/>
  </main>
}
function App() {
  return <AppMain/>
}

// React Element (JSX)
var app = <App/>

// ReactDOM (rendering)
ReactDOM.render(app, document.querySelector('#app'))
```

{% endtab %}
{% endtabs %}

## React 개발 환경 구성&#x20;

React로 개발, 컴파이르 번들링 배포하는 과정에 많은 도구의 힘을 빌린다. 그래서 React를 배우기 어렵하고 하는 이유 중의 하나가 이것이다. 해당 도구를 사용할 수 있어야 하기 때문이다.&#x20;

![](/files/-MSZerro529r0MNIxuIl)

## [StackBlitz](https://stackblitz.com/) 실습 환경&#x20;

이전에 자바 스크립트 실습할 때 사용한 codepen이 아닌 StackBlitz를 사용한다.&#x20;

## Create React App

하지만 번거로운 개발 환경 구성 없이 React를 바로 시작할 수 있도록 [create-react-app](https://create-react-app.dev/)을 사용할 수 있다.&#x20;

![](/files/-MSZfjkA5D4Z5c9r8djQ)

### 설치하기&#x20;

```
$ npx -v
$ npx create-react-app <프로젝트-이름>

예시 
$ npx create-react-app study-react 
```

![설치 후 생성된 폴더와 파일 ](/files/-MSZutuJ34icEliBoter)

### 현재 저장소에 설치 하기&#x20;

저장소에 따로 폴더를 만들지 않고 현재 머물고 있는 저장소에 CRA을 설치하고 싶다면 아래와 같이 project name을 입력하는 곳에 `.`을 입력하면 된다.&#x20;

```markup
npx create-react-app .  
```

{% hint style="danger" %}
주의!&#x20;

만약 저장소 또는 프로젝트 이름에 대문자가 들어가면 오류가 발생한다.&#x20;
{% endhint %}

### CRA 명령어

Create React App이 제공하는 명령&#x20;

| 명령어           | 설명                                                                |
| ------------- | ----------------------------------------------------------------- |
| npm start     | React 프로젝트 개발 서버를 시작                                              |
| npm run build | 배포를 위해 앱을 정적(Static) 파일로 번들(Bundle) 한다.                           |
| npm run test  | 테스트 러너(Test Runner)를 시작한다.                                        |
| npm run eject | 사용자 정의 구성(예: Webpack)을 직접 수행할 수 있도록 프로젝트를 준비한다. (※ 주의! 되돌릴 수 없다.) |

## 프로젝트 디렉토리 구조

`src` 디렉토리는 변하는 소스를 넣는다. \
예를들어 이미지의 해시코드가 바뀐다. (이미지경로와 확장자 사이에 해시기호가 붙는다.)

![src 소스에 해시코드를 확인 할 수 있다. ](/files/-MSaQ6VQxzEl_7u1veEN)

`public` 디렉토리는 변하지 않는 정적 소스를 관리한다. \
예를들어 favicon 또는 html, css 등 바꾸지 않을 것들을 관리한다. &#x20;

```
.
├── README.md
├── node_modules/ # 개발 의존 모듈 집합 디렉토리
├── package.json
├── public/ # 정적 리소스 디렉토리
│   ├── favicon.ico
│   ├── image.png
│   ├── video.mp4
│   ├── index.html # 애플리케이션 기본 템플릿
│   └── manifest.json
├── src/ # React 애플리케이션 개발 디렉토리
│   ├── App.css
│   ├── App.js # 애플리케이션 파일
│   ├── App.test.js
│   ├── index.css
│   ├── index.js # 엔트리 파일
│   ├── logo.svg
│   └── serviceWorker.js
└── yarn.lock
```

### public

정적 리소스 디렉토리이며 비디오, 이미지, 정적 html 등이 있다. 비디오와 이미지 파일 등을 index.html에서 불러와서 사용한다.&#x20;

### public/ index.html&#x20;

해당 파일은 React 앱이 구성되는 기본 템플릿 파일이다. 언어(lang)을 설정하거나 필요한 비디오, 이미지와 같은 정적 리소스를 추가할 수 있다.&#x20;

`%PUBLIC_URL%`은 변수처럼 사용된다. `public` 디렉토리를 가리킨다고 보면 된다.&#x20;

`manifest.json` 파일은 사용 되는 메타 데이터의 정보를 제공한다.&#x20;

```markup
<!DOCTYPE html>
<!-- en 값을 ko-KR로 변경 -->
<html lang="ko-KR">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <!--
      manifest.json은 웹 앱을 사용자의 모바일 장치 또는
      데스크톱에 설치할 때 사용되는 메타 데이터를 제공한다.
      참고: https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      위의 태그에서 %PUBLIC_URL%을 사용한다.
      %PUBLIC_URL%은 빌드하는 동안`public` 폴더의 URL로 대체 된다. 
      public 폴더 안에 있는 파일들만 HTML에서 참조 할 수 있다.

      "/favicon.ico"또는 "favicon.ico"과 달리, "%PUBLIC_URL%/favicon.ico"는
      클라이언트 사이드 라우팅(CSR)과 non-root public URL에서 문제없이 작동한다.
      `yarn build` 명령을 실행하면 non-root public URL에 대해 알 수 있다. 
    -->
    <title>React 앱</title>
  </head>
  <body>
    <noscript>이 앱을 실행하려면 JavaScript가 사용가능한 환경이어야 합니다.</noscript>
    <div id="root"></div>
    <!--
      이 HTML 파일은 템플릿이다.
      브라우저에서 직접 열면 빈 페이지가 나타난다. 

      이 파일에 웹 폰트, 메타 태그 또는 Google 애널리스틱(통계, 분석)을 추가 할 수 있다.
      빌드 단계에서 번들 된 스크립트는 <body> 태그 내부에 삽입된다.

      개발을 시작하려면`npm start` 또는 `yarn start`를 실행한다. 
      배포를 위한 번들 파일을 생성하려면 `npm run build` 또는 `yarn build`를 실행한다. 
    -->
  </body>
</html>
```

### src/ index.js

React 애플리케이션의 엔트리(Entry) 파일로 애플리케이션을 구성하는 설정이 포함된다.&#x20;

React, ReactDOM을 불러오며 App.js  파일도 여기서 불온다. 그리고 지막으로 가상 돔요소를 실제 돔요소에 render()하는 작업을 이곳에서 한다&#x20;

### src/App.js

React의 컴포넌트 파일로, 필요한 컴포넌트를 설정하는 작업을 이 파일에서 한다.&#x20;
