1. 가상 돔
개발자들이 DOM을 직접 건드리지 않고 훨씬 더 쉬운 구조물로 UI를 개발할 수 있도록 중간에 DOM처리는 리액트에게 맡기고 개발자는 JSX만 개발하면 될 수 있도록 하는 것.
리액트는 실제 DOM과 메모리 상에 쌓아둔 가상 DOM을 비교해서 다른 것만 비교하여 특정 부분을 변경한다.
export class Component {
constructor(props) {
this.props = props;
}
}
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;
}
function makeProps(props, children) {
return {
...props,
children: children.length === 1 ? children[0] : children,
};
}
export function createElement(tag, props, ...children) {
props = props || {};
if (typeof tag === 'function') {
if (tag.prototype instanceof Component) {
const instance = new tag(makeProps(props, children));
return instance.render();
} else {
if (children.length > 0) {
return tag(makeProps(props, children))
} else {
return tag(props);
}
}
} else {
return { tag, props, children };
}
}
export function render(vdom, container) {
container.appendChild(createDOM(vdom));
}
여기서 가상돔 역할을 하는 것은 createElement 함수의 리턴에 있는 { tag, props, children } 객체로서
이것은 현재 HTML의 형태를 데이터로 가지고 있는 것이다.
이 객체의 특징은 트리 구조를 가지고 있다는 것이다.
루트는 하나고 그 아래에는 루트의 자식들로서 단일 객체이며 실제 돔은 createDOM을 통해 생성된다.
실제 React 라이브러리는 이것보다 훨씬 더 복잡하게 코드가 구현되어있다.
이런 식으로 가상돔을 구현해두면 좋은 것이 UI가 업데이트할 때 엄청난 장점을 발휘한다.
기존에 그려진 DOM과 만들고자하는 DOM이 메모리 상에 있다.
이 전에 그렸던 가상돔을 메모리에서 가지고 있다가 새로 써야 하는 형태의 가상돔이 오면
그 두 개의 객체를 비교해서 달라진 것만 비교할 수 있다는 것이다. (객체 대 객체로서 비교 가능)
이 구조 덕분에 React는 핫한 라이브러리가 되었다.
대략적으로 DOM을 비교하는 로직을 짜면 이렇게 될 것이다.
export const render = (function() {
let prevDom = null;
return function(vdom, container) {
if (prevDom === null) {
prevDom = vdom;
}
// diff
container.appendChild(createDOM(vdom));
}
})();
이런 식으로 diff 부분에서 두 개의 객체를 비교하면 기존에 가지고 있던 DOM과 다른 것만을 구별해낼 수 있을 것이다.
2. 참고할만한 글
1. 가상돔을 공부할만한 라이브러리 : snabbdom
https://github.com/snabbdom/snabbdom
2. virtual-DOM open source library
https://awesomeopensource.com/projects/virtual-dom
끝!