티스토리 뷰
Part 1. 시작하며
01. 무엇을 배울 것인가
intex.html
->
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2.2 객체 to DOM Render</title>
<script type="module" src="app.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
app.js
->
function createDOM(node) {
if(typeof node === 'string') {
return document.createTextNode(node);
}
const element = document.createElement(node.tag);
node.children
.map(createDOM)
.forEach(element.appendChild.bind(element));
return element;
}
const vdom = {
tag:'p',
props:{}, //객체요소
children: [
{
tag:'h1',
props:{}, //객체요소
children:["React 만들기"], //문자열
},
{
tag: 'ul',
props: {},
children: [
{
tag: 'uli',
props: {},
children: ["첫 번째 아이템"]
},
{
tag: 'uli',
props: {},
children: ["두 번째 아이템"]
},
{
tag: 'uli',
props: {},
children: ["세 번째 아이템"]
}
]
}
],//자식요소
};
document
.querySelector('#root')
.appendChild(createDOM(vdom));
02. 1타 2피, 3피, 4피
*참고 사이트: https://caniuse.com/
-> 검색 async
DOM 의 문제를 개선시키기 위한 react.js 입니다.
DOM 자체를 사용하지 않는다.
03. 작게 시작하기
*참고 사이트: https://ko.wikipedia.org/wiki/%EC%B5%9C%EC%86%8C_%EA%B8%B0%EB%8A%A5_%EC%A0%9C%ED%92%88
Rreact : 초기엔 'JavaScript Iibrary' 를 가지고 있었다.
Declarative(선언적) : 선언적인 '코드'가 생산되게끔 유도하는게 'React'의 대표 커셈 중 하나
Efficient(효율적인) : 'React'는 'DOM'과 'interaction' 하는 것을 최소화 한다. 그리고 'DOM'에 모의 표현을 사용하여 'DOM'을 처리한다
Flexible(유연성) : 우리가 이미 알고 있는 'library'와 혹은 'Framework'과 같은 것들과같이 동작할 수 있다. 그래서 유연성이 높다.
04. 변경하지 않고 확대하기
*참고 사이트: https://ko.wikipedia.org/wiki/%ED%94%8C%EB%9F%AC%EA%B7%B8%EC%9D%B8
05. 웹프론트앤드 개발환경
*참고 사이트:
https://webpack.kr/
https://babeljs.io/
Part 2. React 만들기
01. 해결책 만들기
02. 객체 to DOM Render
html
->
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2.2 객체 to DOM Render</title>
</head>
<body>
<div id="root"></div>
<script src="app.js" type="module" defer></script>
</body>
</html>
app.js
->
function createDOM(node) {
if(typeof node === 'string') {
return document.createTextNode(node);
}
const element = document.createElement(node.tag);
node.children
.map(createDOM)
.forEach(element.appendChild.bind(element));
return element;
}
const vdom = {
tag:'p',
props:{}, //객체요소
children: [
{
tag:'h1',
props:{}, //객체요소
children:["React 만들기"], //문자열
},
{
tag: 'ul',
props: {},
children: [
{
tag: 'li',
props: {},
children: ["첫 번째 아이템"]
},
{
tag: 'li',
props: {},
children: ["두 번째 아이템"]
},
{
tag: 'li',
props: {},
children: ["세 번째 아이템"]
},
]
}
],//자식요소
};
document
.querySelector('#root')
.appendChild(createDOM(vdom));
--> 화면이 나오지 않아 오류 확인중...
03. webpack 과 babel 세팅
터미널을 키고
npm init -y
개발환경 설정하기
npm install webpack-cli --save-dev
npm install webpack-dev-server babel-loader @babel/core @babel/preset-env @babel/preset-react html-webpack-plugin --save-dev
다음 webpack.config.js 파일을 만든다.(node.js)
html
->
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2.3 setup webpack & babel</title>
</head>
<body>
<div id="root"></div>
<script src="app.js" type="module" defer></script>
</body>
</html>
app.js
->
const HtmlWbpackPlugin = require('html-webpack-plugin');
const path= require('path');
module.exports = {
mode: 'development', //객체 입력정보(어떤 자바스크립트의 정보를 입력할지)
entry: './app.js', //키
output: { //출력
path: path.resolve(__dirname,'dist'),
filname: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/, //정규식으로 패턴화
use: {
loader:'babel-loader',
}
options: {
presets:["@babel/preset-env", "@babel/preset-react"]
}
}
]
},
plugins: [
new HtmlWbpackPlugin({
title: '2.3 setup webpack & babel',
template: 'index.html'
})
]
}
//기본적인 세팅
*참고사이트: https://www.npmjs.com/
검색: html-webpack-plugin
파일 생성 bable.config.json
package.json에 추가
"scripts": {
"webpack": "webpack",
"dev": "webpack serve",
"test": "echo \"Error: no test specified\" && exit 1"
},
터미널에서 npm run dev 실행 확인 하기
-->>실행이 안됨;; 뭔지 모르겠지만
html
->
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2.3 setup webpack & babel</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
app.js / react.js 폴더 나누기
app.js (상위폴더 src 안으로 넣기)
->
import { createDOM, render } from "./react";
const vdom = {
tag:'p',
props:{}, //객체요소
children: [
{
tag:'h1',
props:{}, //객체요소
children:["React 만들기"], //문자열
},
{
tag: 'ul',
props: {},
children: [
{
tag: 'li',
props: {
style: "color:red",
},
children: ["첫 번째 아이템"]
},
{
tag: 'li',
props: {
style: "color:blue",
},
children: ["두 번째 아이템"]
},
{
tag: 'li',
props: {
style: "color:green",
},
children: ["세 번째 아이템"]
},
]
}
],//자식요소
};
render(vdom, document.querySelector('#root'));
react.js (상위폴더 src 안으로 넣기)
->
export function createDOM(node) {
if(typeof node === 'string') {
return document.createTextNode(node);
}
const element = document.createElement(node.tag);
Object.entries(node.props)
.forEach(([name, value]) => element.setAttribute(name, value));
node.children
.map(createDOM)
.forEach(element.appendChild.bind(element));
return element;
}
export function render(vdom, container) {
container.appendChild(createDOM(vdom));
}
04. create Element
app.js
->
import { createDOM, createElement,render } from "./react";
const vdom = createElement('p', {},
createElement('h1', {}, "React 만들기"),
createElement('ul', {},
createElement('li', { style: "color:red", "첫 번째 아이템"}),
createElement('li', { style: "color:blue", "첫 번째 아이템"}),
createElement('li', { style: "color:green", "첫 번째 아이템"}),
)
);
console.log(vdom);
render(vdom, document.querySelector('#root'));
05. @jsx
app.js
->
import { createDOM, createElement,render } from "./react";
const vdom = <p>
<h1>React 만들기</h1>
<ul>
<li style="color:red">첫번째 아이템</li>
<li style="color:blue">두번째 아이템</li>
<li style="color:green">세번째 아이템</li>
</ul>
</p>
console.log(vdom);
render(vdom, document.querySelector('#root'));
react.js
->
export function createDOM(node) {
if(typeof node === 'string') {
return document.createTextNode(node);
}
const element = document.createElement(node.tag);
Object.entries(node.props)
.forEach(([name, value]) => element.setAttribute(name, value));
node.children
.map(createDOM)
.forEach(element.appendChild.bind(element));
return element;
}
export function createElement(tag, props, ...children) {
return {tag, props, children};
}
export function render(vdom, container) {
container.appendChild(createDOM(vdom));
}
06. 함수 컴포넌트
app.js
->
import { createDOM, createElement,render } from "./react";
function Title(props) {
console.log('여기는 타이틀');
return <h1>{ props.children }</h1>;
}
function Item(props) {
return <li style={`color:${props.color}`}>{props.children}</li>
}
const vdom = <p>
<Title label="React">React 정말 잘 만들기</Title>
<h1>React 만들기</h1>
<ul>
<Item style="color:red">첫번째 아이템</Item>
<Item style="color:blue">두번째 아이템</Item>
<Item style="color:green">세번째 아이템</Item>
</ul>
</p>
console.log(vdom);
render(vdom, document.querySelector('#root'));
react.js
->
export function createDOM(node) {
if(typeof node === 'string') {
return document.createTextNode(node);
}
const element = document.createElement(node.tag);
Object.entries(node.props)
.forEach(([name, value]) => element.setAttribute(name, value));
node.children
.map(createDOM)
.forEach(element.appendChild.bind(element));
return element;
}
export function createElement(tag, props, ...children) {
props = props || {};
if(typeof tag === 'function') {
if(children.length > 0){
return tag({
...props,
children: children.length === 1 ? children[0] : children,
})
} else{
return tag(props);
}
} else {
return { tag, props, children };
}
}
export function render(vdom, container) {
container.appendChild(createDOM(vdom));
}
07. 클래스 컴포넌트
app.js
->
import { createElement, render, Component } from "./react";
function Title extends Component {
render(){
return <h1>{ props.children }</h1>;
}
}
function Item(props) {
return <li style={`color:${props.color}`}>{props.children}</li>
}
const vdom = <p>
<Title label="React">React 정말 잘 만들기</Title>
<h1>React 만들기</h1>
<ul>
<Item style="color:red">첫번째 아이템</Item>
<Item style="color:blue">두번째 아이템</Item>
<Item style="color:green">세번째 아이템</Item>
</ul>
</p>
console.log(vdom);
render(<App/ >vdom, document.querySelector('#root'));
react.js
->
export function createDOM(node) {
if(typeof node === 'string') {
return document.createTextNode(node);
}
const element = document.createElement(node.tag);
Object.entries(node.props)
.forEach(([name, value]) => element.setAttribute(name, value));
node.children
.map(createDOM)
.forEach(element.appendChild.bind(element));
return element;
}
export function createElement(tag, props, ...children) {
props = props || {};
if(typeof tag === 'function') {
if (tag.prototype instanceof Component){
const instance = new tag(makeProps(props, children));
return instance.render();
}
if(children.length > 0){
return tag({
...props,
children: children.length === 1 ? children[0] : children,
})
} else{
return tag(props);
}
} else {
return { tag, props, children };
}
}
export function render(vdom, container) {
container.appendChild(createDOM(vdom));
}
08. virtual DOM
*참조사이트: https://awesomeopensource.com/projects/virtual-dom
app.js
->
import { createElement, ,render, Component } from "./react";
function Title extends Component {
render(){
return <h1>{ props.children }</h1>;
}
}
function Item(props) {
return <li style={`color:${props.color}`}>{props.children}</li>
}
const vdom = <p>
<Title label="React">React 정말 잘 만들기</Title>
<h1>React 만들기</h1>
<ul>
<Item style="color:red">첫번째 아이템</Item>
<Item style="color:blue">두번째 아이템</Item>
<Item style="color:green">세번째 아이템</Item>
</ul>
</p>
render(<App/ >vdom, document.querySelector('#root'));
react.js
->
export class Component {
constructor(props) {
this.props = props;
}
}
export function createDOM(node) {
if(typeof node === 'string' || typeof node === 'number') {
return document.createTextNode(node);
}
const element = document.createElement(node.tag);
node.props && Object
.entrieds(node.props)
.forEach(([name, value]) => element.setAttribute(name, value));
node.children && node.children
.map(createDOM)
.forEach(element.appendChild.bind(element));
return element;
}
function makeProps(props, children){
return {
...props,
children: children.length === 1 ? children[0] : children
}
}
export function createElement(tag, props, ...children) {
props = props || {};
if(typeof tag === 'function') {
if (tag.prototype instanceof Component){
const instance = new tag(makeProps(props, children));
return instance.render();
}
if(children.length > 0){
return tag({
...props,
children: children.length === 1 ? children[0] : children,
})
} else{
return tag(props);
}
} else {
return { tag, props, children };
}
}
export function render(vdom, container) {
container.appendChild(createDOM(vdom));
}
export const render = (function() {
let prevDom = null;
return function(vdom, container) {
if(prevDom === null) {
prevDom = vdom;
}
container.appendChild(createDOM(vdom));
}
})();
09. 마법의 Hook 원리와 제약
*참조사이트: https://reactjs.org/docs/hooks-faq.html#gatsby-focus-wrapper (react 공식 홈페이지)
react.js
->
export class Component {
constructor(props) {
this.props = props;
}
}
export function createDOM(node) {
if(typeof node === 'string' || typeof node === 'number') {
return document.createTextNode(node);
}
const element = document.createElement(node.tag);
node.props && Object
.entrieds(node.props)
.forEach(([name, value]) => element.setAttribute(name, value));
node.children && node.children
.map(createDOM)
.forEach(element.appendChild.bind(element));
return element;
}
function makeProps(props, children){
return {
...props,
children: children.length === 1 ? children[0] : children
}
}
function useState(initValue) {
if (!hook[currentComponent]) {
hooks[currentComponent] = initValue;
}
const modifier = nextValue => {
hooks[currentComponent] = nextValue;
};
return[ hooks[position], modifier ];
}
export function createElement(tag, props, ...children) {
if(typeof tag === 'function') {
if (tag.prototype instanceof Component){
const instance = new tag(makeProps(props, children));
return instance.render();
}
hooks[currentComponent] = null;
currentComponent++;
if (children.length > 0) {
return tag(makeProps(props, children));
} else {
return tag(props);
}
}
return { tag, props, children };
}
export function render(vdom, container) {
container.appendChild(createDOM(vdom));
}
export const render = (function() {
let prevDom = null;
return function(vdom, container) {
if(prevDom === null) {
prevDom = vdom;
}
container.appendChild(createDOM(vdom));
}
})();
10. 사이드 이펙트
실제로 'DOM'의 문제를 해결하기 위해서 제안했던 방법이 나름의 사이드 이펙트로 장점으로 승화되는 측면들이 많다.
그 승화되는 측면들이 '프론트엔드' 업계에 굉장히 많은 기술적인 진보를 가져왔다.
ex) virtual DOM