프론트엔드 첫걸음

김민태 프론트엔드 강의 - javascript로 React 만들기 본문

개발 공부/React

김민태 프론트엔드 강의 - javascript로 React 만들기

차정 2023. 3. 11. 12:27
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));
}

 

/* @jsx createElement */
const vdom2 = <p>
  <h1>React 만들기</h1>
  <ul>
    <li style="color:red">첫 번째 아이템</li>
    <li style="color:blue">두 번째 아이템</li>
    <li style="color:green">세 번째 아이템</li>
  </ul>
</p>;

 

 

JSX와 Babel의 변환 과정

  • JSX는 JavaScript 문법이 아니라 JavaScript 확장 문법으로, 브라우저에서는 그대로 실행할 수 없다.
    따라서 Babel과 같은 트랜스파일러가 JSX를 일반 JavaScript 코드로 변환해주는 과정이 필요하다.
  • Babel은 JSX를 기본적으로 React.createElement 함수 호출 형태로 변환한다.
    예를 들어 다음과 같은 JSX 코드는:
  • const vdom2 = <p>Hello</p> 
    다음과 같은 코드로 변환된다:
  • const vdom2 = createElement("p", null, "Hello");
  • 이때, Babel은 JSX를 변환할 때 어떤 함수로 변환할지를 결정하는 주석 지시어를 지원한다.
    이 기능이 바로 @jsx이다.

@jsx createElement를 사용해 JSX 변환을 커스텀할 수 있다.

  • /* @jsx customCreateElement */ 주석을 추가하면
    Babel은  React.createElement 대신 우리가 만든 customCreateElement 를 호출하여 JSX를 변환한다.
  • 이 방식으로 React 없이 직접 JSX를 사용할 수 있음.
  • /* @jsx React.createElement */는 명시적인 설정일 뿐, 실제로는 작성하지 않아도 Babel이 기본으로 그렇게 해준다.
    • 과거에 import React from "react" 했어야 하는 이유가 바벨이 변환을 시킬때
      const element = React.createElement("h1", null, "Hello"); 이런 코드를 쓰기때문에
      코드안에서 React 쓸수 있게 import React 해줬어야함.
    • react 17부터는 , React.createElement 호출을 자동으로 처리하게 되어 import React from "react"  필요없음

 

JSX 코드

import React from "react"; /* 17 이전에는 React.createElement가 동작해야하므로 import React 필요*/

const element = <h1>Hello</h1>;

 

바벨 변환결과

const element = React.createElement("h1", null, "Hello");
  • React에서 컴포넌트는 반드시 함수여야 하고, 대문자로 시작해야 한다.
    이 경우 Babel이 내부적으로 대문자로 시작하는 JSX 태그를 일반 문자열이 아니라 JavaScript 변수(컴포넌트)로 취급하여 React.createElement를 호출한다.
  • tag가 함수 컴포넌트인지 확인 (typeof tag === 'function').
    • 함수 컴포넌트 라면 tag(props)를 호출하여 실행 결과를 반환
  • children이 1개면 단일 값으로 전달, 2개 이상이면 배열로 전달.
    • <Title>이름</Title>
    • <Title><Item>1</Item><Item>2</Item></Title> 구분