24. 모듈 소개
지난 섹션에서:
- 리액트에 관한 일반적인 개요: 리액트란? React is a JavaScript library for building user interfaces
- 왜 리액트를 사용하는지 React makes building complex, interacive and reactive UI simpler
이번 섹션에서:
- 어떤 종류의 리액트 앱을 구축하더라도 알아야 할 모든 기본적인 사항Working with Components Working with Data
- React Core Syntax & JSX: What is JSX, Why we use it?
- 모든 기본 기능
- 연 단위로 비용 조회
- 필터링할 경우 사용자 인터페이스 자동 업데이트 with 애니메이션
- 새 비용 추가/수정/삭제 등
- 간단 예제: 비용 추적기 프로그램
- 컴포넌트 중심의 사용자 인터페이스 구축 방법
- Building Interacitve & Scalable UIs**
- **Component-Driven User Interfaces
25. React is all about “Components”
Because all UI in the end are made up of components
컴포넌트가 왜 리액트에서 중요한 개념인지: 그 이유는, 모든 사용자 인터페이스가 결국 컴포넌트로 구성되기 때문
So, what could be a component?
그럼 어떤 것이 컴포넌트가 될 수 있는가: 인터페이스를 구성하는 빌딩 블록들
비용 추적기에서의 컴포넌트

- 같은 비용 아이템이 데이터만 달라진 채 반복됨
- 같은 모양의 차트 막대가 다른 이름과 다른 금액을 담고 반복됨
In the end, “Components” are just combination of html code, css code for styling and possibly JS for some logic.
결국 컴포넌트는 스타일을 만드는 HTML과 CSS 코드, 그리고 어떤 로직을 위한 자바스크립트의 결합일 뿐
컴포넌트를 만들기 위해 컴포넌트를 재사용할 필요는 없음
각각의 컴포넌트를 구축한 뒤엔 최종 UI에서 어떻게 구성할 것인지 명령
Why Components?
재사용 가능
- 반복 회피 → 코드베이스를 작고 관리 가능한 단위로 유지
- 우려사항 분리 가능 각각의 컴포넌트가 하나의 명확한 과제에 초점을 맞춰 집중할 수 있음
Split big chunks of code into multiple smaller functions
- 여러 함수로 코드를 분리하고 웹 응용 프로그램을 위해 코드를 해석
26. 선언적 방식으로 작성된 리액트
How Is A Component Built?
컴포넌트는 어떻게 만들어질까요?
- 컴포넌트는 UI 구성 요소인 HTML, CSS, JavaScript를 결합하고,
- 전체 UI를 구축하기 위해 이 컴포넌트를 결합
선언적 접근 방식(Declarative Approach)
어떻게 해야 하는지보다 무엇과 같은지 설명하는 프로그램 간결하고, *‘어떤 것을 보여줄 것인가’*에 집중할 수 있다는 장점이 있음
중요한 것은, 컴포넌트를 잘 결합하여 구축하는 것
React allows you to create re-usable and reactive components consisting of HTML and JavaScript (and CSS)
Vanilla JS에서:
HTML 요소 생성 후 UI에서 어떤 위치에 삽입되어야 하는지 명령
// Hello, World! 화면에 출력하기
// 순수 javaScript 명령형 코드
const root = document.getElementById('root');
const header = document.createElement('h1');
const headerContent = document.createTextNode(
'Hello, World!'
);
header.appendChild(headerContent);
root.appendChild(header);
React JSX에서:
원하는 최종 상태(목표 상태)를 다양한 상황에 따라 정의
- JS에서 하는 것처럼 DOM 업데이트 구문을 구체적으로 작성할 필요 X
- 실제 웹 페이지에 어떤 요소가 추가, 삭제, 업데이트되어야 하는지 해결
// React 코드 (선언적인)
const header = <h1>Hello, World!</h2>; // jsx
ReactDOM.render(header, document.getElementById('root'));
27. A Note about New React & Node.js
앞으로 진행할 리액트 프로젝트에서는 Node.JS LTS 버전을 사용합니다. Node.JS 17 버전에서는 프로젝트가 작동하지 않습니다.
새 React 프로젝트와 NodeJS에 대한 참고 사항 새로 생성한 React 프로젝트를 실행하는 도중에 ‘digital envelope routines unsupported’ 오류가 발생한다면, 그 이유는 NodeJS 버전 때문이므로, 이 오류가 발생한다면, package.json 파일에서 다음을 교체하십시오.
// package.json "start": "react-scripts start" "build": "react-scripts build" // 부분을 아래와 같이 바꿔주세요. "start": "react-scripts --openssl-legacy-provider start" "build": "react-scripts --openssl-legacy-provider build"
28. 새로운 리액트 프로젝트 생성하기
Create React App
리액트 프로젝트를 생성하는 가장 쉬운 방법
- 기본적인 리액트 코드 파일과 환경설정 파일들이 존재
- 웹 개발 서버를 통해 로컬 컴퓨터에서 응용 프로그램을 미리보기 가능
- 개발 과정 단순화, 리액트 코드 최적화에 적합
Node.js
브라우저 밖에서 JS코드가 실행될 수 있도록 하는 런타임
- Create React App 툴을 위해 필요
- 프로덕션 레디 프로그램을 구축하기 위해 필요한 변환, 최적화 단계를 위한 개발 서버에서 미리보기를 가능하게 함
프로젝트 생성을 위한 터미널 명령어
cd(디렉토리 변경) npx create-react-app react-complete-guide(프로젝트 생성)
오류 발생할 경우:
- 프록시 방화벽 체크
- VPN Client 체크
- 백신 소프트웨어 체크
cd(디렉토리 변경) npm start(응용 프로그램 미리보기)
localhost:3000에서 자동으로 응용 프로그램 오픈
Create-React-App으로 만들어진 폴더 구성
- 소스 폴더: 우리가 작업하게 될 실제 소스코드가 들어있는 폴더
- package.json 파일: 프로젝트에서 어떤 패키지들을 사용하고 있는지
29. 시작 프로젝트
연습용 시작 상태 구성 완료

30. 표준 리액트 프로젝트 분석하기
index.js
파일이 페이지를 불러올 때마다 처음으로 실행되는 코드 파일
But, 사실 이 코드가 실행되는 것이 아닌 변환된 버전의 코드가 실행되는 것 프로젝트 설정 내에 코드를 변환하고 최적화하는 스크립트가 포함되어있음
//index.js
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
npm start
프로세스를 진행하며 코드를 확인 브라우저에 코드를 전달하기만 하는 것이 아닌 전달 전 코드 변환도 수행
import문의 경우, CSS 파일을 JS 파일로 변환하는 과정을 거침 (일반적인 JS에서는 CSS 파일을 가져올 수 없음)
root.render(<App />);
HTML 코드처럼 보이는 언어가 작동함 (마찬가지로, 일반적인 JS에서는 작동하지 않음)
브라우저로 전달되기 전에 변환 과정을 거침 ⇒ 코드를 더 쉽고 나은 방향으로 작성할 수 있게 됨!
package.json
import ReactDOM from 'react-dom/client'에서 어떤 일이 일어날까? ⇒ react-dom이라는 제 3 라이브러리로부터 ReactDOM 객체를 가져오는 것!
//package.json
{
"name": "fe",
"version": "0.1.0",
"private": true,
"dependencies": {
...
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.3.0",
"react-scripts": "^5.0.1",
...
},
...
}
react와 관련된 두 개의 라이브러리
React 라이브러리에서 파생된 각기 다른 역할을 함
- react-dom
- react
기능을 정의하는 방법
A 파일에 함수를 정의하고 해당 함수를 B 파일에 사용 코드를 여러 파일에 나누고 모든 파일을 작고 관리하기 쉽게 만듦
//index.js
import ReactDOM from 'react-dom/client';
//react-dom에서 ReactDOM 객체를 가져옴
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
//ReactDOM의 createRoot 메서드 호출
//이로 인해 주요 엔트리 포인트 생성
//이 메소드로 인해 public/index.html로 이동
ReactDOM.createRoot의 기능
React로 구축할 전반적인 UI에 대한 주요 훅(Hook), 즉, 엔트리포인트 생성
사용자 인터페이스인 React 애플리케이션을 불러온 웹페이지 상에서 ”어디에 배치해야하는지” React에게 알려줌
Hook이란?
리액트 Hook(훅)은 '함수형 컴포넌트'에서
React state와 생명주기 기능을 연동(hook into)가능하게 합니다.
Hook을 사용하는 이유로는
1. 상태 관련 로직을 추상화하여 '독립적인 테스트'와
레이어 변화 없이 '재사용'이 가능하다는 것입니다.
2. 또, 컴포넌트를 '함수 단위'로 잘게 쪼갤 수 있습니다.
//라이프 사이클 메서드에는 관련 없는 로직이 자주 섞여들어가,
//이로 인해 버그가 쉽게 발생할 수 있는데 이를 방지 가능
3. 그 외에도 클래스 기반 컴포넌트를 지양하고자 하는 목적 등
Hook 사용 규칙으로는
1. 최상위에서만 Hook을 호출해야 한다는 것,
(반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하면 안됩니다)
이 규칙을 따르면 컴포넌트가 렌더링 될 때마다
항상 동일한 순서로 Hook이 호출되는 것이 보장됩니다.
2. '리액트 함수 컴포넌트'에서만 Hook을 호출해야 하고,
일반 JS 함수에서는 Hook을 호출해서는 안됩니다.
index.html
React 애플리케이션 전체에서 사용하는 유일한 HTML 파일 (이것으로 인해 리액트는 SPA-단일 페이지 어플리케이션이 된다.)
React로 다루는 웹 페이지와 UI 사이에 일어나는 모든 변경사항들을 다룸 엔트리 포인트인 단일 HTML파일은 React가 주도하는 사용자 인터페이스가 '렌더링 되어야 하는 위치'
index.html의 <div id="root"></div>는 index.js의 root
const root = ReactDOM.createRoot(document.getElementById('root'));
이 정규 JS (ReactDOM을 사용한) 코드로 선택한 div 태그가 곧, React 애플리케이션의 root (React App이 렌더링 될 곳)이란 걸 알림
그 다음, root 객체를 상수나 변수로 저장하여 render 메소드 호출, 렌더링 하고 싶은 것 (ex.<App/>) 인수로 넣음
App.js의 App/>이란?
//index.js
import ReactDOM from 'react-dom/clinet';
import './index.css';
import App from './App'; //App.js에서 확장자는 JS파일이라면 생략 가능
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);
App은 결국 하나의 컴포넌트, <div id=”root”/> 자리에 렌더링할 컴포넌트
//App.js
function App() {
return(
<div>
<h2>Let's get started!</h2>
</div>
);
}
export default App;
현대 JS에선 함수나 클래스가 있거나 한 파일에 정의한 객체가 있을 때, 다른 파일에 사용하고 싶다면 export와 import로 내보낸 후 가져와야 함
JSX란?
App.js에서 HTML코드를 문제 없이 반환할 수 있는 이유는 React 팀이 개발하고 있는 JSX코드가 백그라운드에서 코드 변환을 해주기 때문
31. JSX 소개
JavaScript XML인 JSX
자바스크립트 안에 HTML 코드를 갖고 있음

친숙한 웹 기반 코드 > 백그라운드에서 변환
실제로 크롬에서 개발자 모드를 활성화하면 복잡한 코드로 변환되어 나타남 이 파일들에 있는 코드는 우리 소스 코드 뿐만이 아니라, 전체 리액트 패키지 코드임
main.chunk.js 파일
43줄 언저리에서 function App()이라는 코드를 찾을 수 있음 이것은 브라우저에서 실행되는 변환된 코드
JSX 구문을 사용하여 일반적으로는 브라우저에서 지원되지 않지만, 화면 뒷단에서 자동적으로 브라우저에서 작동되는 코드로 변환됨
32. 리액트 작동 방식
React is all about “Components“
- 컴포넌트는 자체 html 요소이며 선언적인 접근 방식을 통해 작업함
- 리액트는 실제로 화면에 보이는 것을 업데이트 하는 DOM을 생성하고 실행
//App.js
function App() {
return(
<div>
<h2>Let's get started!</h2>
<p>This is also visible!</p> //단락에 변화를 줌
</div>
);
}
export default App;
App 컴포넌트는 함수처럼 보이지만, index.js에서는 자체 HTML요소처럼 사용되는 컴포넌트
JS vs JSX
명령형 접근 방식 (일반적인 JS)
Vanilla JS에서: HTML 요소 생성 후 UI에서 어떤 위치에 삽입되어야 하는지 명령
// Hello, World! 화면에 출력하기
// 순수 javaScript 명령형 코드
const root = document.getElementById('root');
const header = document.createElement('h1');
const headerContent = document.createTextNode(
'Hello, World!'
);
header.appendChild(headerContent);
root.appendChild(header);
- document.getElementById(’root’)를 입력하고, document.createElement로 새로운 요소를 생성한 뒤에 단락을 추가하고 싶다면 innerHTML=’’을 설정해야 함그리고 이 단락에 textContent를 사용해서 'This is also visible'을 설정하면, DOM에 있는 어떤 위치에 도달해서 append()`를 호출한 다음, 인수에 단락 넣음
- 복잡하고 번거롭거나, 변경되는 수백개의 요소들이 있고, 계속해서 나타났다 사라졌다 할 수도 있는 복잡한 UI가 될 수도 있음
선언적 접근 방식 (Declarative Approach in JSX)
React allows you to create re-usable and reactive components consisting of HTML and JavaScript (and CSS)
- 어떻게 해야 하는지보다 무엇과 같은지 설명하는 프로그램 간결하고, *‘어떤 것을 보여줄 것인가’*에 집중할 수 있다는 장점이 있음
- 중요한 것은, 컴포넌트를 잘 결합하여 구축하는 것
React JSX에서: 원하는 최종 상태(목표 상태)를 다양한 상황에 따라 정의
// React 코드 (선언적인)
const header = <h1>Hello, World!</h2>; // jsx
ReactDOM.render(header, document.getElementById('root'));
- JS에서 하는 것처럼 DOM 업데이트 구문을 구체적으로 작성할 필요 X
- 실제 웹 페이지에 어떤 요소가 추가, 삭제, 업데이트되어야 하는지 해결
33. 사용자 지정 컴포넌트 만들기
Why Components?
단순해 보이는 앱을 여러 개의 컴포넌트로 나눔
- 개별적인 차트의막대
- 각가의 비용 아이템
- 새로운 비용을 추가하기 위한 입력 창
한 컴포넌트 당 하나의 파일을 갖기 때문에, 리액트 프로젝트에서 수십, 수백의 컴포넌트를 갖게 됨
Component Tree

컴포넌트: 사용자 인터페이스를 구성하는 조각들 가장 맨 위에 있는 컴포넌트만이 HTML 페이지에 직접 렌더링
컴포넌트 생성 규칙
- 대문자로 시작하는 카멜 케이스
- 함수명도 동일하게 작성
- 실제 사용할때, 원래 HTML코드는 소문자(Ex. <h2 />)로, 컴포넌트는 대문자(Ex. <App />)로 시작하여 사용
App, Modal, ExpenseItem 등
ExpenseItem.js
//ExpenseItem.js
function ExpenseItem() {
return <h2>Expense Item!</h2>
}
export default ExpenseItem;
//App.js
import ExpenseItem from './components/ExpenseItem';
function App() {
return (
<div>
<ExpenseItem></ExpenseItem>
</div>
);
}
export default App;
34. 더 복잡한 JSX 코드 작성
중요한 JSX 코드 작성 규칙
JSX 코드 조각마다 반드시 한 개의 루트 요소를 가짐
Preference > 바로가기 키 > format document
- Shift + Alt + F: 문서 재정렬
확장 > EX7+React/Redex/React Native
- imr: 리액트 임포트
- rfce: 함수형 컴포넌트 생성
- rafce: 명명된 함수형 컴포넌트 생성
- nfn: 명명된 함수 생성
ExpenseItem.js
function ExpenseItem() {
return (
<div>
<div>March 28th 2021</div>
<div>
<h2>Car Insurance</h2>
<div>294.67</div>
</div>
</div>
);
}
export default ExpenseItem;
App.js
import Todo from './components/Todo';
import ExpenseItem from './components/ExpenseItem'
function App() {
return (
<div>
<h1>My Todos</h1>
<Todo text='Learn React' />
<Todo text='섹션 1 학습' />
<h2>Let's get started!</h2>
<ExpenseItem />
</div>
);
}
export default App;
35. 기본 CSS 스타일 추가
CSS 사용 규칙
- import ‘./ExpenseItem.css’ 로 css파일 경로 설정
- class 사용 시 className 사용
- JSX는 HTML처럼 보이게끔 개발자들이 작성해둔 것, 실제가 아님 따라서, class는 JavaScript에서 예약된 단어이기 때문에 리액트에서 CSS를 사용하려면 className을 사용해야 함
ExpenseItem.js
import './ExpenseItem.css';
function ExpenseItem() {
return (
<div className="expense-item">
<div>March 28th 2021</div>
<div className="expense-item__description">
<h2>Car Insurance</h2>
<div className="expense-item__price">294.67</div>
</div>
</div>
);
}
export default ExpenseItem;

36. 동적 데이터 출력 및 표현식 작업
Why Components?

How Is A Component Built?

동적 데이터를 사용해야 하는 이유
날짜, 가격 등의 데이터가 변경되어야 하기 때문
일반적인 JS의 값을 리액트(JSX)에 표시하는 방법
- { }, 중괄호 사용
- 중괄호 내에서 수식 계산 가능
- {1+1} ⇒ 2로 표시
- JS 라이브러리 사용 가능
- {Math.random()} ⇒ 랜덤값 표시
- JS 변수(또는 상수) 표시 가능
- {expenseTitle} ⇒ ‘Car Insurance’ 표시 {expenseDate.toISOString} ⇒ Date객체는 내장 함수로 변환 후 표시

37. “Props”를 통한 데이터 전달
How To Reuse?
태그를 다시 쓰는 것만으로 재사용 가능

Passing Data via “Props”
리액트는 기본적으로 JS와 동일한 개념이 내장되어 있어서, 매개변수나 props를 통해서 재사용할 수 있는 컴포넌트를 만들 수 있음
What’s “Props”?
HTML 요소의 속성처럼, 리액트의 사용자 지정 컴포넌트도 속성을 가짐
- 재사용 가능한 컴포넌트를 만들 수 있게 함
- 다른 컴포넌트에서 컴포넌트로 데이터 전달 가능

props는 properties를 나타내는 것으로, 사용자 지정 컴포넌트의 속성을 설정할 수 있음
App.js
import Todo from './components/Todo';
import ExpenseItem from './components/ExpenseItem'
function App() {
const expenses = [{
id: 'e1',
title: 'Toilet Paper',
amount: 94.12,
date: new Date(2020, 7, 14),
}, {
id: 'e2',
title: 'New TV',
amount: 799.49,
date: new Date(2021, 2, 12)
}, {
id: 'e3',
title: 'Car Insurance',
amount: 294.67,
date: new Date(2021, 2, 28),
}, {
id: 'e4',
title: 'New Desk (Wooden)',
amount: 450,
date: new Date(2021, 5, 12),
}];
return (
<div>
<h1>My Todos</h1>
<Todo text='Learn React' />
<Todo text='섹션 1 학습' />
<h2>Let's get started!</h2>
<ExpenseItem
title={expenses[0].title}
amount={expenses[0].amount}
date={expenses[0].date} />
<ExpenseItem
title={expenses[1].title}
amount={expenses[1].amount}
date={expenses[1].date} />
<ExpenseItem
title={expenses[2].title}
amount={expenses[2].amount}
date={expenses[2].date} />
<ExpenseItem
title={expenses[3].title}
amount={expenses[3].amount}
date={expenses[3].date} />
</div>
);
}
export default App;
<ExpenseItem/> 의 속성으로 title, amount, date를 줌 *title=””*에서 객체 expenses의 프로퍼티에 접근하므로 .프로퍼티명으로 접근
ExpenseItem.js
import './ExpenseItem.css';
function ExpenseItem(props) { // not ExpenseItem(title, amount, date)
// regular JS
const expenseDate = new Date(2021, 2, 28); // 2021년 3월 28일
const expenseTitle = 'Car Insurance';
const expenseAmount = 294.67;
// JSX
return (
<div className="expense-item">
<div>{props.date.toISOString()}</div>
<div className="expense-item__description">
<h2>{props.title}</h2>
<div className="expense-item__price">{props.amount}</div>
</div>
</div>
);
}
export default ExpenseItem;
function ExpenseItem(props) {}에서 매개변수를 props로 설정 props.title, props.amount, props.date로 접근
Props
Properties, 프로퍼티로서 모든 속성을 받는 객체
함수는 한 개의 매개변수를 얻어 사용할 수 있으며, 이 매개변수의 이름은 자유 (일반적으로 props)
주의 사항
props 객체에서 접근하는 키는 App.js에서 작성한 속성 이름과 동일해야 함
38. JS 논리 추가 및 컴포넌트 분할
ExpenseItem.js
import './ExpenseItem.css';
function ExpenseItem(props) {
const month = props.date.toLocaleString('en-US', { month: 'long' });
const day = props.date.toLocaleString('en-US', { day: '2-digit' });
const year = props.date.getFullYear();
return (
<div className="expense-item">
<div>
<div>{month}</div>
<div>{year}</div>
<div>{day}</div>
</div>
<div className="expense-item__description">
<h2>{props.title}</h2>
<div className="expense-item__price">{props.amount}</div>
</div>
</div>
);
}
export default ExpenseItem;
props.date에서 월일, getFullYear로 연도를 가져옴
Number.prototype.toLcaleString()
JS에있는 모든 date 객체에 접근 가능한 내장 메소드 인간이 읽을 있는 형태로 날짜 출력 가능
39. 컴포넌트를 여러 컴포넌트로 분할
컴포넌트 나누기
1. Component in React
응용 프로그램을 더 작은 빌딩 블럭, 컴포넌트로 나눔으로써 모든 빌딩 블럭과 컴포넌트들은 각각 하나의 작업에만 몰두할 수 있음
2. Combining Building Blocks
이 빌딩 블럭들을 결합하여 전체 사용자 인터페이스(UI)를 구축
⇒ And Then…
모든 컴포넌트를 비교적 작고 쉽게 관리할 수 있음
ExpenseItem 분리
ExpenseDate.js
function ExpenseDate(props) {
const month = props.date.toLocaleString('en-US', { month: 'long' });
const day = props.date.toLocaleString('en-US', { day: '2-digit' });
const year = props.date.getFullYear();
return (
<div>
<div>{month}</div>
<div>{year}</div>
<div>{day}</div>
</div>
);
}
export default ExpenseDate;
ExpenseItem.js
import ExpenseDate from './ExpenseDate';
import './ExpenseItem.css';
function ExpenseItem(props) {
return (
<div className="expense-item">
<ExpenseDate />
<div className="expense-item__description">
<h2>{props.title}</h2>
<div className="expense-item__price">{props.amount}</div>
</div>
</div>
);
}
export default ExpenseItem;
여닫는 태그 사이에 컨텐츠가 없다면 < />로 닫아주는게 일반적
Component 사이 Props의 움직임

App(<ExpenseItem date=’’/>) ⇒ ExpenseItem(props.date) 컴포넌트 사용 ExpenseItem(<ExpenseDate date=’’/>) ⇒ ExpenseDate(props.date) 사용
Props 규칙
컴포넌트에서 하위 컴포넌트로 데이터를 직접 보내기 때문에, 다른 컴포넌트의 JSX 코드에 사용되는 컴포넌트는 생략할 수 없음
40-41. 연습하기: 리액트 및 컴포넌트 기본 사항
App에서 Expenses 분리
App.js
import Todo from './components/01Start/Todo';
import Expenses from './components/03ReactBasic/Expense/Expenses';
function App() {
const expenses = [{
id: 'e1',
title: 'Toilet Paper',
amount: 94.12,
date: new Date(2020, 7, 14),
}, {
id: 'e2',
title: 'New TV',
amount: 799.49,
date: new Date(2021, 2, 12)
}, {
id: 'e3',
title: 'Car Insurance',
amount: 294.67,
date: new Date(2021, 2, 28),
}, {
id: 'e4',
title: 'New Desk (Wooden)',
amount: 450,
date: new Date(2021, 5, 12),
}];
return (
<div>
<h1>My Todos</h1>
<Todo text='Learn React' />
<Todo text='섹션 1 학습' />
<h2>Let's get started!</h2>
<Expenses items={expenses} />
</div>
);
}
export default App;
ExpenseItem 대신 Expenses를 추가 이름이 ”items”인 속성(Props)에 Data인 expenses를 연결
Expenses.js
import ExpenseItem from './ExpenseItem';
import './CSS/Expenses.css';
function Expenses(props) {
return (
<div className="expenses">
{props.items ? props.items.map(c => {
return (
<ExpenseItem
title={c.title}
amount={c.amount}
date={c.date} />
)}) : <ExpenseItem />
}
</div>
);
}
export default Expenses;
ExpenseItem과 Expenses.css를 추가하고, 함수 형태로 작성 Props.items.map() 함수로 반복하여 ExpenseItem에 받아온 props를 뿌려줌
42. “컴포지션”의 개념(children prop)
앞으로 배울 것
컴포넌트에 추가할 수 있는 더 많은 기능들 (상호작용, 성능 향상, HTTP 요청 등)
합성(Composition)
작은 빌딩 블럭으로부터 사용자 인터페이스를 구축하는 접근 방법
컴포넌트
JSX 코드를 결합한 사용자 정의 HTML (스타일링) 원한다면, 자바스크립트 로직 추가 가능
다른 컨텐츠를 감싸는 컴포넌트 만들기
- 재사용 가능한 빌딩 블럭 갖기
- 코드 중복 피하기
- 중요! <div/> 안의 요소 가져오려면 props.**children 사용**
Card Component
일반적으로 웹 개발 시에, 둥근 모서리나 옅은 그림자 등의 요소가 있는 컨테이너 모양을 의미
실습 소스 코드
Card.js (Props.children, Props.className}
import './CSS/Card.css'
function Card(props) {
const classes = "card " + props.className;
return <div className={classes}>{props.children}</div>
}
export default Card;
<div/> 안의 요소를 가져오기 위해서 예약어인 props.children을 사용 스타일, 즉 className을 유지하기 위해 props.className을 사용
기타 실습 코드
Card.css
.card {
width: 100%;
border-radius: 12px;
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.25);
}
모서리가 둥글고, 그림자가 진 CSS 스타일을 가져옴
Expenses.js
import ExpenseItem from "./ExpenseItem";
import Card from "../UI/Card"; // Card 사용 위해선 import 필요
import "./CSS/Expenses.css";
function Expenses(props) {
return (
<Card className="expenses">
{props.items ? props.items.map(c => {
return (
<ExpenseItem
title={c.title}
amount={c.amount}
date={c.date} />
)}) : <ExpenseItem />
}
</Card>
);
}
export default Expenses;
// Add, Updated Expenses.css
ExpenseItem.js
import ExpenseDate from "./ExpenseDate";
import Card from "../UI/Card"; // Card 사용 위해선 import 필요
import "./CSS/ExpenseItem.css";
function ExpenseItem(props) {
return (
<Card className="expense-item">
<ExpenseDate date={props.date} />
<div className="expense-item__description">
<h2>{props.title}</h2>
<div className="expense-item__price">${props.amount}</div>
</div>
</Card>
);
}
export default ExpenseItem;
// Add, Updated ExpenseItem.css
다른 수강생의 예시
import ExpenseItem from "./components/ExpreseItem";
import "./App.css";
interface IExpense {
id: string;
title: string;
amount: number;
date: Date;
}
function App() {
const expenses = [
{ id: "e1", title: "First", amount: 1.49, date: new Date(2021.1, 12) },
{ id: "e2", title: "Second", amount: 2.49, date: new Date(2021.2, 12) },
{ id: "e3", title: "Third", amount: 3.49, date: new Date(2021.3, 12) },
{ id: "e4", title: "Forth", amount: 4.49, date: new Date(2021.4, 12) },
];
return (
<>
<h2>Let's Get Started!</h2>
<div className="expenses">
{expenses.map((expense: IExpense) => {
const { id, title, amount, date } = expense;
return <ExpenseItem id={id} title={title} amount={amount} date={date} />;
})}
</div>
</>
);
}
export default App;
이해가 안되는 구문…
고급 구문
// 객체 리터럴 표현을 반환하기 위해서는 함수 본문(body)을 괄호 속에 넣음: params => ({foo: bar}) // 나머지 매개변수 및 기본 매개변수를 지원함 (param1, param2, ...rest) => { statements } (param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements } // 매개변수 목록 내 구조분해할당도 지원됨 var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; f(); // 6
43. 첫 번째 요약
Component-Driven User Interfaces

Building Interative & Scalable UIs 컴포넌트를 만들고 결합해서 사용자 인터페이스를 구축
- 리액트의 핵심 구문과 JSX
- 컴포넌트와 Props로 구축해서 사용
- 데이터로 작업 props를 이용해서 컴포넌트에서 데이터를 공유
How Web & React Works

사용자 지정 컴포넌트 (Card/ExpenseItem 등) 이 없고, <div>나 <h2>같은 것들만 존재
⇒ 사용자 지정 컴포넌트들은 화면에 보이게 하는 진짜 HTML 코드가 아닌, 우리가 작업하는 JSX 코드에서만 사용하는 것
다음 섹션에서는
This APP In Present Section…
고정된 상태의 데이터 (App.js 파일 안, JSON 형태의 비용 배열)
In Next Work Section…
- 응용 프로그램과의 상호작용 방법
- Plus, State의 개념
기억해야 할 것
- JSX의 개념 JSX 안에는 무엇이 있고 어떻게 작동하는지
- 파일을 어떻게 정리하는지
- 함수를 어떻게 작성하는지
44. JSX 자세히 보기
화면 뒷단에서 일어나는 일
Chrome으로 웹 페이지를 살펴보면…

브라우저는 JSX 코드를 지원하지 않기 때문에, 우리가 보는 건 결국 화면 뒷단에서 변환된 코드임
package.json

index.js에서 react-dom을 사용하고 있지만 어디에서도 react는 import되지 않음 그렇다면, react는 어디로 갔을까?
react의 행방
과거 오래된 버전의 리액트 버전에서는, 모든 JSX 리액트 컴포넌트 파일에 import React from 'react'; 구문이 필요했었음
그러나 최신 리액트 프로젝트 셋업에서는 생략 가능
JSX 구문을 사용하지 않을 경우
import React from "react";
// App.js ...
return (
<div>
<h2>Let's get started!</h2>
<Expenses items={expenses} />
</div>
);
return React.createElement(
div,
{},
React.createElement("h2", {}, "Les's get started!"),
React.createElement(Expenses, {items: expenses}, "")
);
// ...
React.createElement();
- 첫 번째 인자: 생성해야 하는 요소 (Ex. <div>)
- 두 번째 인자: 요소를 설정하는 객체 (Ex. <div items={expenses}>)
- 세 번째 인자: 여닫는 태그 사이의 컨텐츠 (Ex. <h2>Let’s get started!</h2>) 또는, 여닫는 태그 사이의 무한대의 컨텐츠 목록
import React from ‘react’;
생략 가능하지만, JSX 코드를 사용할 때 리액트가 사실은 **내부**에서 사용되고 있음을 강조하는 표시
루트 JSX 요소로 왜 래핑 요소가 필요한지에 대한 설명: 반환되는 두 요소를 나란히 가질 수 없기 때문에
// App.js return React.createElement("h2", {}, "Les's get started!"), React.createElement(Expenses, {items: expenses}, "") ; // => 두 요소 동시 반환 불가!! 오류 발생!!
45. 컴포넌트 파일 구성하기

폴더 구분 및 파일 위치 변경할 때, import 구분의 상대 참조 주소를 조정함으로서 정리 가능
46. 대체 함수 문법(syntax)
화살표 함수로 컴포넌트 작성
App.js
import React from "react";
import Todo from "./components/01Start/Todo";
import Expenses from "./components/03ReactBasic/Expense/Expenses";
const App = () => { // or function App() {...}
const expenses = [
// ...
];
return (
<div>
<h2>Let's get started!</h2>
<Expenses items={expenses} />
</div>
);
}
export default App;
짧아서 편할수는 있지만, 어떤 장점이 있진 않음
47. 모듈 리소스
여러분들은 여러분들의 코드를 제 코드와 비교해보고 싶을 수 있습니다 (예: 에러 찾기 + 수정).
그것을 위해, 여러분은 이 모듈의 여러 코드 스냅샷을 이 Github 저장소에서 찾을 수 있습니다.
사용 지침은 이 링크로 연결되는 페이지에서 찾을 수 있습니다.
/code 폴더에서 스냅샷을 고르시면 됩니다
- 하위 폴더 이름은 이 코스 섹션의 강의 이름과 쉽게 일치하도록 설정되었습니다.
여러분은 또한 해당 Github 저장소에서 섹션 슬라이드 (사용 가능한 경우) 를 찾을 수 있습니다.
'React.js > React.js 완벽 가이드 with TS, Redux, Next.js' 카테고리의 다른 글
섹션 5: 렌더링 리스트 및 조건부 Content (0) | 2023.07.03 |
---|---|
섹션 4: 리액트 State 및 이벤트 다루기 (0) | 2023.04.19 |
섹션 2: Next-Gen JS (0) | 2023.04.17 |
섹션 1: 시작하기 - What is react? And Why would we use it? What is SPA? (0) | 2023.04.17 |