개인공부/TIL(Today I Learned)

TIL 79일차_Why Virtual DOM ?

soon327 2021. 4. 7. 23:57

React를 공부하다보면 매우매우 자주 듣게되는 용어들이 있다.
컴포넌트, 단방향데이터, CSR, Virtual DOM . . .
하나하나의 개념을 이해하려고 노력하며 공부하고있다.

오늘은 Virtual DOM에 대해서 공부해봤다.😆

Why Virtual DOM?

누군가 왜 Virtual DOM을 쓰는지 물어본다면 뭐라고 답할까?
DOM 조작이 비효율적이고 느리기 때문에??
자사크립트 엔진은 계속해서 성능이 좋아지는데, 정확히 어떤 부분때문에 DOM이 느려지는 걸까?

정확히는,
DOM조작이 전체 동작을 비효율적으로 만드는게 아니라,
그 이후에 일어나는 일 때문에, 작업이 느려지는 것이다.

이를 이해하기 위해서는 브라우저의 워크플로우에 대해 알 필요가 있다.🏃🏻‍♂️

브라우저의 Workflow

  1. DOM Tree 생성

브라우저가 HTML을 전달받으면 브라우저의 렌더엔진이 이를 파싱하고,
DOM노드(node)로 이뤄진 트리를 만든다.
각노드는 각 HTML 엘리먼트들과 연관되어있다.

  1. Render Tree 생성

CSS파일과 각 엘리먼트의 스타일 정보를 파싱하여 DOM Tree에 따른 새로운 트리인 렌더 트리를 만든다.
이 과정은 동기적 작업이며, DOM트리의 모든 노드들이 갖고있는
attach라는 노드의 메서드가 스타일정보를 계산해서 객체 형태로 반환한다.
(attach는 Webkit엔진에서 사용하는 용어이지만, 작동방식은 대부분의 브라우저에서 비슷하다.)

  1. Layout (reflow)

렌더트리가 완성되면 각 노드들은 스크린의 좌표가 주어지고, 스크린 어느부분에 나타나야 할 지 위치가 주어진다.

  1. Painting

렌더링된 요소들이 paint 메서드를 호출하면서 색을 입히며 스크린에 나타난다.

Virtual DOM

DOM을 조작했을 때, 어떤 작업이 이뤄지는지 다시 정리하자면 다음과 같다.

DOM에 변화가 생긴다
-> 렌더트리가 재생성 된다.( 이과정에서 모든 요소들의 스타일이 다시 계산된다.)
-> 레이아웃을 만들고 페인팅을 한다.

복잡한 SPA에서는 DOM조작이 매우 많이 발생하고,
위의 과정에 따르면 매우 많은 레이아웃변화, 트리변화, 렌더링을 일으킨다.
예를 들어, 30개의 노드를 하나하나 수정하면 그 뜻은,
30번의 잠재적인 레이아웃 재계산과 30번의 잠재적인 리렌더링을 초래한다는 것이다.

이러한 때에 Virtual DOM이 빛을 발한다.
뷰에 변화가 있다면, 그 변화는 실제 DOM에 적용되기 전에 가상의 DOM에 먼저 적용시키고,
그 최종적인 결과를 실제 DOM에 전달함으로써,
브라우저 내에서 발생하는 연산의 양을 줄이면서 성능을 개선할 수 있게 되는 것이다.

Virtual DOM은 특별히 엄청난게 아니고, 그냥 DOM 차원에서의 더블 버퍼링이다.

변화가 일어나면, 그걸 오프라인 DOM트리에 적용시킨다.
이 DOM 트리는 렌더링도 되지 않기때문에 연산비용이 적다.
연산이 끝나면, 최종적인 변화를 딱 한번에 모든 변화를 묶어서 실제 DOM에 던져준다.

그러면, 레이아웃 계산과 리렌더링의 규모는 커지겠지만,
딱 한번에, 하나로 묶어서 적용시키기 때문에 연산의 횟수를 줄일 수 있다.

이러한 과정은 Virtual DOM 없이도 할 수 있지만,
Virtual DOM은 이 과정들을 자동화하고 추상화한다.
우리가 이를 직접 한다면, DOM fragment를 하나하나 직접관리해주고,
기존 값 중 어떤게 바뀌었는지 계속해서 파악해줘야한다.

이를 Virtual DOM이 대신해주고,
DOM관리를 Virtual DOM이 하도록 함으로써,
컴포넌트가 DOM 조작 요청을 할 때, 다른 컴포넌트들과 상호작용 하지 않아도 된다.
특정 DOM을 조작하거나, 조작했다는 정보를 공유할 필요 없이,
즉, 각 변화들의 동기화 작업 없이 모든 작업을 하나로 묶어줄 수 있다.

Virtual Dom In React

앞서 말했듯이,
Virtual DOM은 크게 어려운 개념은 아니다.
로컬에 Virtual DOM을 생성 시키고, 브라우저에 Render를 요청 하기 전에 변경 사항을 요청 하는 방식이다.

React에서 Virtual Dom을 사용하는 Flow를 간단하게 살펴보자.

클릭해야 보여요. (출처: https://medium.com/@js_tut/react-animated-tutorial-7a46fa3c2b96)

변경 사항이 생기면 ReactDOM.render()가 호출 된다.
해당 과정은 변경점을 찾는 작업과, 변경점을 실제 UI 적용하는 과정으로 나누어진다.

변경점을 찾는 작업에서 React는
Virtual DOM을 통하여 브라우저 DOM에 전달하기 전에 Reconciliation라는 비교 과정을 선행하기 때문에 UI에 대한 제어를 최소화 시킨다.
(이는 React-Native에도 동일하게 작동한다.)
Render가 진행 될 때마다, 각 Element들은 key를 부여 받고, 해당 key를 통해 같은 Element라고 인식 되고 비교 된다.

React는 빠르다?

아래는 Redux창시자이자 React 개발팀원인 Dan Abramov의 트윗이다.

Myth: React is "faster than DOM".
Reality: It helps create maintainable applications, and is "fast enough" for most use cases.

React는 유지보수 가능한 어플리케이션을 만드는 것을 도와주고, 대부분의 경우에 "충분히 빠르다."

최적화 작업을 제대로 했을 때와, 리액트를 사용 했을 때를 비교하면 사실 대부분의 경우 전자가 더 빠르다.
그러나 이를 자동화해주는 리액트를 생성했을 때, 생산성에서 강점이 있는 것이다.

출처: VELOPERT.LOG
RyuK 성장 일지