Browser Object Model 의 약자로 브라우저와 관련된 객체들의 집합을 의미한다.
최상위 객체로 window 객체가 있으며 DOM이란 것은 BOM의 하위 객체이다.
Document Object Model 의 약자로 HTML의 엘리멘트들을 객체 tree로 표현한 것이다.

<button id="plus">+</button>
<div id="counter">0</div>
<script>
const btn = document.getElementById('plus');
btn.addEventListener('click', () => {
const counter = document.getElementById('counter');
const count = parseInt(counter.innerText);
counter.innerText = count + 1;
})
</script>

위 코드는 DOM 을 조작하여 카운트 기능을 만든것이다. 이렇게 DOM의 노드를 직접 접근, 수정하여 다시 DOM을 렌더링 시킬수 있다.
<button id="addElement">+</button>
<div style="display: flex; flex-direction: column;"></div>
<script>
const addElement = document.getElementById('addElement');
const container = document.querySelector('div');
let count = 0;
addElement.addEventListener('click', () => {
count++;
const newElement = document.createElement('div');
newElement.innerHTML = `Element ${count}`;
container.appendChild(newElement);
})
</script>

위 코드를 보면 버튼 클릭시 자식 엘리먼트를 추가하는 기능을 볼 수 있다.
위처럼 DOM을 직접 조작하면 문제가 발생한다.
(문제라기 보단 성능의 이슈)
우리가 어플리케이션을 개발하다보면 무한 페이지나 새롭게 엘리먼트들이 추가되어야 하는 기능이 있어야 하는 부분이 많은데 DOM으로 직접 조작하게 된다면 엘리먼트가 10개 생길때 렌더링이 10번 생기게 된다.
여기서 리액트같은 SPA(Single Page Application) 프레임 워크들은 Virtual DOM을 도입하여 이 문제를 해결하였다.
Virtual DOM(가상돔)은 실제 DOM과 같은 내용을 담고 있는 복사본이다.
복사본은 실제 DOM이 아닌 JS 객체형태로 메모리 안에 저장되어 있다.
리액트는 항상 두개의 가상돔을 가지고 있다.
리액트는 STATE(상태)가 변경될 때마다 다시 렌더링 하게 되는데 이 시점, 실제 브라우저가 그려지기 이전에 새로운 내용이 담긴 가상돔을 생성하게 된다.

첫번째, 두번째 가상돔의 차이를 비교해 차이만 실제 DOM에 적용하게 된다.
10개가 바뀌면 한번의 렌더링으로 10개의 엘리먼트를 추가 할 수 있게 된것!
https://callmedevmomo.medium.com/virtual-dom-react-%ED%95%B5%EC%8B%AC%EC%A0%95%EB%A6%AC-bfbfcecc4fbb