[React.js] Virtual DOM 가상 돔

minbr0ther·2022년 3월 30일
2

react

목록 보기
1/3
post-thumbnail

[10분 테코톡] 🥁 지그의 Virtual DOM
(10분) 를 보고 정리하면서 추가적인 내용이 있는 글입니다 :)


1️⃣ 브라우저의 동작

👀 브라우저 렌더링 과정

1. DOM tree & CSSOM tree 생성

  • 렌더 엔진이 HTML을 파싱하여 DOM 노드로 이루어진 트리 생성

2. Render tree 생성

  • css 파일과 inline 스타일을 파싱 DOM + CSSOM 렌더 트리 생성

3. Layout (reflow)

  • 각 노드들의 스크린에서의 좌표에 따라 위치 결정 (position, size)

4. Paint (repaint)

  • 실제 화면에 그리기, 브라우저 화면에 우리가 보는 UI 나타남

❗️ 여기서 문제는 DOM에 변화가 생기면 render tree가 그때마다 재생성 된다는 것입니다.

변화가 발생하면 모든 요소들의 스타일을 다시 계산하고, layout(reflow)과정을 거치고, 다시 repaint하는 과정까지 반복합니다.


👀 DOM 조작의 비효율성

예를 들어 유저가 어떤 포스트에 좋아요를 누르거나, 담아둔 장바구니 목록에서 상품을 하나 삭제하거나, 어딘가에 댓글을 남기면 전체 노드들이 처음부터 다시 그려집니다. 이런 작업들은 불필요한 과정이 반복됩니다.

최근에는 SPA(Single Page Application)을 많이 사용하면서 DOM tree를 즉각적으로 많이 변경할 일이 생겼습니다. 전체 페이지를 서버에서 매번 보내주는 것이 아니라, 브라우저단에서 자바스크립트가 관리하기 떄문에 DOM 조작을 더욱 더 효율적으로 할 수 있게끔 최적화가 필요해진 것입니다.

그래서 등장한 것이 Virtual DOM입니다.


2️⃣ Virtual DOM의 등장

👀 Virtual DOM의 등장

그래서 등장한 것이 Virtual DOM 입니다. Virtual DOM은 기존 DOM의 친구이자 어떤 복사본이라고 할 수 있습니다.

또 다른 표현으로 Virtual DOM은 HTML DOM의 추상화 버전입니다. 실제 DOM object와 같은 속성들을 가지고 있지만, 실제 DOM이 갖고 있는 api는 갖고 있지 않습니다.

데이터가 변경되면 전체 UI는 Virtual DOM에 렌더링 됩니다. 그리고 이전 Virtual DOM에 있던 내용과 업데이트 후에 내용을 비교하여 실제 DOM에 적용시킵니다.

즉 Virtual DOM에 변경사항이 반영되면 원본 DOM에 필요한 변화만 반영되어서 전체 real DOM을 바꾸지 않고도 필요한 UI의 업데이트를 적용할 수 있습니다.

Virtual DOM은 어떻게 생겼길래 이런 동작이 가능할까요?


👀 Virtual DOM의 동작 원리

Virtual DOM은 HTML객체에 기반한 자바스크립트 객체로 표현할 수 있습니다. 이러한 처리는 실제 DOM이 아닌 메모리 상에서 동작하기 때문에 훨씬 더 빠르게 동작합니다. 그리고 Virtual DOM tree는 실제 렌더링이 되지 않기 때문에 연산비용이 적습니다. 그래서 실제 DOM 리렌더링에 비해서 효율적입니다.

사실 Virtual DOM이 하는 것은 DOM fragment에 변화를 묶어서 적용시킨 다음에 기존 DOM에 던져 주는 과정입니다. Virtual DOM은 이 과정을 자동화, 추상화해놓은 것에 불과합니다.


1️⃣ React의 Virtual DOM

React는 Virtual DOM을 이용하는 대표적인 자바스크립트중 하나입니다. 리액트의 공식문서에서는 Virtual DOM을 다음과 같이 설명합니다.

👀 JSX

리액트는 JSX라는 문법과 함께 사용됩니다. 각 컴포넌트에서 리턴되는 React element를 JSX 문법으로 작성하는 것입니다. 마치 그냥 html 태그들처럼 생겼지만 JSX는 자바스크립트의 확장 문법입니다.

이렇게 간단한 JSX를 컴포넌트에서 리턴시키면 바벨은 JSX를 React.createElement()호출로 컴파일 합니다. 실제 바벨에서 변환을 시켜보면 다음과 같이 React element 객체를 리턴하는 것을 볼 수 있습니다.

그리고 React.createElement()로 생성된 React element는 내부적으로 다음과 같은 객체로 표현될 수 있습니다.

앞에서 본 Virtual DOM 객체 구성형태와 비슷합니다. React elements는 DOM 요소의 가상 버전으로 가볍고, 상태를 가지지 않으며, 불변성을 유지합니다. 이 불변성 덕분에 비교하고 업데이트 하는 게 쉬워집니다.

React elements는 React DOM의 render에 의해서 비로소 실제 DOM 요소가 됩니다. React는 이 객체를 읽어들이고 이를 사용해서 DOM을 구성하고 항상 최신상태로 유지합니다.

앞에서 말했듯이 React elements는 변경이 불가능합니다. 그래서 한번 요소를 만들었다면 데이터가 변했다고 해서 그 자식이나 속성을 맘대로 변경할 수 없습니다. 각 element는 해당 순간의 UI를 스냅샷 형태로 보여주기만 할뿐입니다. 그러면 UI를 업데이트할 수 있는 유일한 방법은 새로운 요소를 만들어 ReactDOm.render()로 전송하는 것 뿐입니다.

여기서는 <Backend/>라는 컴포넌트를 <Frontend/>라는 컴포넌트로 바꿔주고 싶은 것 뿐인데 아에 새로운 element를 render 해야 되는 것처럼 보입니다. 하지만 이 때 React는 Virtual DOM을 이용합니다.


👀 React의 Virtual DOM의 diffing 알고리즘

모든 React DOM Object는 그에 대응하는 Virtual DOM object가 있습니다. 그리고 Virtual DOM object는 그 DOM object 하나하나에 매핑됩니다.

데이터가 업데이트되면 바뀐 데이터를 바탕으로 React.createElement()를 통해 JSX element를 렌더링 합니다. 이때 모든 각각의 Virtual DOM Object가 업데이트 됩니다. 이 때 Virtual DOM은 빠르게 업데이트 되기 때문에 비용이 많이 들지 않습니다.

그리고 Virtual DOM이 업데이트 되면 React는 Virtual DOM 을 업데이트 이전에 Virtual DOM 스냅샷과 비교하여 정확히 어떤 Virtual DOM 이 바뀌었는지 검사합니다.

이 과정을 'Diffing'알고리즘이라고 리액트에서 부르고 있고 리액트의 재조정 과정에 해당됩니다. element의 속성 값만 변한 경우에는 속성 값만 업데이트 하고, 해당 엘리먼트에 태그나 컴포넌트가 변경된 경우라면 해당 노드를 포함한 하위의 모든 노드들을 언마운트(제거)한 뒤에 새로운 Virtual DOM으로 대체합니다. 이런 변경이나 업데이트가 모두 마무리 된 이후에 마지막에만 실제 DOM에 이 결과를 업데이트 합니다.


🤔 항상 virtual DOM이 DOM보다 빠를까요?

=> 정답은 NO!

정보 제공만 하는 웹페이지라면 인터렉션이 발생하지 않기 때문에 일반 DOM성능이 더 좋을 수도 있습니다. 그리고 실제의 Virtual DOM의 'diffing'알고리즘이 빠르긴 하지만 추가적인 작업이 발생하기 때문에 필요에 맞게 도입을 고려해야 합니다.

그러나 SPA로 제작된 큰 규모의 복잡한 웹페이지에서는 DOM조작이 많이 발생하기 때문에 Virtual DOM을 사용해서 브라우저 연산량을 줄여서 성능을 좀 더 개선할 수 있습니다.


📝 Virtual DOM 렌더링 과정

  1. 전체 Virtual DOM이 업데이트 된다.

  2. Virtual DOM을 업데이트 이전의 시점과 비교한다.

  3. 실제 바뀐 부분만 Real DOM에서 바꾼다.

  4. Real DOM에서의 변화가 스크린에 그려진다.



🌐 참조 사이트

profile
느리지만 꾸준하게 💪🏻

0개의 댓글