본문 바로가기

React

React - React 기본 및 DOM, Babel, class, component

728x90
반응형

1) React

   1-1) DOM & React

   1-2) Babel

   1-3) class & component

 

 

 

 

 

 

 

 

1) React

1-1) DOM & React

화면을 꾸밀 때 "Javascript"를 활용해서 HTML을 조작함! --> DOM
parser 작업이 진행됨!

 


브라우저 rendering 과정
1. response body에 있는 HTML 내용(string type의 텍스트를 의미함)을 파싱(parsing)함!
2. 파싱 후 tree 구조를 만듦
3. 표현 준비
4. Render(화면이 그려짐)

<html>
  <head>
    <title></title>
  </head>
  <body></body>
</html>

 


React와 무슨 관계가 있는가?
- DOM 조작을 쉽게 하기 위해서

React는 언제 누가 만들었는가?
- Facebook(현 meta)이 만듦

Facebook은 사용자 경험을 위해 SPA(Single Page Application)를 고집하였고,

이 과정에서 Facebook 개발자들이 React를 개발함!

 

DOM 조작을 쉽게 하기 위해, 그리고 SPA를 만들기 위해 React를 사용함!

"JS(Javascript)"를 잘하는 사람이 모여서 만든 것이 아니라,
"개발"을 잘하는 사람이 모여서 만든 것이 "React"이다!

과거에는 React가 "class" 문법으로 만들어져 있음!

React는 초창기에 진입장벽이 높았다!

 

 

React는 현재도 라이브러리인지, 프레임워크인지 논란이 많다!
"directory 구조의 여부"에 따라 프레임워크와 라이브러리로 구분함!

  • 라이브러리는 directory 구조가 없다!
  • 프레임워크는 directory 구조가 있다!

Facebook이 React를 만들었을 때 이는 "라이브러리"였다!


React 요약 : "데이터를 바꾸면 화면이 바뀐다!!"

 

 

Component
"Component"는 상태를 담을 수 있는 element라고 보면 된다!
"Component"는 객체이다!

ReactDOM에서는 상태(state)를 추적한다!

 

 

dom.html

<!DOCTYPE html>
<html lang="en">
  <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>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="text/javascript">
      const root = document.querySelector("#root");
      // const h1 = document.createElement("h1");
      // const span = document.createElement("span");
      // const p = document.createElement("p");

      // span.innerHTML = "hello";
      // p.innerHTML = "world";

      // h1.append(span);
      // h1.append(p);

      // root.append(h1);

      const button = document.createElement("button");
      button.addEventListener("click", (e) => {
        if (e.target.innerHTML === "Login") {
          e.target.innerHTML = "Logout";
        } else {
          e.target.innerHTML = "Login";
        }
      });
      button.innerHTML = "Login";

      root.append(button);
    </script>
  </body>
</html>

 

 

react.html

<!DOCTYPE html>
<html lang="en">
  <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>Document</title>
    <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>
  </head>
  <body>
    <div id="root"></div>

    <script type="text/javascript">
      // React : element를 만들 때 사용하는 라이브러리
      // ReactDOM : 우리가 작업 영역이라거나 DOM 조작을 위한 라이브러리
      // ReactDOM은 "virtual DOM"이라는 개념이 있는데 지금은 여기서부터 React 코드라는 것을 선언한 것을 의미한다고 보면 됨!
      // const root = ReactDOM.createRoot(document.querySelector("#root"));
      // root.render(React.createElement("h1", null, "hello world"));

      class LoginBtn extends React.Component {
        // 생성자 함수(constructor)는 생략 가능하다!!
        constructor(props) {
          super(props);

          // 상태가 바뀌면 component가 바뀐다! === 데이터가 바뀌면 화면이 바뀐다!
          this.state = {
            isLogin: false,
          };
        }

        // 상태값이 바뀌면 "render" 메서드가 다시 실행된다!
        render() {
          console.log(this.state.isLogin);
          // React.createElement('Element 이름', '속성', 'innerHTML')
          return React.createElement(
            "button",
            {
              onClick: () => {
                // 바로 아래 코드는 "this.state.isLogin = !this.state.isLogin"과 동일하게 동작하는 코드이다!!
                this.setState({ isLogin: !this.state.isLogin });
              },
            },
            this.state.isLogin ? "Logout" : "Login"
          );
        }
      }

      const root = ReactDOM.createRoot(document.querySelector("#root"));
      // "component"는 상태(state)를 담을 수 있는 일종의 강화된 "element"로 보면 된다!
      // (중요!!) "React.createElement()"가 실행되는 시점에 "constructor 함수"가 실행된다!
      root.render(React.createElement(LoginBtn));
    </script>
  </body>
</html>

 

 

 

1-2) Babel

"Babel"은 Javascript Compiler(컴파일러)이다!
"Babel"은 특정 내용(코드)을 변경할 때 사용한다!

 

// Javascript
const str = 'hello world';

 

// Typescript
const str:string = 'hello world';


Babel을 적용하면 위의 Typescript 코드의 형태를 변형하여 사용할 수 있음!

 

babel.html

<!DOCTYPE html>
<html lang="en">
  <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>Document</title>
    <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>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  </head>
  <body>
    <div id="root"></div>

    <script type="text/babel">
      class LoginBtn extends React.Component {
        // props : component에 인자값을 넣어주는 것을 담아주는 매개변수
        constructor(props) {
          super(props);

          // 상태가 바뀌면 component가 바뀐다! === 데이터가 바뀌면 화면이 바뀐다!
          this.state = {
            isLogin: false,
          };
        }

        render() {
          return (
            <button
              onClick={() => {
                this.setState({ isLogin: !this.state.isLogin });
              }}
            >
              {this.state.isLogin ? "Logout" : "Login"}
            </button>
          );
        }
      }

      const root = ReactDOM.createRoot(document.querySelector("#root"));
      // root.render(<LoginBtn />); // innerHTML이 없는 경우, "root.render(<LoginBtn></LoginBtn>);"를 해당 코드처럼 뒤의 닫는 태그를 생략하여 쓸 수 있음!!
      /*
      React.createElement(LoginBtn)
      <LoginBtn />

      AJAX
      */

      // root.render(React.createElement(LoginBtn, { id: "1" }, "hihi"));
      root.render(<LoginBtn id="1">hihi</LoginBtn>); // 바로 위의 코드와 동일한 코드임!!
    </script>
  </body>
</html>

 

 


JSX

const element = <h1>Hello, world!</h1>;

 

위의 희한한 태그 문법은 문자열도, HTML도 아닌데 이는 JSX라 하며 JavaScript를 확장한 문법이다!

UI가 어떻게 생겨야 하는지 설명하기 위해 React와 함께 사용할 것을 권장한다!

JSX에는 JavaScript의 모든 기능이 포함되어 있다!

 


하나의 component는 하나의 element만 반환하여야 한다!(단, 하위 element는 몇 개가 되는 상관없다!)
virtual DOM: 기존의 DOM 형태와 내가 가지고 있는 DOM 형태를 비교하여 다른 부분만 갈아 끼워주는 역할을 함!

 

 

dom2.html

<!DOCTYPE html>
<html lang="en">
  <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>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="text/javascript">
      const Clock = () => {
        const div = document.createElement("div");
        const h1 = document.createElement("h1");
        const h2 = document.createElement("h2");

        const txt = "hello world!";
        let time = `It is ${new Date().toLocaleTimeString()}`;

        h1.innerHTML = txt;
        h2.innerHTML = time;

        div.append(h1);
        div.append(h2);

        document.querySelector("#root").innerHTML = div.innerHTML;
      };

      setInterval(Clock, 1000);
    </script>
  </body>
</html>

<!-- 시계: 1초마다 1초씩 시간을 표현하는 코드를 DOM 코드로 작성 -->

 

 

react2.html

<!DOCTYPE html>
<html lang="en">
  <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>Document</title>
    <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>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="text/babel">
      class Clock extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            currentTime: new Date().toLocaleTimeString(),
          };
        }

        // component가 최초에 실행되었을 때 실행하는 코드 영역
        componentDidMount() {
          setInterval(() => {
            this.setState({ currentTime: new Date().toLocaleTimeString() });
          }, 1000);
        }

        render() {
          return (
            <div>
              <h1>Hello world!</h1>
              <h2>It is {this.state.currentTime}</h2>
            </div>
          );
        }
      }

      const root = ReactDOM.createRoot(document.querySelector("#root"));
      root.render(<Clock />);
    </script>
  </body>
</html>

 

 

 

1-3) class & component

class
"객체 생성"을 쉽게 하기 위해 class 문법을 사용함!

상속
객체 속성값을 재활용하기 위해 상속을 사용함!

생명주기

  • componentDidMount : component가 최초에 mount되었을 때 실행되는 메서드
  • componentDidUpdate : 상태(state)가 바뀔 때마다 실행되는 메서드
 

 

 

component1.html

<script type="text/javascript">
  class CreateElement {
    constructor(element, props, inner) {
      const args = {
        children: inner,
        ...props,
      };
    }
  }

  class Component {
    props; // 앞으로 넣을 Element
    state; // 데이터들

    constructor(_props) {
      this.props = _props;
      this.setup();
      this.template();
    }

    setup() {} // 자식클래스에서 구현
    render() {} // 자식클래스에서 구현
    template() {
      this.props.innerHTML = this.render();
    }
    setState(newState) {
      if (this.state === newState) return;
      this.state = { ...this.state, ...newState };
      this.template();
    }
  }

  class LoginBtn extends Component {
    constructor(props) {
      super(props);
      this.state = {
        isLogin: false,
      };
    }

    render() {
      return `<button>${this.state.isLogin ? "logout" : "login"}</button>`;
    }
  }
</script>
<div id="root"></div>
<script type="text/javascript">
  // new LoginBtn(document.querySelector("#root"));

  const root = new VirtualDOM(LoginBtn, document.querySelector("#root"));
</script>

 

 

component2_ex1.html

<script type="text/javascript">
  class Person {
    constructor() {
      this.name = "sangbeom";
      this.age = 28;
    }

    hello() {}
    go() {
      this.hello();
    }
  }

  class Student extends Person {
    constructor() {
      super();
      this.class = "블록체인 8기";
    }

    hello() {
      console.log("sleeping");
    }
  }

  const student = new Student();
  console.log(student);
  student.go();
</script>

 

 

component2_ex2.html

<div id="root"></div>
<script type="text/javascript">
  class Component {
    props;
    state;

    constructor(_props) {
      this.props = _props;
    }

    componentDidMount() {}
    componentDidUpdate() {}

    render() {} // 추상 메서드
    template() {
      this.componentDidMount();
      this.props.innerHTML = this.render();
    }

    setState(newState) {
      if (this.state === newState) return;
      this.state = { ...this.state, ...newState };
      this.render();
      this.componentDidUpdate();
    }
  }

  class LoginBtn extends Component {
    constructor(props) {
      super(props);
      this.state = {
        isLogin: false,
      };
    }

    componentDidMount() {
      console.log("나는 최초에 render가 되었다!");
      this.setState({ isLogin: true });
    }

    componentDidUpdate() {
      console.log("나는 상태가 바뀌었다!");
    }

    clickHandler() {
      alert("hello");
    }

    render() {
      return `<button>${this.state.isLogin ? "logout" : "login"}</button>`;
    }
  }

  class VirtualDOM {
    static createRoot(Props) {
      return {
        props: Props,
        render(Component) {
          new Component(this.props).template();
        },
      };
    }

    // render(Component) {
    //   new Component(this.props).render();
    // }
  }

  const root = VirtualDOM.createRoot(document.querySelector("#root"));
  root.render(LoginBtn);

  // const btn = new LoginBtn();
  // btn.setState({ isLogin: true });
  // console.log(btn.state);

  // const layout = btn.render();
  // console.log(layout);
</script>