https://saiki.hashnode.dev/the-one-thing-that-no-one-properly-explains-about-react-why-virtual-dom

 

The one thing that no one properly explains about React — Why Virtual DOM

The other day a friend had this React question for me: “Composition through components, one way data binding; I understand all that, but why Virtual DOM?”. I’ve given him the usual answer. "Because, direct DOM manipulation is inefficient, and slow."

saiki.hashnode.dev

 

 

공부 목적으로 번역해보고 있어용 오역 매우 많을 수 있음 주의 ㅋ

 

 

 

The other day a friend had this React question for me: “Composition through components, one way data binding; I understand all that, but why Virtual DOM?”.

 

I’ve given him the usual answer. "Because, direct DOM manipulation is inefficient, and slow."

 

“There’s always news on how JavaScript engines are getting performant; what makes adding something directly to the DOM slow?”

 

That is a great question. Surprisingly, I’ve not found any article that properly pieces it all together, making the case for the need of a Virtual DOM rock solid.

 

It’s not just the direct DOM manipulation that makes the whole process inefficient. It is what happens after.

 

To understand the need for a Virtual DOM, lets take a quick detour, a 30000 feet level view on a browser’s workflow, and what exactly happens after a DOM change.

 

어느날 한 친구가 나에게 리액트 관련 질문을 했다: 컴포넌트를 통한 합성, 단뱡향 데이터 바인딩, 이건 이해하겠는데 왜 가상돔이야? 

나는 전형적인 대답을 해줬다. "직접적인 DOM 조작은 비효율적이고 느려서"

자바스크립트 성능은 계속 좋아진다고는 들리는데, 뭐가 정확히 DOM 느리게하는 거야 ? 

좋은 질문이다. 놀랍게도, 가상돔의 필요에 대한 케이스 다르는 적당한 아티클을 찾을 수 없었습니다.

단지 직접적 DOM 조작이 전체 프로세스를 비효율적으로 만드는 건 아닌다. 이건 일어나고 난 뒤다.

가상돔의 필요를 이해하기 위해선,  DOM이 바뀌구 난 후 정확이 어떤일이 일어나는 지 그리고 브라우저의 워크플로우를 간단히 다뤄봐야 합니다.

 


 

브라우저 워크플로우

NOTE: 앞으로 나오는 다이어그램은, Webkit 엔진 용어를 사용했다. 워크플로우는 몇 가지 뉘앙스를 빼고 거의 모든 브라우저에 비슷합니다.

DOM tree 생성

  • 브라우저가 HTML 파일을 받으면, 렌더 엔진이 분석 후 HTML 요소들과 일대일 관계를 가진 노드들의 돔트리를 생성합니다.

 

Render tree 생성

  • 그동안, 분석된 외부 CSS 파일들과 요소들의 인라인 스타일로부터 스타일들을 파싱합니다. DOM 트리의 노드와 함께 스타일 정보는 렌더 트리라고 불리는 다른 트리를 만드는데 사용합니다.

 

The Render Tree — Behind the scenes

  • 웹킷안에서, 노드의 스타일을 처리하는 과정을 'attchment'라고 합니다. DOM 트리안에 모든 노드들은 스타일 정보를 계산해서 렌더 객체로 반환하는 'attach' 메소드를 갖습니다.
  • 'Attachment'는 동기적이고, 돔 트리에 노드를 삽입은 그 새 노드에서 'attach' 메소드를 호출합니다. 
  • 이러한 렌더 개체로 구성된 렌더 트리를 만들려면 각 렌더 개체의 시각적 속성을 계산해야 합니다. 이 속성은 각 요소의 계산된 스타일 속성을 사용하여 수행됩니다.

 

The Layout (reflow라고도 불림)

  • 렌더트리의 구성 뒤에, 레이아웃 프로세스로 넘어갑니다. 렌더 트리안에 모든 노드들은 화면 좌표가 주어지고, 정확히 화면 그 위치에 나타날 것입니다. 

 

The Painting

  • 다음 단계는 렌더 객체를 그리는 것입니다. 렌더 트리는 모드는 노드들을 거쳐가면서 'paint' 메소드를 호출합니다. 결국 컨텐츠가 화면에 나타나게 됩니다.

 


 

Virtual DOM으로

 

So, as you can see from the above flow of steps, whenever you make a DOM change all the following steps in the flow, right from the creation of the render tree (which requires recalculation of all the style properties of all the elements), to the layout, to the painting step, all are redone.

위 단계에서 볼 수 있듯이, DOM이 바뀔때마다 플로우안에 렌더트리 생성, 레이아웃, 페인팅 모든 단계들이 모든 다시 실행된다.

In a complex SPA, often involving a large number of DOM manipulations, this would mean multiple computational steps (which could be avoided) which make the whole process inefficient.

복잡한 SPA에서는 엄청나게 많은 DOM 조작이 자주 수반됩니다. 즉, 모든 프로세스를 비효율적으로 만드는 다중 계산 단계를 뜻합니다. (즉 피할수도 있겠죠)

This is where the Virtual DOM abstraction truly shines; when there’s a change in your view; all the supposed changes that are to be made on the real DOM, are first made on the Virtual DOM, and then sent on to the real DOM, thus reducing the number of following computational steps involved.

이럴때 가상돔 추상법이 진정으로 빛납니다. 당신의 화면안에서 변화가 있을때, 모든 변화는 Real DOM에서 이뤄져야합니다만, 모두 처음에 Virtual DOM에서 만들지고, Real DOM으로 보내지게 됩니다. 그에따라 따라오는 엄청난 수의 계산 과정을 줄일 수 있습니다.

 

 

업데이트 👏🏼

 

The real problem with DOM manipulation is that each manipulation can trigger layout changes, tree modifications and rendering. Each of them. So, say you modified 30 nodes, one by one. That would mean 30 (potential) re-calculations of the layout, 30 (potential) re-renderings, etc.

 

Virtual DOM is actually nothing new, but the application of "double buffering" to the DOM. You do each of those changes in a separate, offline DOM tree. This does not get rendered at all, so changes to it are cheap. Then, you dump those changes to the "real" DOM. You do that once, with all the changes grouped into 1. Layout calculation and re-rendering will be bigger, but will be done only once. That, grouping all the changes into one is what reduces calculations.

 

But actually, this particular behaviour can be achieved without a virtual DOM. You can manually group all the DOM modifications in a DOM fragment yourself and then dump it into the DOM.

 

So, again, what does a Virtual DOM solve? It automates and abstracts the management of that DOM fragment so you don't have to do it manually. Not only that, but when doing it manually you have to keep track of which parts have changed and which ones haven't. So a Virtual DOM (if implemented correctly) also automates this for you, knowing which parts need to be refreshed and which parts don't.

 

Finally, by relinquishing DOM manipulation for itself, it allows for different components or pieces of your code to request DOM modifications without having to interact among themselves, without having to go around sharing the fact that they've modified or want to modify the DOM. This means that it provides a way to avoid having to do synchronization between all those parts that modify the DOM while still grouping all the modifications into one.

 

DOM 조작의 진짜 문제는 각 모든 조작은 트리 변경과 렌더링, 레아아웃 변화를 일으킵니다. 30 노드들을 하나하나 수정했다고 합시다. 그건 즉 layout 30번 재계산과 30번의 리렌더링을 뜻합니다.

가상 돔은 사실 전혀 새로운 것이 아닙니다. 하지만 DOM에서는 '더블 버퍼링'의 응용이라고 할 수 있겠죠. 이러한 각 변경은 별도의 오프라인 DOM 트리에서 수행합니다. 이러면 전혀 렌더링이 되지 않기때문에, 비용이 적습니다. 그러고나서 real DOM으로 최종 변화를 던집니다. 모든 변화들은 1이라는 그룹안에 넣어 한번만 실행합니다. 레이아웃 계산과 리렌더링은 더 커지겠지만 한번만 실행됩니다. 이렇게 모든 변화를 그루핑하면서 연산을 줄입니다.

가상돔없이 해당 동작을 이뤄낼 수 있습니다. DOM 조각의 모든 DOM 수정사항을 직접 수동으로 그룹화 한다음 DOM 던져주면 됩니다.

그래서 다시한번, 가상돔은 무엇을 해결하려는걸까 ? DOM 조각의 관리를 자동화, 주상화하여 수동적으로 사용자가 다룰 필요 없겠죠. 그것뿐만 아니라, 수동으로 사용할때는 직접 어떤부분이 변경되었는지 않았는지 추적해야합니다. 가상돔은 어떤 부분이 리프레쉬가 필요한지 아닌지 또한 자동화해줍니다.

마지막으로, DOM 조작 자체를 포기함으로써, DOM을 수정했거나 수정하려는 사실을 공유하지 않고 서로 상호 작용할 필요 없이 코드의 다른 구성 요소나 조각이 DOM 수정을 요청할 수 있습니다. 즉, 모든 수정사항을 하나로 그룹화하면서 DOM을 수정하는 모든 부분 간에 동기화를 수행할 필요가 없습니다.

 

'Good to Know' 카테고리의 다른 글

React.lazy랑 @loadable Component 차이 ?  (0) 2023.02.02
REST가 뭘까요?  (0) 2023.01.12
LocalStorage vs SessionStorage vs Cookie  (1) 2023.01.03
웹은 어떻게 동작하는가 ?  (0) 2023.01.02
Intl 국제화표준 API  (0) 2022.11.30