1. 프로젝트 구조
📦src
┣ 📂types
┃ ┗ 📜createElementTypes.ts // 타입 정의
┣ 📜App.tsx // 메인 컴포넌트, 진입점
┣ 📜jsx.ts // createElement 구현
┣ 📜render.ts // Virtual DOM → 실제 DOM 변환
┗ 📜style.css // 스타일
2. Virtual DOM 렌더링 함수(render.ts)
렌더링 함수는 Virtual DOM을 실제 DOM으로 변환하는 핵심 기능을 담당합니다.
import { VirtualElement } from "./types/createElementTypes";
export function render(vdom: VirtualElement | string, container: HTMLElement) {
함수는 두 개의 인자를 받습니다.
- vdom: Virtual DOM 객체 또는 문자열
- container: 실제 DOM 요소 (렌더링될 위치)
2.1 문자열 처리
if (typeof vdom === "string") {
container.appendChild(document.createTextNode(vdom));
return;
}
텍스트 내용을 처리합니다. 예를 들어, "Hello"와 같은 문자열을 DOM의 텍스트노드로 변환합니다.
2.2 DOM 요소 생성
const element = document.createElement(vdom.type as string);
Virtual DOM의 type 속성을 사용하여 실제 HTML 요소를 생성합니다.
ex) "div" => <div></div>
2.3 속성(props) 처리
Object.entries(vdom.props).forEach(([key, value]) => {
if (key === "className") {
element.setAttribute("class", value as string);
} else {
element.setAttribute(key, value as string);
}
});
Virtual DOM의 props를 실제 DOM 요소의 속성으로 변환합니다.
- className은 특별히 class 속성으로 변환
- 나머지 props는 그대로 속성으로 설정
2.4 자식 요소 처리
vdom.children.forEach((child) => {
render(child, element);
});
모든 자식 요소에 대해 재귀적으로 render함수를 호출하여 전체 DOM 트리를 구성합니다.
3. 컴포넌트 구현(App.tsx)
3.1 Header 컴포넌트
function Header({ title, buttonText }: HeaderProps): VirtualElement {
return (
<div className="header">
<h1 id="title">{title}</h1>
<button id="login">{buttonText}</button>
</div>
);
}
3.2 Content 컴포넌트
function Content({ text }: ContentProps): VirtualElement {
return (
<div className="container">
<p id="content">{text}</p>
</div>
);
}
3.3 App 컴포넌트: 전체 앱의 구조를 정의하는 메인 컴포넌트 입니다.
function App(): VirtualElement {
return (
<div id="app">
<Header title="Header" buttonText="login" />
<h1>Hello, React!</h1>
<Content text="Virtual DOM 이해 및 복잡한 구조의 컴포넌트 분석" />
</div>
);
}
4. 앱 렌더링: Virtual DOM을 생성하고 실제 DOM으로 렌더링합니다.
const appElement = <App />;
const container = document.getElementById("app");
if (container) {
render(appElement, container);
}
5. Virtual DOM 구조 확인: 생성된 Virtual DOM의 구조를 콘솔에서 확인할 수 있습니다.
console.log(JSON.stringify(appElement, null, 2));
6. 전체 코드
render.ts
import { VirtualElement } from "./types/createElementTypes";
export function render(vdom: VirtualElement | string, container: HTMLElement) {
// 문자열이나 숫자인 경우 테스트 노드 생성
if (typeof vdom === "string") {
container.appendChild(document.createTextNode(vdom));
return;
}
// 1. 실제 DOM 엘리먼트 생성
const element = document.createElement(vdom.type as string);
// 2. 속성(props) 처리
Object.entries(vdom.props).forEach(([key, value]) => {
// className 특별 처리
if (key === "className") {
element.setAttribute("class", value as string);
} else {
element.setAttribute(key, value as string);
}
});
// 3. 자식 요소를 재귀적으로 처리
vdom.children.forEach((child) => {
render(child, element);
});
// 4. 부모 컨테이너에 추가
container.appendChild(element);
}
App.tsx
/** @jsx createElement */
import "./style.css";
import {
ContentProps,
HeaderProps,
VirtualElement,
} from "./types/createElementTypes";
import { createElement } from "./jsx";
import { render } from "./render";
// Header 컴포넌트
function Header({ title, buttonText }: HeaderProps): VirtualElement {
return (
<div className="header">
<h1 id="title">{title}</h1>
<button id="login">{buttonText}</button>
</div>
);
}
// Content 컴포넌트
function Content({ text }: ContentProps): VirtualElement {
return (
<div className="container">
<p id="content">{text}</p>
</div>
);
}
// App 컴포넌트
function App(): VirtualElement {
return (
<div id="app">
<Header title="Header" buttonText="login" />
<h1>Hello, React!</h1>
<Content text="Virtual DOM 이해 및 복잡한 구조의 컴포넌트 분석" />
</div>
);
}
const appElement = <App />;
const container = document.getElementById("app");
if (container) {
render(appElement, container);
}
console.log(JSON.stringify(appElement, null, 2));
7. 결론
이 구현을 통해 React의 핵심 개념인 Virtual DOM과 컴포넌트 기반 구조를 이해할 수 있었습니다. 실제 React는 더 복잡하고 최적화된 방식으로 동작하지만, 이 기본 구현으로도 React의 작동 원리를 파악할 수 있었습니다.
주요 포인트
- JSX는 createElement 함수 호출로 변환됨
- Virtual DOM은 실제 DOM의 가벼운 복사본
- render 함수가 Virtual DOM을 실제 DOM으로 변환
- 컴포넌트는 재사용 가능한 UI 단위
이러한 이해를 바탕으로 React와 같은 현대적인 UI 라이브러리의 동작 방식을 더 깊이 이해할 수 있습니다.
'왓에버' 카테고리의 다른 글
컴포넌트 작성과 Virtual DOM 구조 분석 (1) | 2025.01.28 |
---|---|
Virtual DOM과 createElement 함수 구현 (0) | 2025.01.28 |
React 직접 만들어보기: JSX 이해 및 개발 환경 구축 (0) | 2025.01.27 |