HTML , CSS , JavaScript 등 개발자가 작성한 문서를 브라우저에서 출력하는 과정을 말한다.
첫 번째로 브라우저가 렌더링할 문서를 읽게 되는데 HTML과 CSS로 나눠서 읽게 된다. 이때 HTML과 CSS는 단순한 텍스트이므로 각각 연산과 관리가 가능하도록 HTML Parser와 CSS Parser를 사용해 관리가 가능한 Object Model로 만든다.
여기서 렌더링 엔진은 더 나은 사용자 경험을 위해 가능한 빠르게 내용을 표시하게 만들어졌는데, 따라서 모든 HTML, CSS파싱이 끝나기도 전에 이후의 과정을 수행하여 미리 사용자에게 보여줄 수 있는 내용들을 출력한다.
단계에서 DOM 트리와 CSSOM 트리가 생성되면, 이 둘을 연결하여 표시해야 할 순서로 내용을 그려낼 수 있도록 하기 위해 렌더 트리를 생성해준다. 이 과정을 Attachment 라고 한다. DOM 트리의 모든 노드들은 ‘attach’ 라는 메소드가 있다. 이 메소드는 스타일 정보를 계산해서 객체형태로 반환한다.
이 과정은 동기적(synchronous) 작업이며, DOM 트리에 새로운 노드가 추가되면 그 노드의 attach 메소드가 실행된다.
순수한 요소들의 구조와 텍스트만 존재하는 DOM 트리와는 달리 렌더 트리는 스타일 정보가 설정되어 있으며 실제 화면에 표현되는 노드들로만 구성된다. display: none;과 같은 속성이 설정된 노드는 화면에서 어떠한 공간도 차지하고 있지 않기 때문에 렌더 트리를 만드는 과정에서 제외된다.
tree 구조에서 root 노드를 포함한 모든 개개의 개체를 node라고 표현한다. head, body, title, script, h1, HEADER-1 등의 태그뿐 아니라 태그 안의 텍스트나 속성 등도 모두 node에 속한다.
이중 HTML 태그를 요소노드(Element Node)라고 부르고 요소 노드 안에 있는 글자를 Text 노드(Text Node)라고 부르기도 한다.
레이아웃 단계에서는 뷰포트 내에서 각 요소의 정확한 위치와 크기를 정확하게 캡처하는 Box 모델이 출력됩니다. 모든 상대적인 측정값은 화면에서 절대적인 픽셀로 변환됩니다.
마지막으로 렌더링 트리의 각 노드를 화면의 실제 픽셀로 변환하게 됩니다. 레이아웃 단계에서 모든 계산이 완료가 되면, 화면에 요소들을 그리게 됩니다. 이 단계를 “페인팅” 또는 “래스터화”라고 합니다.
이미 레이아웃 단계에서 각 노드들이 위치, 크기, 색상 등 스타일이 모두 계산이 되었기 때문에 화면에 실제 픽셀로 변환하게 됩니다.
DOM에 변화가 생기면, 렌더트리를 재생성하고 (그러면 모든 요소들의 스타일이 다시 계산됩니다) 레이아웃을 만들고 페인팅을 하는 과정이 다시 반복된다.
복잡한 SPA(싱글 페이지 어플리케이션) 에서는 DOM 조작이 많이 발생해요. 그 뜻은 그 변화를 적용하기 위해 브라우저가 많이 연산을 해야한단 소리고, 전체적인 프로세스를 비효율적으로 만든다.
우선 위의 과정에서 DOM에 변화가 생기면 과정을 반복하며 비효율적이라는 것을 알게되었다. 그러면 Virtual DOM은 이를 어떻게 해결했을까?
우선 Virtual DOM을 리액트 공식 홈페이지에서는 다음과 같이 설명한다.
Virtual DOM (VDOM)은 UI의 이상적인 또는 “가상”적인 표현을 메모리에 저장하고 ReactDOM과 같은 라이브러리에 의해 “실제” DOM과 동기화하는 프로그래밍 개념입니다. 이 과정을 재조정이라고 합니다.
조금더 풀어서 설명하자면 Virtual DOM은 만약에 뷰에 변화가 생기면, 그 변화를 실제 DOM에 적용하기 전에 먼저 가상의 DOM (Virtual DOM)에 적용을 시킨 후 실제 DOM과 비교하여 변화된 부분만을 수정하는 개념이다. 이러한 방법을 통해 기존의 DOM보다 연산의 양을 줄일 수 있어 성능이 개선된다.
OM 조작의 실제 문제는 각 조작이 레이아웃 변화, 트리 변화와 렌더링을 일으킨다. 그래서, 예를 들어 30개의 노드를 하나 하나 수정하면, 그 뜻은 30번의 (잠재적인) 레이아웃 재계산과 30번의 (잠재적인) 리렌더링을 초래하게 된다.
Virtual DOM 은 DOM 차원에서의 더블 버퍼링과 비슷한 개념이다. 변화가 일어나면 그걸 가상의 DOM 트리에 적용시킨다. 이 DOM 트리는 렌더링도 되지 않기때문에 연산 비용이 적다. 연산이 끝나고나면 그 최종적인 변화를 한번에 묶어서 실제 DOM에 보내주게 된다. 이 방식으로 하게 되면 레이아웃 계산과 리렌더링의 규모는 커지겠지만, 하나로 묶어서 보내기 때문에 연산의 횟수는 확실히 줄어들게 된다.
사실, 이 과정은 Virtual DOM 이 없이도 이뤄질수 있어요. 그냥, 변화가 있을 때, 그 변화를 묶어서 DOM fragment 에 적용한 다음에 기존 DOM 에 던져주면 돼요.
DOM fragment를 관리하는 과정을 수동으로 하나하나 작업 할 필요 없이, 자동화하고 추상화한다. 그 뿐만 아니라, 만약에 이 작업을 직접 한다면, 기존 값 중 어떤게 바뀌었고 어떤게 바뀌지 않았는지 계속 파악하고 있어야하는데 (그렇지 않으면 수정 할 필요가 없는 DOM 트리도 업데이트를 하게 될 수도 있기 때문에), 이것도 Virtual DOM 이 이걸 자동으로 해준다.
마지막으로, DOM 관리를 Virtual DOM 이 하도록 함으로써, 컴포넌트가 DOM 조작 요청을 할 때 다른 컴포넌트들과 상호작용을 하지 않아도 되고, 특정 DOM 을 조작할 것 이라던지, 이미 조작했다던지에 대한 정보를 공유 할 필요가 없다. 즉, 각 변화들의 동기화 작업을 거치지 않으면서도 모든 작업을 하나로 묶어줄 수 있다는 것이다.
https://velopert.com/3236
https://velog.io/@kja/Virtual-DOM
https://www.howdy-mj.me/dom/what-is-dom/
https://boxfoxs.tistory.com/408