Virtual DOM
부드럽고 빠르며 아키텍쳐에 대한 고민이 적다.
CDN
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
React 시작하기
function helloWorldButton() {
return React.createElement(
"button",
{ onClick: () => {} },
"Hello, React World!"
);
}
const e = React.createElement;
const domContainer = document.querySelector('#app');
const root = ReactDOM.createRoot(domContainer);
root.render(e(helloWorldButton));
1. React.createElement() 를 만들어주는 함수 선언
2. dom 위치를 찾아주고
3. ReactDOM.createRoot() 로 해당 위치를 넣어준 다음,
4. root 위치에 리액트 엘리먼트를 render() 해준다.
function helloWorldButton() {
const [isClick, setClickState] = React.useState("It isn't clicked");
console.log(isClick);
return React.createElement(
"button",
{ onClick: () => setClickState("It's Clicked!") },
isClick
);
}
const e = React.createElement;
const domContainer = document.querySelector('#app');
const root = ReactDOM.createRoot(domContainer);
root.render(e(helloWorldButton));
리액트는 함수의 형태로 '컴포넌트' 로 관리
함수로 html 요소를 만들어내고 관리하는 것
State
리액트의 상태
컴포넌트의 상태를 js 처리로 html 을 변경시켜주는? 그런 것..
React.useState(상태)로 배열 형식으로 비 구조화 할당을 사용
JSX (Javascript XML)
자바스크립트와 xml/html 을 섞어서 사용하는 개념, 리액트에서 사용됨
개발자들이 DOM 방식으로 html을 그리다보니 이게 바로 납득이 안가서 만들어짐
html 문서 구조를 js 에서도 사용이 가능
다만 이를 읽기 위해선 Babel 이라는 컴파일러가 필요하다
Babel ?
JS 컴파일러로, ES6 가 나오고 브라우저에서 지원하지 않고 ES5 와 충돌이 잦아서 ES6 -> ES5 으로 변환해주던 기능을 했는데 요즘은 브라우저에서 ES6 지원이 대부분 되므로 다른 추가적인 언어들에 대한 컴파일러 역할을 해준다. 대표적인 것인 React 이다.
Webpack ?
자바스크립트는 별 기능이 없던 언어로 웹이 커지고 요구하는 것이 많아지다보니 기능이 추가되기 시작했고
모든 기능을 모두 넣어서 사용하고자 하니 용량의 문제가 생기고
필요한 기능을 필요한 순간에 모듈 형태로 불러와서 사용을 하고 배포할 때 필요없는 기능을 빼고 빌드하는 방식을 사용하게 되었는데
이는 브라우저가 지원하지 않는다고 한다.
그래서 등장한 Webpack 으로 빌드 할 때, 의존성이 있는 모듈을 모아서 하나의 파일로 만들어주는 역할을 해준다고 한다.
하지만 React 를 하려면 바벨과 웹팩을 설정해줘야 하는 것이 아닌,
Create-react-app
https://ko.reactjs.org/docs/create-a-new-react-app.html
해당 방법을 사용해서 리액트 애플리케이션을 만든다!
npx (node package exute)
노드를 실행하기 위한 명령어로 npm 와 달리 최신 버전의 패키지를 임시로 설치해서 실행하는 용도로 사용된다.
한번만 임시로 설치해서 해당 node 를 실행시키고 사라진다!
그래서 npm 에 대한 의존성이 없기에 다른 nodejs 버전으로 이동도 가능하고 자유로운 코드 공유가 가능하다.
리액트를 위해 많은 패키지가 필요하지만 그럴때마다 로컬에 패키지를 설치하면 낭비가 심할테니 한번만 설치하고 할일이 끝나면 삭제되어 사라진다.
create-react-app 으로 리액트 프로젝트 만들기
npx create-react-app my-app
** create-react-app 으로 리액트 프로젝트 만들 때, 프로젝트명에 대문자를 넣어주지 않아야 한다.
cd my-app // 만들어진 리액트 프로젝트 폴더에 이동
npm start // 리액트 프로젝트 실행 명령 - 개발용
프로젝트 폴더 살펴보기
public
index.html 하나로 SPA 로 하나의 웹페이지로 구동
<!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>
여기다가 직접 건드려서 웹페이지를 만들어주지 않는다.
src
// 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>
);
reportWebVitals();
// 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;
모듈은 노드와 달리 CommonJS 가 아닌 ES6 방식으로 쓰인다.
기본 프로젝트의 검사창의 네트워크를 확인하면
2.6mb 나 사용됨을 알 수 있다. 이유는 리액트에서 필요한 필수 모듈 등이 전부 들어와 있기 때문이다.
이는 Webpack 이 압축하기 전이므로 빌드를 하면 줄어든다.
리액트 프로젝트 빌드 하기
npm run build
그러면 웹팩이 필요한 모듈만 가져와서 빌드할 것임
빌드가 성공하면, 해당 폴더 안에 build 폴더가 생긴다.
build 폴더 안의 static 폴더 안에 브라우저가 이해할 수 있는 코드들이 들어있다.
빌드 내용을 서버로 확인하기
npx serve -s build
웹팩으로 1.0mb 로 리소스 크기가 줄었다.
Component
리액트의 핵심 개념
기존의 웹 페이지들은 웹 페이지의 작은 부분이 업데이트 되어도 페이지 전체를 리로딩 해줘야 했지만,
리액트 컴포넌트 단위로 페이지 새로고침이 가능하여 리소스 절약이 가능하고 사용자에게 부드럽고 빠른 경험을 제공한다.
독립적으로 구성하여 재사용이 편리함
데이터는 속성(props)으로 받고, 상태(state) 에 따라 view 를 변화한다.
컴포넌트는 기본적으로
1. .jsx 파일로(js OK)
2. 함수 형태로 만든다
3. 원하는 html 모양은 return ( ) 안에 써준다. - 다만 return 안 html 들을 전부 감싸는 상위 태그가 필요함!
4. 마지막에 export default 함수명; 으로 내보내준다.
5. 위에서 만들어준 컴포넌트를 사용하기 위해선 import 변수명 from 상대경로 형태로 받아주고
6. jsx 파일은 결국 html 이므로 사용을 위해선 import로 지정해준 변수명을 태그에 넣어서(<변수명 />) 사용해준다.
- 리액트 컴포넌트의 첫글자는 대문자를 사용한다(필수) -> PascalCase 사용이 관례
- 컴포넌트는 JS에서 클래스 또는 생성자 함수와 비슷한 역할을 하기 때문 (정의 -> 재사용)
- 그리고 컴포넌트는 클래스로 만들어졌기 때문임
- 컴포넌트 레벨에서 변화가 있을 때 페이지가 자동으로 해당 부분만 리렌더링 해주므로 새로고침 하지 않아도 되는 것이다. (이는 가상돔의 효과이다)
function MainHeader() {
// 기능 -> 자바스크립트 ok
const pororo = '뽀로로';
const friend = '친구들';
// 리턴 -> jsx, 자바스크립트와 html 둘다 ok
return (
<div>
<h1>Hello, Component?</h1>
<p>{pororo} {friend} 안녕</p>
</div>
)
}
export default MainHeader;
* jsx파일에서 리액트의 경로는 기본적으로 public 부터 시작하므로 public 폴더 아래에 image 폴더를 만들어서 관리한다.
** css 파일에서 경로는 src 폴더를 기준으로 한다.
이미지를 public 폴더? src 폴더?
public 폴더 -> 프론트에서 접근 | src 폴더 -> 백엔드에서 접근 |
앱이 컴파일될 때 사용하지 않는 모든 것 | 앱이 컴파일 될 때 사용하는 모든 것 |
절대 경로 사용 가능 | 개발하면서 작업하는 파일 (js, css 등) |
정적 파일을 담는 곳 | 컴포넌트 안에서 사용하는 이미지는 src 폴더에 있어야 함 |
<img src="/image.jpg" /> | <img src={require('../../assets/image.jpg')} /> |
웹팩에 의해 관리되지 않는다! - minify 되지 않고 content hash 가 포함되지 않고 원본이 build 폴더에 복사된다. |
파일을 찾지 못하는 경우 컴파일 단계에서 에러를 잡을 수 있음 |
public 폴더에 접근하기 위해선 PUBLIC_URL 환경변수를 사용해야한다 | import 할 경우 참조할 수 있는 경로 문자열을 출력함 |
경로가 잘못 되었거나 파일이 없을 경우 컴파일 단계에서 에러가 발생하지 않고 404 에러 발생 | content hash 가 파일명에 포함되기 때문에 브라우저가 오래된 버전의 파일을 캐싱하고 있는 경우를 고려하지 않아도 됨 ( 파일이 변경되었을 때만 hash 값이 변경됨) |
minifest.webmanifest 처럼 build 된 결과물에서 특정한 파일 이름이 필요한 경우나 수천 개의 이미지 파일을 동적으로 참조해야 하는 경우에 public 폴더 관리가 유용하다. | 서버 요청 횟수를 줄이기 위해 10,000bytes 이하의 이미지는 경로 대신 data url 을 반환 (bmp, gif, jpg, jpeg, png 에만 적용/svg 파일 제외) |
src 폴더에 있는 이미지는 import 나 require 를 사용 가능 다만, public 폴더에 있는 이미지는 상대경로로 접근 가능
node.js 환경이므로 require 로 문서 어디서나 파일을 불러올 수 있다.
// import 이미지변수 from "상대경로";
function ImgComponent() {
return (
<div>
{/* public 폴더에 넣기 */}
<img src="/tistory.png" />
{/* src 폴더에 넣기
<img src={이미지변수} />
*/}
</div>
);
}
export default ImgComponent;
<React.StrictMode> ?
// index.js
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
React.StrictMode 를 써주면 <App /> 을 빠르게 2번 실행시켜준다 - 안정화..? 를 위해서인 듯
기본적으로 리액트는 기존 JS 문제점을 보완하기 위하여 프레임워크 레벨에서 자체적으로 Strict 모드를 강제한다.
컴포넌트의 종류 - 클래스형 컴포넌트 / 함수형 컴포넌트
클래스형 컴포넌트
- 최초로 사용되었던 컴포넌트
- 컴포넌트 자체가 JS 의 class 와 유사하기에 사용
- state 와 라이프사이클이라는 리액트의 장점을 사용 가능
- 메모리 자원도 많이 먹고 느림
- render() 함수를 사용해야만 그릴 수 있음
import React, {Component} from 'react';
class ClassComponent extends Component {
render() {
return(
// html 작성
);
}
}
export default ClassComponent;
함수형 컴포넌트
- 함수를 컴포넌트화 시킨 것
- 구조 자체가 클래스에 비해 단순
- 메모리를 덜 먹고 빠름 -> 특히 render 함수가 빠짐
- state 와 라이프 사이클 기능이 사용이 불가능 했지만 최근 Hooks 이라는 기능 도입으로 같은 역할을 수행할 수 있게 됨
- 클래스형 컴포넌트 보다 우세!
const FunctionComponent = () => {
return (
// html
);
};
export default FunctionComponent;
'학원에서 배운 것 > React' 카테고리의 다른 글
KDT 5th 웹개발자 입문 수업 40일차 (0) | 2023.03.31 |
---|---|
KDT 5th 웹개발자 입문 수업 39일차 (0) | 2023.03.30 |
KDT 5th 웹개발자 입문 수업 38일차 (0) | 2023.03.29 |
KDT 5th 웹개발자 입문 수업 37일차 (0) | 2023.03.28 |
KDT 5th 웹개발자 입문 수업 36일차 (0) | 2023.03.27 |