왓에버

Virtual DOM과 createElement 함수 구현

choijming21 2025. 1. 28. 01:30

오늘은 Virtual DOM의 개념을 이해하고 이를 구현하기 위한 createElement 함수를 만들어보았습니다!

 

 

 

 

Virtual DOM 이란?

Virtual DOM실제 DOM(Document Object Model)의 가벼운 복사본이라고 할 수 있습니다. JavaScript 객체 형태로 표현되며, 실제 DOM과 달리 메모리에만 존재하기 때문에 변경 작업이 훨씬 빠릅니다.

 

실제 DOM 구조가 있다고 가정해보겠습니다.

<div class="container">
  <h1 id="title">Hello World</h1>
  <p id="content">This is a paragraph</p>
</div>

 

이것을 Virtual DOM으로 표현하면 다음과 같은 JavaScript 객체가 됩니다.

{
  "type": "div",
  "props": {
    "className": "container"
  },
  "children": [
    {
      "type": "h1",
      "props": {
        "id": "title"
      },
      "children": [
        "Hello World"
      ]
    },
    {
      "type": "p",
      "props": {
        "id": "content"
      },
      "children": [
        "This is a paragraph"
      ]
    }
  ]
}

 

 

 

 

 

원리

1. 코드 작성 부분

const element2 = (
  <div className="container">
    <h1 id="title">Hello World</h1>
    <p id="content">This is a paragraph</p>
  </div>
);

 

위 코드는 JSX 문법으로 작성된 코드입니다. 브라우저는 이 JSX를 이해하지 못해서, 바벨(Babel)이 코드를 다음과 같이 변환합니다.

 

const element2 = createElement('div', { className: 'container' },
  createElement('h1', { id: 'title' }, 'Hello World'),
  createElement('p', { id: 'content' }, 'This is a paragraph')
);

 

 

2. Virtual DOM 생성

위 코드가 실행되면 우리가 만든 createElement 함수에 의해 Virtual DOM 객체가 생성됩니다.

{
  type: 'div',
  props: { className: 'container' },
  children: [
    {
      type: 'h1',
      props: { id: 'title' },
      children: ['Hello World']
    },
    ...
  ]
}

 

 

 

 

 

createElement 함수 구현

Virtual DOM을 생성하기 위해 createElement 함수를 구현했습니다.

function createElement(type, props, ...children) {
  return {
    type,
    props: props || {},
    children: children.flat(),
  };
}

 

  • type: HTML 태그 이름("div", "h1" 등)
  • props: 요소의 속성들(className, id 등)
  • children: 자식 요소들을 매개변수로 받아 Vritual DOM 객체를 생성합니다.

 

 

 

 

여러가지 예시로 살펴보기

1. 기본적인 구조

const element1 = (
  <div>
    <h1>Hello</h1>
    <p>World</p>
  </div>
);

 

콘솔 출력 결과:

{
  "type": "div",
  "props": {},
  "children": [
    {
      "type": "h1",
      "props": {},
      "children": [
        "Hello"
      ]
    },
    {
      "type": "p",
      "props": {},
      "children": [
        "World"
      ]
    }
  ]
}

 

 

2. 속성이 있는 구조

const element2 = (
  <div className="container">
    <h1 id="title">Hello World</h1>
    <p id="content">This is a paragraph</p>
  </div>
);

 

콘솔 출력 결과:

{
  "type": "div",
  "props": {
    "className": "container"
  },
  "children": [
    {
      "type": "h1",
      "props": {
        "id": "title"
      },
      "children": [
        "Hello World"
      ]
    },
    {
      "type": "p",
      "props": {
        "id": "content"
      },
      "children": [
        "This is a paragraph"
      ]
    }
  ]
}

 

 

3. createElement 직접 호출하기

JSX를 사용하지 않고 createElement 함수를 직접 호출할 수도 있습니다.

const test = createElement(
  "div",
  { className: "test" },
  createElement("h1", null, "Test"),
  createElement("p", null, "Content")
);

 

콘솔 출력 결과:

{
  "type": "div",
  "props": {
    "className": "test"
  },
  "children": [
    {
      "type": "h1",
      "props": {},
      "children": [
        "Test"
      ]
    },
    {
      "type": "p",
      "props": {},
      "children": [
        "Content"
      ]
    }
  ]
}

 

 

4. main.jsx의 전체 코드

/** @jsx createElement */

// 1. createElement 함수 구현
function createElement(type, props, ...children) {
  // type: 태그 이름('h1', 'div' 등)
  // props: 속성들(class, id 등)
  // children: 자식 요소들

  return {
    type,
    props: props || {},
    children: children.flat(), // 중첩된 배열 처리를 위해 flat() 추가
  };
}

// 2. 댜양한 JSX 예시들 작성
// 2.1 기본 예시
const element1 = (
  <div>
    <h1>Hello</h1>
    <p>World</p>
  </div>
);

// 2.2 속성이 있는 예시시
const element2 = (
  <div className="container">
    <h1 id="title">Hello World</h1>
    <p id="content">This is a paragraph</p>
  </div>
);

// 3. Virtual DOm 객체 출력 및 구조 분석
console.log("기본 예시의 Virtual DOM 구조");
console.log(JSON.stringify(element1, null, 2));

console.log("속성이 있는 예시의 VIrtual DOM 구조");
console.log(JSON.stringify(element2, null, 2));

// 4. 간단한 테스트
const test = createElement(
  "div",
  { className: "test" },
  createElement("h1", null, "Test"),
  createElement("p", null, "Content")
);

console.log("직접 createELement를 호출한 결과");
console.log(JSON.stringify(test, null, 2));

 

 

 

Virtual DOM을 사용하는 이유

  1. 성능 최적화: 실제 DOM 조작은 비용이 많이 들지만, Virtual DOM은 JavaScript 객체를 다루는 것이므로 훨씬 빠릅니다.
  2. 일괄 처리: 여러 변경사항을 Virtual DOM에서 한 번에 모아서 실제 DOM에 적용할 수 있습니다.
  3. 크로스 플랫폼: Virtual DOM은 브라우저의 DOM에 직접적으로 의존하지 않기 때문에 다양한 환경(ex: React Native)에서 사용할 수 있습니다.

 

 

 

 

느낀 점

오늘 구현한 createElement 함수를 통해 JSX로 작성한 코드가 어떻게 Virtual DOM 객체로 변환되는지, 그리고 그 구조가 어떻게 되는지 이해할 수 있었습니다. 이는 React가 내부적으로 동작하는 방식을 이해하는 첫 걸음이 되었습니다!_!