# 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;


---

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