본문 바로가기
FRONT-END/React

나만의 React 만들기(Build your own react) - STEP 0

by 랄라J 2024. 9. 3.

https://pomb.us/build-your-own-react/ 을 기반으로 학습 내용을 정리한 글입니다.


React가 제공해 주는 기능들을 당연한 듯 사용해 왔지만,
React 내부가 어떻게 동작하는지 궁금해본 적 없이 당연한 듯 사용하기를 n년...
그리고 모던 React Deep Dive를 사고 앞 챕터 부분을 분명 읽었는데 역시 빠르게 휘발되어 버렸다...

 

build-your-own-react 에서 알려주는 대로 차근차근 따라가며 확실히 이해하는 과정 기록을 위해 블로그를 작성한다.
왜냐면 사실 한번 쭉 따라 해봤는데, 완벽히 이해했나요? 아니요🙂‍↔️... 상태이기 때문이다.
다시 차근차근.. 이제는 알고쓰자 React!

 

실습을 하며 같이 진행해야 하기 때문에 해당 문서에서 지원하는 리액트 버전을 설치한 후 진행합시다!
여기서는 react를 대체해 didact로 구현합니다.

# react 16.8.6 버전으로 프로젝트 세팅
npx create-react-app didact
cd didact
npm i react@16.8.6 react-dom@16.8.6

# 설치 완료 후 실행
npm start

 

 

 

프로젝트를 설치한 후에는 현 실습에 불필요한 파일들을 지워줬다.
왼쪽과 같이 public에는 index.html, src에는 index.js가 있다.
index.js에 불필요한 코드도 지워서 준비해 줬다.

 

 

일단, index.js 코드는 아래와 같다.
아래 코드 상태로 npm start를 해주면 Hello가 보인다.

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

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<h1 title="foo">Hello</h1>);

 

 

STEP 0. React, JSX 및 DOM 요소의 동작방식을 알아보자

우선, 앞으로 작성하게 되는 코드는 모두 index.js 한 파일에 위치함을 미리 알린다 :)

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

const element = <h1 title="foo">Hello</h1>;
const container = document.getElementById("root");
ReactDOM.render(element, container);

위 index.js 코드를 예시 코드 형태로 변경했다.
ReactDOM.createRoot를 사용하는 것도 첫 번째 인자로 countainer를 받고 ReactDOM.Root를 return 한다.
root는 다시 root.render가 가능한 형태로 선언 방식의 차이일 뿐 동일한 코드이다.

 

자, 이제 위 코드를 하나씩 살펴보자.
1. react element를 정의
2. DOM에서 하나의 node를 가져옴
3. React 요소를 container에 render

 

여기까진 전혀 어렵지 않다 :)
우리는 이제 차근차근 React에서 제공하는 것들을 동일한 기능을 하는 javascript 코드로 바꿔 나갈 것이다.

 

차근차근 JSX 변환부터 알아보자.
JSX(Javascript Syntax extension)는 Babel과 같은 빌드 도구를 통해 JS로 변환된다.
변환 과정은 보통 단순하다.
tag 내부의 코드를 createElement 호출로 바꾸고 tag 이름, props 및 children을 매개변수로 전달한다.

const element = React.createElement(
    "h1",
    {title: "foo"},
    "Hello"
)

또 여기서 한 단계 더 나아가면 React.createElement는 인수를 받아 객체를 생성한다.

React.createElement(type, props, ...children);

생성되는 객체의 형태는 아래와 같다.

const element = {
  type: "h1",
  props: {
    title: "foo",
    children: "Hello",
  },
};

이렇게 React.createElement 함수 호출을 하면 객체로 안전하게 대체할 수 있게 된다.
여기서 typeDOM node의 유형을 지정하는 문자열이다.
HTML 요소를 생성하려는 경우 document.createElement에 전달하는 tagName이다. (h1, div...)
props는 또 다른 객체이며, JSX 속성의 모든 키와 값을 갖는다. children이라는 속성도 있다.
위에서 children은 단순히 문자열로 들어가 있지만, 일반적으로 더 많은 요소가 포함된 배열이다. 자식 요소들이다.
즉, 요소는 tree 구조로 이루어진다. <div><p>1</p> <p>2</p></div> 이렇게 여러 하위 요소가 들어오는 걸 생각하면 된다!

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

// const element = <h1 title="foo">Hello</h1>;
// const element = React.createElement("h1", { title: "foo" }, "Hello");
const element = {
  type: "h1",
  props: {
    title: "foo",
    children: "Hello",
  },
};

const container = document.getElementById("root");
ReactDOM.render(element, container);

자, 그럼 여기까진 변환 완료!

 

다음은 ReactDOM.render를 하는 코드를 ReactDOM을 활용하지 않고 직접 업데이트하는 코드로 바꿔보자.

const node = document.createElement(element.type)
node["title"] = element.props.title

const text = document.createTextNode("")
text["nodeValue"] = element.props.children

먼저 element.type을 사용해 node를 만들고, 모든 props를 해당 node에 할당한다.
(지금은 title만 있으니 title만 한 것!)
그리고 children을 위한 node를 만든다. 현재는 Hello 문자열만 있기 때문에 textNode를 만든다.
innerText를 사용하는 방법도 있지만, textNode를 사용하면 나중에 모든 요소들을 동일한 방식으로 처리할 수 있기 때문에 textNode로 만든다.

이제 이렇게 만든 node와 text를 node에 text 추가, container에 node 추가하여 차곡차곡 쌓아준다.

 

const element = {
  type: "h1",
  props: {
    title: "foo",
    children: "Hello",
  },
};

const container = document.getElementById("root");

const node = document.createElement(element.type)
node["title"] = element.props.title

const text = document.createTextNode("")
text["nodeValue"] = element.props.children

node.appendChild(text)
container.appendChild(node)

그럼 이렇게 React를 사용하지 않고 똑같은 app을 만들 수 있게 되었다!

index.js 코드 내 위와 같이 코드가 들어있고 실행해도 이전처럼 Hello가 동일하게 표시된다!


여기까지 STEP 0 완료!

728x90

댓글