05.08 디지털 트윈 부트캠프 18일차
프론트엔드 - React
UI : User Interface
UX : User Experience
리액트
JS 라이브러리의 하나로 사용자 인터페이스를 만들기 위해 사용
Single Page Apps(SPA)를 쉽게 만들 수 있으며 UI 컴포넌트를 구축하기 위한 도구
MVC
Model - View - Controller
기존 사용되던 사용자 인터페이스
데이터 및 논리 제어를 구현하는데 널리 사용되는 소프트웨어 디자인 패턴
=> 아주 적은 내용이 바뀌었을지라도 매번 실행 => 자원 낭비
DOM
Document Object Model
웹페이지를 이루는 태그들을 JS가 이용할 수 있게 트리구조로 만든 객체
뷰
자바스크립트 기반 프레임워크 - 모델, 뷰
모델: 어플리케이션에서 사용하는 데이터를 관리하는 영역
뷰: 사용자에게 보여지는 부분
렌더링: 사용자 화면에 뷰를 보여주는 것
react에서는 render 함수가 맨 처음 어떻게 보일지를 정한다.
render 함수는 뷰가 어떻게 생겼고 어떻게 작동하는지에 대한 정보를 지닌 객체로, 렌더링 작업이 끝나면 가지고 있는 정보를 이용해 html 마크업 및 이를 우리가 보는 실제 페이지의 DOM 요소 안에 주입한다.
새로운 내용을 이전 내용에 갈아끼우는 작업도 render() 함수가 한다.
가상 DOM
DOM은 문서객체모델로 정리하자면, html 문서를 파싱해 문서의 구성요소를 객체로 구조화하여 나타낸 것이다.
html 엘리먼트, 속성, css 스타일, 이벤트, 메소드 등을 제어하는 DOM은 반복적으로 직접 조작하게 되면 브라우저는 렌더링을 자주하게 되고 그 만큼 렌더링의 비효율성과 복잡도가 증가한다.
따라서 virtual DOM은 조작에 대한 렌더링의 비효율성을 개선하고 SPA의 특징으로 DOM 복잡도 증가에 따른 최적화 및 유지보수를 더 쉽게 하기 위해 DOM을 추상화한 가상의 객체를 사용한다.
변경 내용을 DOM에 직접 수정하는 것이 아닌 중간 단계로 Virtual DOM에 변경 내역을 모으고 실제 DOM과 변경된 virtual DOM의 차이를 판단한 후 구성요소의 변경된 부분만 찾아 변경한 뒤 렌더링은 한 번만 한다.
React
사용자 인터페이스를 만들기 위한 JS의 라이브러리, 컴포넌트 기반
컴포넌트는 코드 조각이라고 할 수 있으며 로직은 JS로 작성된다.
데이터가 변경될 때 React는 컴포넌트를 효율적으로 업데이트하고 다시 렌더링한다.
개별 컴포넌트는 매개변수 props를 받은 후 render 함수를 통해 표시할 뷰 계층 구조, 즉, react 엘리먼트를 반환한다.
npx create-react-app 프로젝트이름
위처럼 npx를 이용해 새로운 react 프로젝트를 생성할 수 있다.
npm run start
위처럼 run이나 start를 하나만 사용하는 것이 아닌 npm run start를 함께 사용해 실행할 수 있다.
처음 생성되는 폴더구조는 위와 같으며, public 안에 있는 index.html이 모든 파일의 기초가 된다.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
index.html의 파일은 이렇게 기초 생성되어있다.
이 중 주석처리된 부분을 지우면
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
이렇게 간편하게 볼 수 있는데, 여기서 잠깐 index.js 파일을 보면
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
이렇게 index.html에 있는 root와 index.js에 있는 root가 연결되어 있는 것을 볼 수 있다.
id가 root인 div 태그가 js파일에서 getElementById를 이용해 불러와져 ReactDOM의 Root로 지정되고 렌더링을 위한 태그가 된 것이다.
root.render 내부를 보면 App 태그가 있는 것을 볼 수 있는데, 과연 이건 뭘까?
이를 확인하려면 App.js 파일로 이동해야한다.
App.js
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
index.js의 App은 App.js와 연결된다.
index.js의 상단 import 부분을 보면 우리는 import App from './App.js' 를 확인할 수 있는데, 이를 통해 App.js의 함수이자 컴포넌트인 App이 불러와져 index.js에서 렌더링되는 것이다.
결국엔 App.js에서 서술되는 태그, 로직 등등 여러 부분이 index.js에서 root를 통해 렌더링되어 index.html에 나타나는 것이다.
따라서 React를 활용하는 가장 보편적인 방법은 App.js 내부의 App 함수의 return 문 안에 렌더링하고 싶은 것들을 작성하는 것이다.
결국은 react를 이해하려면 react를 설치한 후 초기 폴더 구조를 명확히 이해해야 한다.
public
가상 DOM이 들어갈 바지 사장 html(index)가 존재하는 폴더
src
리액트를 이용한 개발이 실제적으로 이루어지는 폴더로 대부분의 파일이 이곳에 저장된다.
components
렌더링되는 페이지 중 공통적으로 사용되는 컴포넌트를 모아둔다.src 폴더 내에 생성된다.
assets
프로젝트에 사용할 이미지, 폰트, json 파일들을 넣는다.주로 public에 생성된다.
컴포넌트
function 뒤에 대문자로 이름을 시작해야 한다.
export default를 사용해 다른 파일에서 불러올 수 있다.
리액트는 여러 개의 컴포넌트를 조합해 웹페이지를 만든다.
컴포넌트는 코드 조각이라고 할 수 있으며 로직은
jsx
주로 카멜케이스로 작성한다. ex) onClick
return () 문 안에 무조건 최상위 태그가 하나만 존재해야 한다.
{boolean}, {null}, {undefined}는 무시 => 유효해도 렌더링 x => 문자열로 전환 후에 출력 가능
{showHeader && Header}에서 showHeader가 true면 <Header /> 컴포넌트를 렌더링한다.
jsx는 react 엘리먼트를 만들고 react 엘리먼트는 브라우저 DOM을 생성한다.
기본적인 js에서는 class, react에서는 className => 실제 DOM으로 렌더링하면 class로 변경되어 html 문법에 맞춰 들어가 있다.
export default: 해당 컴포넌트를 다른 파일에서 사용
ReactDom.render(html코드, html엘리먼트)
지정된 html 엘리먼트 안에 html 코드 표시데이터를 입력 받아 화면에 표시할 내용을 반환하는 역할
React.createElement()
document가 아닌 React의 createElement 함수를 이용해 DOM 요소를 나타내는 개체를 반환한다.
React가 가상 DOM을 사용하기 때문이다.
props & state
둘 다 JS 객체로 렌더링 결과물에 영향을 주는 정보를 갖고 있으나 props는 함수 매개변수처럼 컴포넌트에 전달되고 state는 함수 내 선언된 변수처럼 컴포넌트 안에서 관리한다.
props
데이터, 이벤트 핸들러를 자식 컴포넌트에 전달할 때 사용
한 번 설정되면 변경할 수 없다.상위 컴포넌트는 하위 컴포넌트에 대한 props를 설정한다.
state
뷰에 렌더링되어야 하는 컴포넌트의 데이터를 저장할때 사용
상태는 데이터를 보유하고 시간이 지남에 따라 변경 가능
이벤트 핸들러: 일반적으로 state를 업데이트