[React] React를 사용하는 이유와 React.createElement()

Joowon Jang·2024년 10월 1일

React

목록 보기
2/19

React.createElement()

  • React에서 요소를 생성하는 함수
  • API : createElement(type, props, ...children)

React와 순수 JavaScript의 DOM요소를 생성하는 방법을 비교해보자.

React를 사용하지 않고 JavaScript에서 DOM요소를 생성하는 방법

// 실제 DOM 구성 (엘리먼트 트리)
// 웹 API를 사용해 문서 객체(Document Object) 생성
// <figure> 요소를 생성

// 부모(상위) 요소 생성
const figureElement = document.createElement('figure');

// 자식(하위) 요소 생성
const figcaptionElement = document.createElement('figcaption');

// 요소간 관계 형성
figureElement.append(figcaptionElement);

// 실제 DOM에 마운트(mount, 착장 === 렌더링)
const actualDomElement = document.getElementById('actual-dom');
console.log(actualDomElement);

actualDomElement.append(figureElement);

실제 DOM요소를 생성해서 DOM트리에 연결

React를 사용하여 DOM요소를 생성하는 방법

// Virtual DOM 가상 문서 객체 모델
// 실제 DOM을 추상화(단순화)
// 가상(추상화된, 단순화된) 요소(엘리먼트) 생성

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

// 자식(하위) 요소
const figcaptionVElement = React.createElement('figcaption');
// console.log(figcaptionVElement);

// 부모(상위) 요소
const figureVElement = React.createElement('figure', null, figcaptionVElement);
// console.log(figureVElement);


/* ----------아직은 DOM요소가 생성되지 않고 JavaScript객체인 상태---------- */
/* ---------------이제 가상 요소를 실제 DOM 요소로 생성------------------ */

// API : createRoot(container) (React 17 이하 버전에서는 ReactDom.render()를 사용함)
const virtualRootElement = document.getElementById('virtual-dom');
const vRoot = ReactDOM.createRoot(virtualRootElement);
vRoot.render(figureVElement);

가상 DOM요소를 생성하고, 그 가상 요소들끼리 연결된 가상 DOM트리 객체 정보를 가지고 있다가, 실제 DOM트리에 연결하는 시점에 실제 DOM요소로 변환

// 예시
// React.createElement()로 만들어진 figureElement는
// 아래처럼 가상 DOM요소의 정보를 담고있는 객체
const figureVElement = {
  "$$typeof": Symbol(react.transitional.element),
  type: 'figure',
  props: null,
  // figcaptionVElement
  children: {
    "$$typeof": Symbol(react.transitional.element),
    type: 'figcaption'
  }
}

보통 JSX문법으로 React를 좀 더 편하게 사용하기 때문에 이 방식이 낯선 사람도 많을 것이다.
하지만, React는 이런 API를 통해 동작하고, JSX 코드가 babel과 같은 트랜스파일러를 통해 이렇게 변환되는 것이기 때문에 정확하게 이해하고 사용하는 것이 중요하다.

위의 코드를 JSX 코드로 변경하면 아래와 같다.

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

const figureVElement = (
  <figure>
    <figcation></figcation>
  </figure>
);

/* ----------아직은 DOM요소가 생성되지 않고 JavaScript객체인 상태---------- */
/* ---------------이제 가상 요소를 실제 DOM 요소로 생성------------------ */

const virtualRootElement = document.getElementById('virtual-dom');
const vRoot = ReactDOM.createRoot(virtualRootElement);
vRoot.render(figureVElement);

React를 사용하는 이유

두 방식의 차이점은 알겠지만, 왜 React를 사용하는 것일까?

React가 DOM트리를 생성 및 업데이트하는 과정

  1. 가상 DOM 생성
    React 컴포넌트가 렌더링될 때, 가상 DOM트리가 생성된다. 이 트리는 JavaScript 객체로 구성되어 있으며, 실제 DOM의 구조를 반영한다.

  2. 변경 사항 감지
    상태(state)나 속성(props)이 변경되면, React는 새로운 가상 DOM트리를 생성한다.

  3. 비교 (Diffing)
    React두 가상 DOM트리를 비교하여 변경된 부분을 찾는다. React는 내부 알고리즘을 통해 최소한의 변경 사항을 감지한다.

  4. 실제 DOM 업데이트 (reconciliation)
    변경된 부분만 실제 DOM에 반영된다. React변경된 요소들만 업데이트하기 때문에 전체 DOM을 다시 렌더링하는 것보다 훨씬 빠르다.

DOM트리의 변경 사항을 비교하는 연산 시간 때문에 더 느리지 않을까?

단순한 구조의 DOM트리를 조작할 때에는 그럴지도 모른다.
하지만, React의 방식이 전체 DOM트리를 조작하는 것보다 빠르게 동작하는 것에는 다음과 같은 이유들이 있다.

  • 배치 업데이트
    React는 여러 상태 변경을 하나의 업데이트로 배치한다. 즉, 여러 번의 상태 변경이 발생해도 React는 이를 모아서 한 번에 처리하기 때문에 불필요한 DOM 업데이트를 줄일 수 있다.

  • 최소한의 실제 DOM 조작
    실제 DOM 조작은 비용이 많이 드는 작업이다. React는 가상 DOM을 사용하여 변경된 부분만 실제 DOM에 반영하기 때문에, 전체 DOM을 다시 렌더링하는 것보다 훨씬 효율적이다.

  • 브라우저 최적화
    브라우저는 실제 DOM 조작 시 레이아웃 계산, 리페인트, 리플로우 등의 작업을 수행해야 하는데, 많은 시간이 걸릴 수 있다. React는 가상 DOM을 사용하여 이러한 작업을 최소화하고, 브라우저가 더 효율적으로 동작할 수 있도록 한다.

추가적으로, React는 두 가상 DOM 트리를 비교할 때, 동일한 레벨의 요소들만 비교한다거나, 배열을 비교할 때에는 key 속성을 사용해 요소를 식별하는 등 최대한 효율적인 알고리즘을 사용한다.

참고: https://ko.react.dev/reference/react/createElement

profile
깊이 공부하는 웹개발자

0개의 댓글