라이브러리,프레임워크의 차이
라이브러리: 폴더의 구조가 없음.
프레임 워크:폴더 구조가 있음.
패키지를 설치 할 수 있기 때문에
리액트 개발을 할 때 편하게 초기 세팅을 설치받아서 사용할 수 있다.
메타에서 개발한 것은 react와 react-router 라이브러리
메타에서 개발하고 오픈소스에 기여중임~
리액트를 프레임워크라고 하는 이유?
메타에서 라이브러리를 개발하고
npx create-react-app [폴더명] 구문으로 패키지를 제공해서
react를 개발할 때 권장 개발환경을 구성해준다.
react 프로젝트 설정
그래서 블로그나 개발자들 사이에서 프레임워크라고 하는것.
리액트는 화면을 구성할 때 자바스크립트를 활용해서 html을 조작해줌 dom
효율적인 브라우저 랜더링을 위해
페이지를 효율적으로 업데이트 하기 위해서
react는 가상 DOM을 사용해서 변경된 부분만 다시그림.(업데이트)
일반적인 html은 변경된 부분만 업데이트 하지않고 전체 페이지를 다시 그려주는데
react의 가상 DOM은 메모리에 남아있고 실제 페이지의 DOM은 분리되어있는 상태
react의 상태가 변하면 새 가상 DOM이 생성되고 이전 상태의 가상 DOM과 비교해서
업데이트 해야할 부분믕 찾고 (틀린그림 찾기) 실제 DOM에 업데이트를 해준다.
그래서 효율적인 업데이트가 가능하다.
react를 사용하는 이유
react의 부분 랜더링
react는 view 중심 보여주는 것에 집중된 라이브러리
PHP EJS 이런 SSR
서버에서 페이지를 완성 시켜서 브라우저에 응답해주는것.
클라이언트에서 페이지를 구성하는 것을 하고싶다.
랜더링을 클라이언트 측에서 하고 싶었던것
CSR => React, vue, angular
react는 DOM의 조작을 쉽게 하기 위해서 사용을 하고
SPA를 만들기 위해서 사용한다.
하나의 페이지에서 내용을 바꿔서 페이지가 전환된것 처럼 보여준다.
react를 만든 사람은 자바스크립트를 잘하는 사람들이 만든건 아니고 그냥 개발을 잘하는 사람들이 만든것
class문법으로 되어있음.
다음은 chatGPT의 대답이다.
🖥️React(또한 React.js 또는 ReactJS로 알려져 있음)는 사용자 인터페이스를 구축하기 위한 인기있는 JavaScript 라이브러리로, 특히 싱글 페이지 애플리케이션에 사용됩니다. 이것은 Facebook에서 개발되고 유지되고 있습니다.
React는 페이지 새로고침 없이 데이터 변경에 따라 효율적으로 업데이트하고 렌더링 할 수 있는 대규모 웹 애플리케이션을 만들 수 있게 합니다. React의 핵심 목표는 가능한 최고의 렌더링 성능을 제공하는 것입니다. 그 힘은 전체 웹 페이지가 아닌 개별 컴포넌트에 초점을 맞추는 데서 나옵니다.
다음은 React의 주요 기능입니다:
⇒뒤에 있는 훅과 redux는 아직 배우지 않았으니 언급하지 않겠다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
</body>
<script>
const root = document.querySelector("#root");
// DOM을 직접 다루지 않고 state(상태값)으로 랜더링
let state = {
items: ["아이템1", "아이템2"],
};
const setState = (_state) => {
// 초기 상태값에 추가로 새로운 상태값
state = { ...state, ..._state };
render();
};
// 랜더링 해줄 함수
const render = () => {
// 상태값이 아닌 변수를 그냥 사용하면
// 변수를 다시 선언해서 초기화 된다.
// 그러면 보관해야하는 값은 상태값으로 보관을 해야한다.
let temp = 0;
const { items } = state;
root.innerHTML = `
<ul>
${items.map((a) => {
return `<li>${a} </li>`;
})}
</ul>
<button id='append'> 추가</button>
`;
document.querySelector("#append").addEventListener("click", () => {
//state 변경 시키자.
// react는 상태값을 주시하고 있는데
// 상태를 주시하고 있는 이유는 상태가 변하면 리랜더링 시킨다.
// setState으로만 변경을 하자고 약속함.
setState({ items: [...items, `아이템 ${items.length + 1}`] });
console.log(temp);
temp++;
});
};
// 최초 화면 그려주기
render();
</script>
</html>
let state = {
items: ["아이템1", "아이템2"],
};
const setState = (_state) => {
// 초기 상태값에 추가로 새로운 상태값
state = { ...state, ..._state };
render();
};
const render = () => {
// 상태값이 아닌 변수를 그냥 사용하면
// 변수를 다시 선언해서 초기화 된다.
// 그러면 보관해야하는 값은 상태값으로 보관을 해야한다.
let temp = 0;
const { items } = state;
root.innerHTML = `
<ul>
${items.map((a) => {
return `<li>${a} </li>`;
})}
</ul>
<button id='append'> 추가</button>
`;
document.querySelector("#append").addEventListener("click", () => {
//state 변경 시키자.
// react는 상태값을 주시하고 있는데
// 상태를 주시하고 있는 이유는 상태가 변하면 리랜더링 시킨다.
// setState으로만 변경을 하자고 약속함.
setState({ items: [...items, `아이템 ${items.length + 1}`] });
console.log(temp);
temp++;
});
};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
</body>
<script>
// react의 UI의 기본 단위 컴포넌트
// 컴포넌트는 자주 사용할 것 같은 UI요소의 기본단위 (재사용성)
// 컴포넌트는 상태와 속성을 가지고 있어요.
// react 단방향성 데이터의 흐름
// 부모에서 자식으로 값을 전달해줄 수 있다.
// class
// 컴포넌트 클래스
// 컴포넌트의 모양을 만들거고 상속 받아서 사용할 거임
class Component {
target;
state; //상태값 컴포넌트의 유지되는 데이터
constructor(target) {
// 컴포넌트의 target을 설정
this.target = target;
this.setUp();
this.render();
console.log("최초 render");
}
// 초기 설정
setUp() {
// 컴포넌트를 초기 설정 랜더링 하기전에 동작하는 함수.
console.log("initialize");
}
template() {
// 컴포넌트 HTML 템플릿을 반환 해줄거임
return "없음";
}
render() {
// 컴포넌트를 타겟 요소에 그리기
this.target.innerHTML = this.template();
this.setEvent();
}
setEvent() {
// 컴포넌트 이벤트 세팅
console.log("컴포넌트 이벤트 세팅");
}
setState(_state) {
// 컴포넌트의 상태를 업데이트
// 업데이트 되면 리렌더링
this.state = { ...this.state, ..._state };
console.log(this.state,'asd',_state)
this.render();
console.log("state changed");
}
}
// 가상 DOM클래스 정의
// 렌더링 시킬거임
class VirtualDOM {
constructor(component, target) {
// 매개변수로 전달받은 컴포넌트 생성후 타겟 요소 전달.
// 컴포넌트 클래스 생성자 함수의 매개 변수로 타겟 전달
this.Component = new component(target);
}
render() {
this.Component.template();
}
}
// App class 컴포넌트 상속 받아서 정의
class App extends Component {
setUp() {
// App 컴포넌트 초기세팅 함수
this.state = { items: ["아이템1", "아이템2"] };
}
template() {
// App 컴포넌트의 HTML을 생성 해서 반환
const { items } = this.state;
console.log(items)
return `
<ul>
${items.map((a) => `<li>${a} </li>`)}
</ul>
<button> 추가</button>
`;
}
setEvent() {
// App 컴포넌트의 이벤트 등록
this.target.querySelector("button").addEventListener("click", () => {
const { items } = this.state;
this.setState({ items: [...items, `아이템 ${items.length + 1}`] });
});
}
}
// root 선택자로 잡고
const root = new VirtualDOM(App, document.querySelector("#root"));
root.render()
</script>
</html>
class Component {
target;
state; //상태값 컴포넌트의 유지되는 데이터
constructor(target) {
// 컴포넌트의 target을 설정
this.target = target;
this.setUp();
this.render();
console.log("최초 render");
}
// 초기 설정
setUp() {
// 컴포넌트를 초기 설정 랜더링 하기전에 동작하는 함수.
console.log("initialize");
}
template() {
// 컴포넌트 HTML 템플릿을 반환 해줄거임
return "없음";
}
render() {
// 컴포넌트를 타겟 요소에 그리기
this.target.innerHTML = this.template();
this.setEvent();
}
setEvent() {
// 컴포넌트 이벤트 세팅
console.log("컴포넌트 이벤트 세팅");
}
setState(_state) {
// 컴포넌트의 상태를 업데이트
// 업데이트 되면 리렌더링
this.state = { ...this.state, ..._state };
console.log(this.state,'asd',_state)
this.render();
console.log("state changed");
}
}
class App extends Component {
setUp() {
// App 컴포넌트 초기세팅 함수
this.state = { items: ["아이템1", "아이템2"] };
}
template() {
// App 컴포넌트의 HTML을 생성 해서 반환
const { items } = this.state;
console.log(items)
return `
<ul>
${items.map((a) => `<li>${a} </li>`)}
</ul>
<button> 추가</button>
`;
}
setEvent() {
// App 컴포넌트의 이벤트 등록
this.target.querySelector("button").addEventListener("click", () => {
const { items } = this.state;
this.setState({ items: [...items, `아이템 ${items.length + 1}`] });
});
}
}
class VirtualDOM {
constructor(component, target) {
// 매개변수로 전달받은 컴포넌트 생성후 타겟 요소 전달.
// 컴포넌트 클래스 생성자 함수의 매개 변수로 타겟 전달
this.Component = new component(target);
}
render() {
this.Component.template();
}
}
const root = new VirtualDOM(App, document.querySelector("#root"));
root.render()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<!-- React,ReactDOM라이브러리 -->
<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,ReactDOM라이브러리 -->
<!-- Babel을 가져와서 JSX 문법을 사용 -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- Babel을 가져와서 JSX 문법을 사용 -->
<!-- 자바스크립트 ㅋ드를 변환 해주는 착한 도구 babel
자바 스크립트를 컴파일 해준다.
자바 스크립트 문법은 꾸준히 진화를 했는데
자바 스크립트 문법이 진화하면,ES6=>ES5 변환
babel을 통해서 문법을 쉽게 고칠 수 있다.
babel은 JSX구문을 브라우저에서 읽을 수 있는 자바스크립트로도 변환 해준다. -->
<body>
<div id="root"></div>
</body>
<script type="text/babel">
class LoginBtn extends React.Component {
constructor(props) {
// 부모 생성자 함수 호출
super(props);
// 컴포넌트의 상태
this.state = {
isLogin: false,
};
}
render() {
return (
// {} 중괄호는 EJS때 <% %> 자바스크립트 구문을 사용하겠다는 의미
<button
onClick={() => {
// 현재 상태의 반대값으로 준것.
this.setState({ isLogin: !this.state.isLogin });
}}
>
{this.state.isLogin ? "Logout" : "Login"}
</button>
);
}
}
// 루트 요소를 가상 DOM으로 생성
// createRoot 메서드 랜더링을 위한 루트 객체를 생성
// 루트를 root 아이디를 가진 태그로 설정
const root = ReactDOM.createRoot(document.querySelector("#root"));
// JSX문으로 LoginBtn 컴포넌트를 root에 렌더링한다.
root.render(<LoginBtn id='2'>버튼이다</LoginBtn>);
</script>
</html>
class LoginBtn extends React.Component {
constructor(props) {
// 부모 생성자 함수 호출
super(props);
// 컴포넌트의 상태
this.state = {
isLogin: false,
};
}
render() {
return (
// {} 중괄호는 EJS때 <% %> 자바스크립트 구문을 사용하겠다는 의미
<button
onClick={() => {
// 현재 상태의 반대값으로 준것.
this.setState({ isLogin: !this.state.isLogin });
}}
>
{this.state.isLogin ? "Logout" : "Login"}
</button>
);
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"));
// JSX문으로 LoginBtn 컴포넌트를 root에 렌더링한다.
root.render(<LoginBtn id='2'>버튼이다</LoginBtn>);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<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,ReactDOM라이브러리 -->
<!-- Babel을 가져와서 JSX 문법을 사용 -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<body>
<div id="root"></div>
</body>
<script type="text/babel">
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {
time: new Date().toLocaleTimeString(),
};
}
// react 생명주기
// react생명주기란 화면이 그려지는 시기와 state값이 변했을 때 동작해야하는 작업이 있을 경우
// 화면이 그려지는 시기와 state값이 변했을 때 동작해야하는 작업이 있을경우
// 이런 부분을 제어 할 수있게 해주는 것이 lifecycle 함수이다.
update() {
setState({});
// 아직 변경전 상태가 찍힘
// console.log(this.state);
}
componentDidMount() {
// 여기 내용이 컴포넌트가 생성되면 호출됨 딱 최초에 한 번
setInterval(() => {
this.setState({ time: new Date().toLocaleTimeString() });
}, 1000);
console.log("최초 한 번 실행됨");
// 최초 한 번 실행됨
}
componentDidUpdate() {
console.log("state updated!");
}
render() {
return (
<>
<h1>안뇽, 내 컴퓨터 시간</h1>
<h2>time:{this.state.time}</h2>
</>
);
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<Clock></Clock>);
</script>
</html>
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {
time: new Date().toLocaleTimeString(),
};
}
// react 생명주기
// react생명주기란 화면이 그려지는 시기와 state값이 변했을 때 동작해야하는 작업이 있을 경우
// 화면이 그려지는 시기와 state값이 변했을 때 동작해야하는 작업이 있을경우
// 이런 부분을 제어 할 수있게 해주는 것이 lifecycle 함수이다.
update() {
setState({});
// 아직 변경전 상태가 찍힘
// console.log(this.state);
}
componentDidMount() {
// 여기 내용이 컴포넌트가 생성되면 호출됨 딱 최초에 한 번
setInterval(() => {
this.setState({ time: new Date().toLocaleTimeString() });
}, 1000);
console.log("최초 한 번 실행됨");
// 최초 한 번 실행됨
}
componentDidUpdate() {
console.log("state updated!");
}
render() {
return (
<>
<h1>안뇽, 내 컴퓨터 시간</h1>
<h2>time:{this.state.time}</h2>
</>
);
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(<Clock></Clock>);