티스토리 뷰

반응형

# 지난 시간 정리

 

리덕스는 전형적인 펍섭(pubsub) 모델을 구현한 .

사실상 리액트와 연관성이 전혀 없다.

 

publish - subscribe 구조. 상태 변경되면 그걸 알려주고 구독한 쪽에서 알람 받을 있는 구조.

observer 패턴이랑은 다르다.

 

 

# 리액트 만들기

좋은 아키텍처를 말할 때 대원칙 중에 하나는 같은 것끼리 묶고 다른 것끼리 분리하는 것에 있다. 여기서 지식 수준의 차이에 따라 어떤게 같은것이고, 어떤게 다른것인지 판단하는 기준이 달라진다. 

그러나 보통 기본적인것(네이밍 잘 짓기 등)만 지켜도 70% 먹고 들어간다.

 

## 리액트 컨셉

리액트 컨셉은 완전히 새로운게 아니다.

 

브라우저의 경우 예를 들어보자.

HTML코드의 문자열 구조를 직접 다루는 것은 어렵기 때문에 훨씬 다루기 쉬운 DOM Tree 객체를 만들어서 노드를 관리한다.

 

리액트의 경우도 같다.

다루기 어려운 Real DOM 대신 다루기 쉬운 VDOM 만들어서 DOM 컨트롤한다. (DOM - VDOM - JS 흐름)

결국 브라우저의 DOM Tree 같은 컨셉이다.

어려운 구조를 다루기 위해 쉬운 구조의 레이어를 하나 더 만드는 컨셉은 프로그래밍에 여럿 있다.

그래도 또 개발자들이 어려워할까봐 다루기 쉽도록 JSX 적용함.

보통 객체가 가장 다루기 쉬운 구조다. 프리미티브(원시) 타입은 다루기 어렵다.

 

## 컴포넌트

import React from "react";
import ReactDOM from "react-dom";

function StudyList() {
  return (
    <ul>
      <li className="item">React</li>
      <li className="item">Redux</li>
      <li className="item">TypeScript</li>
      <li className="item">mobx</li>
    </ul>
  );
}

function App() {
  return (
    <div>
      <h1>Hello</h1>
      <StudyList />
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

StudyList라는 컴포넌트를 생성하여 분리하였다.

컴포넌트 이름만 봐도 어떤 컴포넌트인지 파악 가능하도록 네이밍을 잘하면 안에 데이터를 보지 않아도 된다.

 

 

## Tiny React

// const vdom = {
//   type: "ul",
//   props: {},
//   children: [
//     { type: "li", props: { className: "item" }, children: "React" },
//     { type: "li", props: { className: "item" }, children: "Redux" },
//     { type: "li", props: { className: "item" }, children: "TypeScript" },
//     { type: "li", props: { className: "item" }, children: "mobx" }
//   ]
// };

function renderElement(node) {
  // vdom은 전형적인 재귀 호출 데이터 (어디가 끝인지 모르기 때문에)
  if (typeof node === "string") {
    return document.createTextNode(node);
  }
  const el = document.createElement(node.type);

  node.children.map(renderElement).forEach((element) => {
    el.appendChild(element);
  });

  return el;
}

function render(vdom, container) {
  // 실제 리액트라면 vdom vs. newVdom 비교해서 바뀐부분만 렌더링.
  container.appendChild(renderElement(vdom));
}

function createElement(type, props = {}, ...children) {
  if (typeof type === "function") {
    return type.apply(null, [props, ...children]);
  }
  return { type, props, children };
}
/* @jsx createElement */
import { createElement, render } from "./tiny-react";

function Row(props) {
  return <li>{props.label}</li>;
}

function StudyList() {
  return (
    <ul>
      <Row label="우와아아" />
      <li className="item" label="haha">
        React
      </li>
      <li className="item">Redux</li>
      <li className="item">TypeScript</li>
      <li className="item">mobx</li>
    </ul>
  );
}

function App() {
  return (
    <div>
      <h1>Hello</h1>
      <StudyList item="abcd" id="hoho" />
    </div>
  );
}

render(<App />, document.getElementById("root"));
console.log(<App />);

 

  • vdom의 대략적인 구조는 주석처리 되어있는 부분과 같다.
  • 기존에 사용하는 React.createElement()  vdom 만드는 함수다. render()   호출된다.
  • 이 때 상단에 /* @jsx createElement */ 이 코드를 써주면 바벨이 기본값인 React.createElement() 대신 옵션으로 지정해준 createElement 함수를 호출하도록 컴파일 된다. babel 플러그인 중 하나다.
  • 바벨 playground에서 실행한 결과

  • 맨 마지막줄에 콘솔로 <App />을 찍어보면 vdom 구조의 객체가 찍힌다. 컴파일 타임에 vdom으로 변환되기 때문에.
  • 빌트인 컴포넌트와 사용자 컴포넌트를 구분하는 방식 - 맨 앞글자가 대문자냐 소문자냐
  • 컴파 (vdom 만들 때)  ‘div’, ‘h1’ 이런값들은 문자열로 넣어주고 사용자 컴포넌트는 함수  자체를 넣어줌.
  • ex) createElement(‘div’, null, ‘’) createElement(App, null, ‘’)

virtual dom library 검색해보면 가벼운 라이브러리들 많이 있음. (코드 까보기 쉽다)

버츄얼 라이브러리는 diff 알고리즘(리얼 돔과 비교하는 로직) 필연적으로 가지고 있다.

 

코드를 까보고 싶을때 요령 : 초기 릴리즈를 쫓아가서 기본 컨셉 내용을 파본다. 

기본 로직은 거의 안바뀌기 때문. 방어로직 코드양이 별로 없어서 분석하기 쉽다.

 

 

## 도대체 상태란 무엇인가?

값은 상태가 아니다. 변하지 않으니까. 상태는 변해야 한다. 

그래서 변수를 만들어서 값을 바꿔 저장한다.

 

함수형 컴포넌트는 상태를 가질 없다.

왜냐하면 호출될 마다 변수가 초기화 되니까.

 

클래스는 외부에서 객체를 파기하지 않는 상태를 변경할 있다.

그래서 초기 리액트는 상태를 가지지 않고 받은 props 이용해서 그리기만 하면 함수형, 상태를 가지면 클래스 컨벤션 가짐.

 

함수형은 라이프사이클이 없다. 호출하고 나면 끝이기 때문에.

 

클래스는 라이프사이클 메소드가 존재. ex) componentDidMount() {}

라이프사이클 메소드는 델리게이터 패턴이다.

필요하면 만들어. 내가 호출해줄게라는 식.

 

리액트는 기본적으로 render 언제 호출해야 할지 시점을 없다. 사용자가 상태를 언제 변경할지 모르기 때문에.

그래서 setState() 메소드를 제공하고 해당 메소드를 사용할 마다 render 호출된다.

 

최근에는 자바스크립트 스펙에 proxy 추가되서 데이터 변경 감지 가능함.

 

saga thunk redux 미들웨어다. redux 없이 단독으로 사용 불가.

 

import React, { useState } from "react";
import ReactDOM from "react-dom";

class Hello extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return <p>안녕하세요!</p>;
  }
}

const hello = new Hello();
hello.render();

function App() {
  const [counter, setCounter] = useState(1);

  return (
    // 객체 구조상 트리형태이기 때문에 부모가 항상 하나.
    // react에서 fragment를 사용해 여러 부모가 가능하긴 하나 트릭일 뿐 원리는 똑같음.
    <div>
      <h1 onClick={() => setCounter(counter + 1)}>상태 {counter}</h1>
      <Hello />
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

 

# 리액트 

useState() 데이터와 데이터를 변경할  있는 메소드를 제공해준다.

전역에있는  배열에 컴포넌트가 생성된 순서대로 배열에 인덱스화해서 넣어둔다.

그래서 반드시 전역에서 사용해야함. 컨디셔널문이나 반복문에서 호출하면 인덱싱이 어그러짐.

함수형에서만 써야하고 리액트 컨포넌트에서만 써야함.

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함