728x90
반응형
- 2024-08-28 : First posting.
npm init react-app .
실행하면서 대부분 깔렸을듯. Netlify 같은 remote server 에 올리려면 Bundler 만 필요한거니까...
// 그리고 매 .js file 마다 import React from 'react';
를 안쓰려면, @babel/preset-react 같은걸 깔아야 하는듯?
npm install react react-dom jquery immer use-immer
npm install -g typescript
npm install typescript typescript@next @types/react @types/react-dom @types/jquery ts-loader @babel/preset-typescript --save-dev
tsc --init
```/
typescript 를 깔았기 때문에 project 에 typescript file 이 한개는 존재 해야 함. Error 를 방지하기 위해... 의미없는 빈 .ts file 을 하나 만들어서 넣어줍시다.
```
// * ./src/placeholder.ts
export {};
```/
### 모든 React file 들에서 import React from 'react';
를 생략할 수 있게 만드는 세팅.
우선 최상위 폴더에 react-shim.js
란 file 을 다음과 같이 작성해 줍시다.
```
import React from 'react';
export { React };
```/
그리고 esbuild.config.js
file 을 다음과 같이 설정해 줍시다.
```
import esbuild from 'esbuild';
esbuild.build({
sourcemap: true,
logLevel: 'info',
platform: 'browser',
entryPoints: ['src/index.js'],
bundle: true,
minify: true,
outfile: 'dist/esb-bundle.js',
write: true,
loader: {
'.js': 'jsx',
'.svg': 'file',
'.jpg': 'file',
'.jpeg': 'file',
'.png': 'file',
},
define: { 'process.env.NODE_ENV': '"production"' },
jsxFactory: 'React.createElement',
jsxFragment: 'React.Fragment',
inject: ['./react-shim.js'], // 자동 주입 파일 추가
// Other options...
})
.catch(() => process.exit(1));
```/
마지막 줄 inject 가 핵심. React 18 에서부터인가는 explicit 하게 React 를 import 할 필요가 없다고 들은것도 같은데... esbuild 해보니 React 가 정의되지 않았다고 뜨길래, Copilot 한테 물어봐서 이렇게 해결. 더 좋은 방법도 있을거 같긴 한데... 잘 모르겄음.
한 react-app directory 에 한가지 page 만 구현하지는 않으니까 다음과 같이 esbuild.config.js
를 만들어 놓고 node .\esbuild.config.js [pagename]
을 실행해주면 되는거 같음.
```
import esbuild from 'esbuild';
// Get the page name from the command line arguments
let pageName = process.argv[2];
let dirName = `${pageName}/`;
if (!pageName) {
console.log('Default is index[.js]');
pageName = 'index';
dirName = '';
}
esbuild.build({
sourcemap: true,
logLevel: 'info',
platform: 'browser',
entryPoints: [`src/${pageName}.js`],
bundle: true,
minify: true,
outfile: `dist/${dirName}esb-bundle.js`,
write: true,
loader: {
'.js': 'jsx',
'.svg': 'file',
'.jpg': 'file',
'.jpeg': 'file',
'.png': 'file',
},
define: { 'process.env.NODE_ENV': '"production"' },
jsxFactory: 'React.createElement',
jsxFragment: 'React.Fragment',
inject: ['./react-shim.js'], // 자동 주입 파일 추가
// Other options...
})
.catch(() => process.exit(1));
```/
매번 파일이 수정될때마다 변경된 사항을 다 적용시켜줘야 하니까 build-all.bat
file 을 다음과 같이 만들어놓고 이걸 실행시키면 될거 같음.
```
node .\esbuild.config.js
node .\esbuild.config.js login
node .\esbuild.config.js signup
node .\esbuild.config.js items
```/
### package.json 설정 with esbuild.
이렇게 하면 package.json 은 다음과 같이 됨. TypeScript version 이 너무 높아서 문제가 생기는 것도 같음. 아래 package.json 을 복붙 저장한 다음 npm install
로 까는게 더 안전해 보임.
```
{
"name": "moviepedia",
"version": "0.1.0",
"private": true,
"type": "module",
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"immer": "^10.1.1",
"jquery": "^3.7.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-scripts": "^3.4.4",
"use-immer": "^0.10.0",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": ".\\node_modules\\.bin\\esbuild .\\src\\index.js --loader:.svg=file --loader:.js=jsx --bundle --minify --outfile=.\\dist\\esb-bundle.js",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/preset-typescript": "^7.24.7",
"@types/jquery": "^3.5.30",
"@types/react": "^18.3.4",
"@types/react-dom": "^18.3.0",
"esbuild": "0.23.1",
"ts-loader": "^9.5.1",
"typescript": "^3.2.1"
}
}
```/
일일히 package 들을 install 하기 귀찮다면, 이 package.json 파일만 잘 만들어 저정해 놓고 npm install
혹은 npm install --upgrade
로 까시면 됨.
중간 중간 막히는 부분은 ChatGPT 나 Copilot, Claude, Gemini, Cue 등 AI 에게 물어보면서 해결하시길...
svg 가 제대로 처리가 안되던데 --loader:.svg=file
설정 집어넣으니까 잘 됐던거 같음.
Bundling 실행은 npm run build
### tsconfig.json 설정.
tsconfig.json 설정은 대충 아래와 같이 했고...
```
{
"compilerOptions": {
"target": "ES2022",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "ES2022",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
```/
### esbuild.config.js 설정.
esbuild.config.js 설정은 다음과 같이 함. npm run build
로 bundling 을 하는게 아니라 node .\esbuild.config.js
를 입력해서 bundling 을 해야 하는거 같음.
```
import esbuild from 'esbuild';
esbuild.build({
sourcemap: true,
logLevel: 'info',
platform: 'browser',
entryPoints: ['src/index.js'],
bundle: true,
minify: true,
outfile: 'dist/esb-bundle.js',
write: true,
loader: {
'.svg': 'file',
'.jpg': 'file',
'.jpeg': 'file',
'.png': 'file',
'.js': 'jsx'
},
// Other options...
})
.catch(() => process.exit(1));
```/
### public/index.html 만 남기고 다 지우고 초기화.
```[.lang-html]
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>주사위 게임</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
```/
### index.js 만 남기고 다 지우고 초기화.
```[.lang-jsx]
import ReactDOM from 'react-dom/client';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<h1>안녕 리액트!</h1>);
```/
## 반드시 하나의 요소로 감싸기 - Fragment or <></>
최상위로 원소를 2개 이상 붙이고 싶을 때 쓰는 tag
```
<Fragment>
<div>가위</div>
<div>바위</div>
<div>보</div>
</Fragment>
or
<>
<div>가위</div>
<div>바위</div>
<div>보</div>
</>
```/
## JavaScript JSX 안에 쓰기.
```
import ReactDOM from 'react-dom/client';
const product = "MacBook";
const model = "Air";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<h1>{product} {model} 주문하기</h1>);
```/
{} 안에는 JavaScript 표현식만 가능. if else 같은 건 못 씀.
JSX 문법도 결국은 자바스크립트 문법이기 때문에, for 나 class 처럼 자바스크립트의 문법에 해당하는 예약어와 똑같은 이름의 속성명은 사용할 수 없습니다. 그래서 HTML 의 for 의 경우에는 자바스크립트의 반복문 키워드 for 와 겹치기 때문에 htmlFor
로, HTML 의 class 속성도 자바스크립트의 클래스 키워드 class 와 겹치기 때문에 className
으로 작성해 주어야 합니다.
## Component
React element
React function component: 첫문자는 대문자로 시작해야 함.
React lets you combine your markup, CSS, and JavaScript into custom “components”, reusable UI elements for your app. React components are regular JavaScript functions, but their names must start with a capital letter or they won’t work! Without parentheses, any code on the lines after return will be ignored! https://react.dev/learn/your-first-component
```
function Hello() {
return <h1>Hello World!</h1>
}
```/
## Props and children
기본적으로 React component 는 props 라는 properties (or attributes) 와 React tag 안의 내용물인 children 을 가지고 있는데 이것 모두 function component 에서 첫번째 parameter 로 전달 받을 수 있음.
```
function Dice(props) {
return (<div>
<h2>{props.title}</h2>
<p>{props.description}</p>
<div>{props.children}</div>
</div>);
}
export default Dice;
```/
위의 Dice 란 React component 를 쓰려면 우선 import 를 하고 적절한 props (or attributes) 를 넣어서 전달해 주면 됨.
```
import Dice from "./Dice.js";
function App() {
return (<>
<Dice title="I am title!" description="I am description!">
I am children
<div>Children can be plain text or another react component or HTML elements</div>
<Hello/>
</Dice>
</>)
}
```/
## Refactoring
### Reusing components
### Refactoring
Check out redundancy: 중복
Compute num and sum from records: 계산하는 속성 vs 저장하는 속성 records
num, sum 은 records 로부터 뽑아낼 수 있다.
계산이 오래 걸리거나, 빈번할 경우 귀찮다. 그 경우는 계산 속성도 저장하는게 좋을때도.
### React rendering
첫 rendering: Page 를 처음 불러올 때. Props 로 사용자가 처음 봐야 할 내용/데이터를 전달.
Rerendering (첫 rendering 이후): State 가 바뀔 때.
props, state
state 가 바뀔 때
Virtual DOM 에서 미리 rerendering 을 해보고, 바뀐 부분만 (diff 란 효율적인 중간과정을 거쳐서 :: git 에서 사용되는 diff 랑 비슷한 algorithm) 실제 DOM 에 update 가 필요한 부분만 rerendering.
## inline style
```
<div style={{backgroundColor:"black", fontFamily:"맑은 고딕", color:"white"}}></div>
```/
CamelCase 로 입력 {{}}
두개 써서 JSON object 를 넘겨주는 방식으로...
## CSS className
Create index.css under src.
Import index.css in index.js. (automatically included in head)
## RRA
- https://react.dev/
- https://react.dev/learn/react-developer-tools
- kipid's blog :: React 사용 설정하기 (esbuild) with TypeScript
- geundung.dev :: esbuild 기반 React Native 번들러 개발기
// 토스 개발자로 알고 있음. 유튜브 링크도 있었던거 같긴 한데... Tree Shacking 도 지원하고 multi thread 로 돌아가서 esbuild 가 다른 bundler 보다 훨씬 빠르고 좋다는 결론. - https://publish.obsidian.md/iasandcb/
https://publish.obsidian.md/iasandcb/site/2024-08-26
https://publish.obsidian.md/iasandcb/site/2024-08-27
https://publish.obsidian.md/iasandcb/site/2024-08-28
https://publish.obsidian.md/iasandcb/site/2024-08-29
https://publish.obsidian.md/iasandcb/site/2024-08-30
728x90
반응형