가상돔과 리액트의 관계를 알아보기에 앞서, 간단하게 개념설명을 진행하겠습니다. 🕶️
" 웹페이지의 구조를 표현하는 객체 모델. HTML/ XML 문서에 접근하기 위한 인터페이스.DOM은 HTML과 스크립팅언어(Javascript)를 서로 이어주는 역할"
" 실제 돔(Document Object Model)의 가벼운 복사본. 실제 돔과 동일한 구조를 가지지만, 메모리상에 존재하는 가벼운 복사본!! 직접적으로 dom에 있는 문서에 접근하지 않는다. 변경사항을 하나의 가상 돔에 모았다가 DOM에 보내는 기술"
트리형태의 구조로 표현됨 (실제 돔의 구조와 유사함) 웹/앱의 UI를 계층적으로 표현.
Node
: 실제 돔의 요소를 나타냄. HTML요소, 텍스트, 주석 등 다양한 유형의 노드가있음.
Element
: HTML 요소를 나타내는 노드.
같은 HTML 태그로 표현 가능. Element는 태그이름, 속성(Attribute), 자식노드를 포함!
Text
: 실제 돔의 텍스트 내용
Attribute
: Element는 Attribute를 가질 수 있음. ‘class’, ‘id’, ‘src’ 와 같은 속성을 가진 요소를 표현 가능. Attribute는 Element 의 추가정보를 제공함.
Children
: 가상돔의 노드는 다른 노드들을 자식으로 가질 수 있음.
1->5에 이어지는 동작원리의 순서를 확인해보자.
초기 랜더링
: 초기에는 실제 돔과 동일한 구조를 가지고 있음. 초디상태를 기반으로 가상돔이 생성됨.UI 업데이트
: 웹/앱에서 상태변경이 발생하면, 가상돔은 <변화된 가상돔 vs 이전 가상돔>의 차이를 계산함.가상돔 비교
: 요소의 유형, 속성, 텍스트 내용 등을 비교해서 이전가상돔과의 변경된 부분을 식별함.돔 조작
: 변경된 부분을 실제 돔에 반영하기 위해 돔 조작 실행.실제 돔 업데이트
: 가상돔의 돔 조작 완료 후, 실제 돔은 변경된 부분에 대한 업데이트를 실행 → 이를 통해 UI가 새로운 상태로 업데이트됨.🧐 Virtual DOM 의 대유행을 유발하는 한 라이브러리의 등장… 두둥!!
발단
: Facebook에서 메세지가 오지않았는데, 메세지가 와있다고 뜨는 심각한 버그가 있었는데, 실제로 그 버그를 해결하지 못하는 상황이 옴. "Facebook 알림 버그”→ 구체화 된 아이디어
: 전부 다 Virtual DOM 에 새로 그리고, 기존에 비해 변경된 부분만 DOM에 한 번에 보내버리자!!데이터가 바뀔 때마다 전부 다 다시 그려 버리면
버그가 생길 일이 없지 않냐는 생각을 하게되고, 아이디어를 구체화함.결국 React 는 성공
했고, React를 이용하면 데이터 흐름과 DOM의 차이에 의한 버그가 발생하지 않았고, 코드를 선언적으로 깔끔하게 작성 할 수 있게 됨.성능 개선
: 웹/앱에서 상태가 변경될 때마다 실제 돔을 직접 조작하는 것은 비용이 크고 성능에 부담을 줄 수 있음 → 이런 문제를 해결하기 위해 가상돔은 실제 돔과의 차이를 분석 + 최소한의 변경을 적용함으로 불필요한 레이아웃 계산과 리플로우를 방지하고 성능을 개선함.선언적 UI 업데이트 + 개발 생산성
: 상태의 변화에 따라 UI를 업데이트하기 위해 선언적인 방식을 사용하는데, 가상돔 비교를 통해 변경된 부분만 감지 후 업데이트를 하기에 개발자가 UI 업데이트에 집중할 수 있음!크로스 플랫폼 개발
: 가상돔을 사용하면 플랫폼에 종속되지 않음! 동일한 코드를 여러 플랫폼에 재사용이 가능. React Native 가 React와 동일한 가상돔을 사용하여 앱을 개발하는 것도 가능!랜더링
이란 ?
- 현재 props 및 상태를 기반으로 React 가 컴포넌트에게 UI 영역이 어떻게 보이길 원하는지 설명을 원하는 프로세스
[1단계] 렌더링 큐(Rendering Queue)를 사용하여 컴포넌트의 업데이트를 관리
- 상태(State) 및 속성(Properties) 변경
- 컴포넌트 업데이트 계획
- 랜더링 큐에 업데이트 등록
- 랜더링 시작
- 컴포넌트 랜더링
- 가상돔 비교 및 실제 돔 업데이트
- 자식 컴포넌트 렌더링
[2단계] ReactDOM.render() 메서드를 사용하여 root 컴포넌트를 실제 돔에 마운트
[3단계] root 컴포넌트의 render() 메서드 호출 → 해당 컴포넌트 & 하위 컴포넌트들의 가상돔 트리가 생성됨.
virtual DOM 데이터와 diff 알고리즘으로 reconciliation 과정을 거쳐 화면을 수정 → 이 과정은 n개의 node가 있는 트리에 대해 O(n) 복잡도를 가지게 됨.
복제본이기 때문에 추가적인 작업 및 계산이 필요하기 때문에 실제 돔보다 초기 랜더링 속도가 느릴 수 있음.
컴포넌트가 복제되고 이전 상태와 비교되는 과정에서 추가적인 메모리가 필요. 하지만 일반적으로 크게 문제 x
가상돔은 모든 컴포넌트의 변화를 추적하고 이에 대한 업데이트를 수행하기 때문에 불필요한 랜더링이 발생 할 수 있음.
: 가상돔을 블록 단위로 처리하는 방식! 컴포넌트의 랜더링을 블록으로 나누고, 각 블록은 독립적으로 처리되며 업데이트가 됨. (컴포넌트, 요소 포함)
https://developer.mozilla.org/ko/docs/Web/API/Document_Object_Model/Introduction
https://gist.github.com/sebmarkbage/75f0838967cd003cd7f9ab938eb1958f
https://velog.io/@huurray/React의-탄생과-Flux-패턴에-대하여
https://velopert.com/3236
https://velog.io/@woohm402/virtual-dom-and-react
https://ko.legacy.reactjs.org/docs/reconciliation.html
https://million.dev/blog/virtual-dom