본문 바로가기

Computer Programming/React

리액트가 Virtual DOM을 사용하는 이유?

1. DOM 조작의 비효율성과 Virtual DOM의 등장

 

우선 DOM이란 무엇일까?

https://nayoungkim00.tistory.com/47

 

[Browser] DOM (Document Object Model)

https://nayoungkim00.tistory.com/44 브라우저의 구조와 렌더링 엔진의 working process 에 관한 글을 먼저 작성했습니다. 이후 DOM 에 관해 모던 자바스크립트 Deep dive 책을 읽고 정리해보았습니다. 프론트엔드

nayoungkim00.tistory.com

 

 

DOM은 객체를 문서구조로 표현하는 방식으로, XML이나 HTML로 작성된다. 웹 브라우저는 이 DOM을 활용해 객체에 자바스크립트와 CSS를 적용한다.

 

 

 

추가 ) 브라우저의 렌더링 과정 

https://nayoungkim00.tistory.com/44

 

Browser - 브라우저의 구조와 렌더링 과정

1. 브라우저의 구조 웹브라우저의 기능이 다양화되면서 많은 역할을 수행하고 있습니다. 그러나 웹브라우저의 근본적인 역할은 웹페이지를 다운받아 렌더링하여 화면에 보여주는 것입니다. - Us

nayoungkim00.tistory.com

 

 

 

이 DOM은 트리 구조이기 때문에 특정 노드를 찾아 수정하거나 제거하는 작업이 가능하다. 그러나 대규모의 애플리케이션에서 어떤 동적 요소들을 움직일 때 모두 이 DOM을 조작한다면 어떨까

?

 

조작된 DOM 노드가 있다면 이 DOM 트리는 웹브라우저에 의해 CSS 를 다시 연산하고, 레이아웃을 구성한 뒤, 페이지를 리페인트해야한다. DOM 자체가 느린 것은 아니지만 DOM에 변화된 노드를 화면에 반영하기 위해 웹 브라우저는 같은 연산을 반복해야한다. 이는 비용이 많이들고 효율적이지 않은 작업이다.

 

 

최근 애플리케이션은 UX/UI의 극대화를 위해 사용자 인터렉션을 증가시키고, SPA의 등장으로 CSR이 대중화되었다. 그러나 그때마다 DOM 업데이트가 잦다면 성능이 매우 저하될 것이다.

 

이러한 상황에서 최적화의 문제가 대두되었고, 이를 해결하기 위해 리액트는 Virtual DOM 방식을 사용해 DOM 업데이트를 추상화하기로 한다. 그래서 결론적으로 DOM 처리 횟수를 최소화하고 효율적으로 진행할 수 있게 된다.

 

 

 

 

 

2. Virtual DOM

Virtual DOM은 실제 노드 트리를 복제해 추상화한 자바스크립트 객체이다. DOM보다는 가벼운 사본같은 느낌이다. 리액트는 실제 DOM에 바로 접근하여 사용하지 않는다.

 

 

만약 애플리케이션에서 데이터가 변하여 웹 브라우저에 실제 DOM을 업데이트해야 할 때에는 다음과 같은 절차를 거친다.

 

https://blog.bitsrc.io/incremental-vs-virtual-dom-eb7157e43dca

 

 

 

 

1. 애플리케이션 시작 시 실제 DOM이 생성되고, 브라우저에 UI가 렌더링된다. 이때 Virtual DOM은 이 DOM트리를 가벼운 버전으로 복사한다.

 

2. DOM 노드에 변화가 생기면, Virtual DOM은 새로운 가상의 돔 트리를 새롭게 만든다. 새롭게 만드는 부분이 비효율적이라고 느낄 수 있겠지만, Virtual DOM은 실제 화면에 렌더링 되는 것이 아니라 메모리상에서만 존재하기 때문에 상당히 빠르다.

 

3. 변경 전의 DOM 트리와, 변경 후의 DOM 트리를 비교하게 된다.

 

diff(previous: VTree, current: VTree) -> PatchObject

그러면 기존에 비해 변경된 부분을 DOM에 보내버리기만 하면 되는 것이다.

 

4. 실제 DOM에 적용한다.

 

patch(rootNode : DOMNode, patches: PatchObject) -> DOMNode newRootNode

이전의 3번에서 비교했던 새로 변경된 노드를 patch함수를 통해 실제 DOM에 적용하고 렌더링 과정을 수행한다.

 

 

 

이러한 과정에서 Virtual DOM은 일련의 버퍼링, 또는 캐싱의 과정이라고 말할 수 있다.

 

 

 

3. 재조정 (Reconciliation)

리액트에서는 자바스크립트를 확장한 문법인 JSX를 사용한다. 이 JSX는 Babel과 같은 툴에 의해 자바스크립트 객체로 변환되고, 이 객체들로 Virtual DOM tree가 구성된다.

 

재조정이란 이 Virtual DOM의 UI의 이상적인 또는 가상적인 표현을 메모리에 저장하고 ReactDOM과 같은 라이브러리에 의해 실제 DOM과 동기화하는 과정이다.

 

https://ko.legacy.reactjs.org/docs/reconciliation.html

 

재조정 (Reconciliation) – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

 

 

재조정 과정에서 리액트는 key prop 을 요구한다.

만약 수정 또는 삭제 등의 변경이 일어난 노드를 찾기 위해 모든 자식 노드를 모두 다시 연산한다면?

 

불필요한 연산으로 성능이슈 ,,,,

 

 

https://velog.io/@rlatp1409/TIL-Virtual-DOM

 

 

 

이러한 문제를 해결하기 위해 어떤 노드가 변경되었는지의 식별자로서 각 요소들의 유일성을 보장할 수 있는 key prop을 제공한다. 이를 이용해 기존의 트리의 자식과 새로운 트리의 자식이 일치하는지 아닌지 확인할 수 있다. 

 

 

* index를 key로 사용하면 -> 배열의 요소가 바뀔 때 (삭제)마다 index가 다시 부여되기 때문에, 배열의 요소에 변화가 있다면 사용하면 안된다.