Vanilla JavaScript로 Virtual DOM을 직접 구현하고, Firebase와 연동하여 실시간으로 좋아요의 갯수의 렌더링 변화를 관찰합니다. 구현한 JS Virtual DOM, React의 Virtual DOM 및 JS Real DOM과 비교하여 성능과 렌더링 성능을 실험하고 DOM의 작동 원리를 탐구합니다.
- DOM과 VirtualDOM의 원리를 학습합니다.
- Virtual DOM이 실제로 어떤 방식으로 작동하는지 직접 구현을 통해 이해합니다.
- React와 Vanilla JS 간의 웹 성능 차이를 비교해 결과를 분석합니다.
- 브라우저 엔진이 어떻게 발전해왔는지를 학습합니다.
구현 방식 | 설명 |
---|---|
1. like-component-vanillajs-virtualdom | Vanilla JS로 Virtual DOM을 구현한 Like Conunt Module |
2. like-component-vanillajs | VanillaJS 및 HTML/CSS로 Real DOM의 성능 측정을 위한 Like Conunt Module |
3. like-component-react | React로 구현한 Like Conunt Component |
git clone https://github.com/woorifisa-service-dev-5th/tech-seminar-vanillajs-vdom.git
가상 DOM을 적용한 좋아요 모듈을 직접 구현하여 diff → patch 방식으로 좋아요 숫자가 존재하는 node의 요소만 변경하는 실습
cd like-component-vanillajs-virtualdom
npx live-server
비교 테스트를 위한 일반적인 Vanilla JS 방식으로 구성된 좋아요 모듈
cd like-component-vanillajs
npx live-server
비교 테스트를 위한 React.js를 활용하여 구성된 좋아요 컴포넌트
cd like-component-react
npm install
cp .env.example .env
npm run dev
복잡한 모듈은 오히려 테스팅 환경 통제에 영향을 준다고 생각하여 간단한 좋아요 카운팅 모듈을 구현

![]() |
![]() |
- 좋아요 버튼 클릭 시, 콘솔에서 가상 DOM이 이전 노드와 새로운 노드를 비교하는 과정을 로그로 출력하였습니다.
- 각 노드는
{type : <tag type> , props : {children:nodeValue }}
의 형식으로 존재하며 이는 각각 JS의 객체라 할 수 있습니다.
구현한 Virtual DOM은 일반적으로 다음과 같은 흐름으로 작동
- 사용자가 버튼을 클릭하면 이벤트 핸들러가 실행됩니다.
- 버튼 클릭으로 인해 데이터(상태)가 변경됩니다.
likeCount
값이 +1 증가(이는 메모리 상의 변화)
- 변경된 상태를 기반으로 **새로운 Virtual DOM(메모리상 가상 노드 트리)**이 생성됩니다.
- 이전 Virtual DOM과 새로운 Virtual DOM을 비교(
diff
)하여 변경된 부분만 찾아냅니다.
- 달라진 노드만 실제 DOM에 반영하여 불필요한 전체 리렌더링을 방지합니다.
파일명 | 설명 |
---|---|
createElement.js |
Virtual DOM Node 생성 로직 |
render.js |
Virtual DOM → 실제 DOM 변환 |
diff.js |
이전 VDOM과 새로운 VDOM 비교 알고리즘(diffing) |
patch.js |
diff 결과를 실제 DOM에 반영하는 패치 함수 |
main.js |
Firebase 연동 및 전체 Like 모듈 렌더링 로직 |
LightHouse와 Developer Tools Performance로 웹 성능과 렌더링 성능 측정
동일한 모듈 수, 환경과 브라우저, DB를 연결하여 최대한 변인을 통제
1 | 2 | 3 |
---|---|---|
![]() |
![]() |
![]() |
1 | 2 | 3 |
---|---|---|
![]() |
![]() |
![]() |
1 | 2 | 3 |
---|---|---|
![]() |
![]() |
![]() |
(테스트 환경: Chrome 138, 환경 동일 조건)
지표 (점수) | React | VanillaJS (Virtual DOM) | VanillaJS (Real DOM) |
---|---|---|---|
Performance | 88 | 98 | 99 |
Accessibility | 90 | 88 | 88 |
Best Practices | 100 | 93 | 93 |
SEO | 82 | 90 | 100 |
지표 (측정값) | React | VanillaJS (Virtual DOM) | VanillaJS (Real DOM) |
---|---|---|---|
First Contentful Paint (FCP) | 1.1s | 0.7s | 0.6s |
Largest Contentful Paint (LCP) | 1.8s | 0.8s | 0.7s |
Total Blocking Time (TBT) | 140ms | 60ms | 55ms |
Cumulative Layout Shift (CLS) | 0.001 | 0.001 | 0.001 |
Speed Index (SI) | 1.1s | 0.7s | 0.7s |
- Vanilla JS 기반 모듈이 React보다 빠른 초기 로딩 속도와 낮은 TBT을 보임.
- React는 JS 파싱 및 번들 로딩 시간 때문에 TTI와 TBT가 상대적으로 느림.
- Virtual DOM 사용 시 Real DOM 대비 큰 차이는 없지만, DOM 업데이트를 최소화하여 CPU 연산 부담을 줄이는 효과가 있음.
모듈 | 실행 시간 | 설명 |
---|---|---|
React | 약 1.5s | Vanilla JS보다 약 2배 소요 |
VanillaJS | 약 780ms | 순수 DOM 조작만 있으므로 최소한의 JS만 실행. |
VanillaJS Virtual DOM | 약 710ms | Real DOM Vanilla JS와 근소한 차이 |
모듈 | 실행 시간 | 설명 |
---|---|---|
React | 약 380ms | JS번들링, Props 처리, 이벤트 바인딩, 재조정 등 다양한 내부 작업 포함. |
VanillaJS | 약 50ms | 직접적인 DOM 조작만 있으므로 최소한의 JS만 실행, 코드의 양이 절대적으로 적음 |
VanillaJS Virtual DOM | 약 70ms | diff, patch 로직 포함 → Vanilla보다 약간 높지만 여전히 빠른 실행시간. |
- React: 약 70ms
- VanillaJS: 약 80ms
- JS Virtual DOM: 약 50ms
⚡ diff 알고리즘으로 바뀐 node만 계산 → 미비하지만 실제로 렌더링 시간 감소에 도움이 된다는 결론

- 브라우저 자체의 렌더링 엔진이 최적화가 잘 되어 있어, 작은 규모 앱에서는 Virtual DOM 이점이 크지 않았다.
- 결국 DOM 엔진의 고도화, 고성능 DOM API의 등장 그리고 하드웨어 성능의 비약적인 향상이 React보다 Vanilla JS의 성능이 높은데 기여했다고 생각.
- React는 부가적인 라이브러리 코드와 상태 관리 로직/훅으로 JS 실행 시간 당연히 늘어날 수 있음.
- 다만, Virtual DOM이 어떻게 구성되고 작동하는지 코드와 결과값으로 직접 체감할 수 있었으며, 프로젝트의 규모에 따라 적절히 JS와 Framework/Library를 선택하는 능력이 중요하다고 생각.
- React 공식 문서 - Reconciliation
- DOM vs Virtual DOM (Velog)
- DOM과 JavaScript (CodeStates Blog)
- DOM 뽀개기 (Naver D2)
- MDN - Document Object Model 소개
- Vanilla JS와 Virtual DOM 비교 (Tistory)
Virtual DOM의 동작원리와 이해 : Vanilla JS를 활용한 VDOM 구현