React의 Virtual DOM 개념이 더티 모델 검사보다 성능이 뛰어난 이유는 무엇입니까?


372

나는 ( Pete Hunt : React : Rethinking best practice-JSConf EU 2013 ) 에서 React dev 강연을 보았고 발표자는 모델의 더러운 확인이 느릴 수 있다고 언급했습니다. 그러나 대부분의 경우 가상 DOM이 모델보다 커야하므로 가상 DOM 간의 차이를 계산하는 것이 실제로 성능이 떨어 집니까?

Virtual DOM (특히 서버 측 렌더링)의 잠재력을 정말 좋아하지만 모든 장단점을 알고 싶습니다.


난 당신이 너무이 이야기를 말할 수 있다고 생각 youtube.com/watch?v=-DX3vJiqxm4 그는 특히 벤치 마크에 대해 이야기 곳.
inafalcao

답변:


493

저는 virtual-dom 모듈 의 기본 저자 이므로 귀하의 질문에 대답 할 수 있습니다. 실제로 해결해야 할 두 가지 문제가 있습니다.

  1. 언제 다시 렌더링합니까? 답변 : 데이터가 더러워진 것을 관찰했습니다.
  2. 효율적으로 다시 렌더링하려면 어떻게합니까? 답변 : 가상 DOM을 사용하여 실제 DOM 패치 생성

React에서 각 구성 요소는 상태를 갖습니다. 이 상태는 녹아웃 또는 다른 MVVM 스타일 라이브러리에서 볼 수있는 관찰 가능과 같습니다. 기본적으로 반작용이 알고있는 경우 가 때이 데이터 변경 관찰 할 수 있기 때문에 장면을 다시 렌더링 할 수 있습니다. 정기적으로 데이터를 폴링하고 데이터 구조의 모든 값을 재귀 적으로 확인해야하기 때문에 더티 검사는 관찰 가능 항목보다 느립니다. 이에 비해 상태 값을 설정하면 일부 상태가 변경되었음을 리스너에게 알릴 수 있으므로 React는 단순히 상태에서 변경 이벤트를 수신하고 다시 렌더링을 대기시킬 수 있습니다.

가상 DOM은 DOM을 효율적으로 다시 렌더링하는 데 사용됩니다. 이것은 실제로 데이터 더러운 검사와 관련이 없습니다. 더티 검사가 있거나없는 가상 DOM을 사용하여 다시 렌더링 할 수 있습니다. 두 가상 트리 사이의 차이를 계산하는 데 약간의 오버 헤드가 있지만 가상 DOM 차이는 데이터가 변경되었는지 여부와 관계없이 DOM에서 업데이트해야 할 사항을 이해하는 것입니다. 실제로 diff 알고리즘은 더티 체커 자체 이지만 DOM이 더티인지를 확인하는 데 사용됩니다.

상태가 변경 될 때만 가상 트리를 다시 렌더링하는 것이 목표입니다. 따라서 옵저버 블을 사용하여 상태가 변경되었는지 확인하는 것은 불필요한 다시 렌더링을 방지하는 효율적인 방법으로, 불필요한 트리 차이가 많이 발생합니다. 아무것도 바뀌지 않았다면, 우리는 아무것도하지 않습니다.

가상 DOM은 마치 전체 장면을 다시 렌더링하는 것처럼 코드를 작성할 수 있기 때문에 좋습니다. 뒤에서 우리는 DOM을 업데이트하여 우리가 기대하는 방식을 보이는 패치 작업을 계산하려고합니다. 따라서 가상 DOM diff / patch 알고리즘 은 최적의 솔루션이 아니지만 응용 프로그램을 표현할 수있는 아주 좋은 방법입니다. 우리는 단지 우리가 원하는 것을 정확하게 선언하고 React / virtual-dom은 장면을 이렇게 보이게 만드는 방법을 연습 할 것입니다. 수동 DOM 조작을하거나 이전 DOM 상태에 대해 혼동하지 않아도됩니다. 전체 장면을 다시 렌더링 할 필요가 없으므로 패치하는 것보다 효율성이 떨어질 수 있습니다.


1
React는 구성 요소 소품에 대해 더티 검사를 수행합니까? setProps () 함수가 없기 때문에 묻습니다.
bennlich


1
그러한 예는 unnecessary re-renders무엇입니까?
vsync

9
"가상 DOM diff / patch 알고리즘이 최적의 솔루션이 아닐 수도 있습니다"라고 말하면 이론적으로 더 최적의 솔루션을 염두에 두어야합니까?
CMCDragonkai

3
이것은 질문에 대답하지 않는 것 같습니다. React는 상태가 변경되었음을 알리기 위해 setState를 사용해야합니다. 할 this.state.cats = 99수 있었다면 Angular dirty가 $ scope 트리를 점검하는 것처럼 모델 변경을 점검하기 위해 dirty 점검이 여전히 필요합니다. 이것은 두 기술의 속도를 비교 한 것이 아니며, 백본 스타일 설정자가 있기 때문에 React가 더티 검사를하지 않는다는 진술 일뿐입니다.
superluminary

133

최근에 React의 diff 알고리즘에 대한 자세한 기사를 읽었습니다 : http://calendar.perfplanet.com/2013/diff/ . 내가 이해 한 것에서 React를 빠르게 만드는 것은 다음과 같습니다.

  • 배치 된 DOM 읽기 / 쓰기 작업
  • 하위 트리 만 효율적으로 업데이트합니다.

더티 체크와 비교하여 IMO의 주요 차이점은 다음과 같습니다.

  1. 모델 더티 검사 : React 컴포넌트는 setState호출 될 때마다 명시 적으로 더티로 설정 되므로 여기에 데이터를 비교할 필요가 없습니다. 더티 검사의 경우 모델의 비교는 항상 각 다이제스트 루프에서 발생합니다.

  2. DOM 업데이트 : DOM을 수정하면 CSS 스타일, 레이아웃을 적용하고 계산하기 때문에 DOM 작업이 매우 비쌉니다. 불필요한 DOM 수정으로 절약 된 시간은 가상 DOM을 비교하는 데 소요되는 시간보다 길 수 있습니다.

두 번째 요점은 많은 양의 필드가 있거나 큰 목록이있는 것과 같은 사소한 모델에 훨씬 더 중요합니다. 복잡한 모델의 하나의 필드 변경으로 인해 전체 뷰 / 템플릿 대신 해당 필드와 관련된 DOM 요소에 필요한 조작 만 발생합니다.


1
실제로 나는 몇 가지 기사를 읽었으므로 이제는 (적어도 일반적으로) 작동 방식을 살펴 보았습니다. 더티 모델을 검사하는 것보다 더 효율적인 이유를 알아 내고 싶었습니다. 그리고 1) 예, 그것은 모델을 비교하지 않고 훨씬 더 큰 가상 돔을 비교합니다. 2) 모델의 더티 검사는 (앵귤러처럼) 필요한 것만 업데이트 할 수있는 능력을 제공합니다
Daniil

변경 된 구성 요소에 해당하는 가상 DOM의 일부만 비교해야한다고 생각하지만 더티 검사는 아무것도 변경되지 않더라도 모든 범위의 모든 값에 대해 모든 다이제스트 루프가 발생합니다. 많은 양의 데이터가 변경되면 Virtual DOM의 효율성이 떨어지지 만 작은 데이터 변경에는 적합하지 않습니다.
tungd

1
Angular에 관해서는, 감시자가 다이제스트하는 동안 상태를 변경할 수 있기 때문에 $scope.$digest다이제스트 사이클 당 여러 번 실행되므로 전체 데이터 비교의 여러 시간과 부분 가상 DOM 트리 비교의 단일 시간입니다.
tungd

4
많은 스마트 개발자들이 "느린"DOM 등을 다루기 위해 "산"을 개발하는 것은 슬픈 일입니다. 브라우저 자체를 수정하고 DOM 속도 저하를 완전히 없애기 위해 우리의 결합 된주의를 집중시키는 것이 아닙니다. 그것은 암 자체를 고치는 대신 암을 다루고 환자의 삶을 개선하는 방법을 연구하기 위해 모든 인류의 자원을 사용하는 것과 같습니다. 조롱.
vsync

@vsync DOM은 화면에 내용을 표시해야합니다. 가상 DOM은 그렇지 않습니다. 이상적인 DOM을 수행하더라도 가상 DOM을 만드는 것이 더 빠릅니다.
Jehan

75

Virtual DOM (특히 서버 측 렌더링)의 잠재력을 정말 좋아하지만 모든 장단점을 알고 싶습니다.

-OP

리 액트 만이 DOM 조작 라이브러리가 아닙니다. 자세한 설명과 벤치 마크가 포함 된 Auth0 의이 기사를 읽고 대안을 이해하는 것이 좋습니다 . 나는 당신이 요구 한대로 여기에 그들의 장단점을 강조하겠습니다 :

React.js의 가상 DOM

여기에 이미지 설명을 입력하십시오

찬성

  • 빠르고 효율적인 "확산"알고리즘
  • 다중 프론트 엔드 (JSX, 하이퍼 스크립트)
  • 휴대 기기에서 실행할 수있을 정도로 가벼움
  • 많은 견인력과 마음가짐
  • React없이 사용할 수 있습니다 (예 : 독립 엔진으로)

단점

  • DOM의 전체 메모리 사본 (더 높은 메모리 사용)
  • 정적 요소와 동적 요소를 구분하지 않음

Ember.js의 글 림머

여기에 이미지 설명을 입력하십시오

찬성

  • 빠르고 효율적인 디핑 알고리즘
  • 정적 요소와 동적 요소의 차별화
  • Ember의 API와 100 % 호환 (기존 코드를 크게 업데이트하지 않고도 이점을 얻을 수 있음)
  • DOM의 가벼운 인 메모리 표현

단점

  • Ember에서만 사용되는 의미
  • 하나의 프론트 엔드 만 사용 가능

증분 DOM

여기에 이미지 설명을 입력하십시오

찬성

  • 메모리 사용량 감소
  • 간단한 API
  • 많은 프론트 엔드 및 프레임 워크와 쉽게 통합 (처음부터 템플릿 엔진 백엔드로 의미)

단점

  • 다른 라이브러리만큼 빠르지 않습니다 (논쟁의 여지가 있습니다. 아래 벤치 마크 참조).
  • 적은 정신 공유 및 커뮤니티 사용

ReactJS의 DOM 조작에 대한 표현은 거의 나에게 보이지 않습니다. ReactJS의 가상 DOM은 실제 DOM이 아닌 완전히 변경되는 가상 DOM입니다. 맞습니까? 원본 기사에서 참조 기사를 참조하고 있으며 여기에는 teropa.info/images/onchange_vdom_change.svg가 있습니다. teropa.info/blog/2015/03/02/…
smile.al.d.way

35

다음은 React 팀 멤버 Sebastian Markbåge의 의견입니다.

React는 출력에서 ​​diffing을 수행합니다 (이것은 알려진 직렬화 가능 형식 인 DOM 속성). 즉, 소스 데이터는 모든 형식이 될 수 있습니다. 변경 불가능한 데이터 구조 및 클로저 내부 상태 일 수 있습니다.

각도 모델은 참조 투명도를 유지하지 않으므로 본질적으로 변경 가능합니다. 기존 모델을 변경하여 변경 사항을 추적합니다. 데이터 소스가 변경 불가능한 데이터이거나 매번 새로운 데이터 구조 (예 : JSON 응답) 인 경우 어떻게해야합니까?

더티 검사 및 Object.observe가 클로저 범위 상태에서 작동하지 않습니다.

이 두 가지는 기능 패턴에 매우 제한적입니다.

또한 모델의 복잡성이 커지면 더티 트래킹을 수행하는 데 점점 더 많은 비용이 듭니다. 그러나 React와 같은 시각적 트리에서만 차이를 내면 주어진 지점에서 화면에 표시 할 수있는 데이터 양이 UI에 의해 제한되기 때문에 그 수가 커지지 않습니다. 위의 피트 링크는 더 많은 퍼포먼스 혜택을 다룹니다.

https://news.ycombinator.com/item?id=6937668


2
실제로 마지막 단락에 대해 : 그것은 틀린 것입니다 : 각 모델 값마다 적어도 하나의 가상 돔 요소 (일반적으로 하나 이상)가 있기 때문에 모델이 가상 돔보다 큽니다. 표시되지 않은 모델을 원하는 이유는 무엇입니까?
Daniil

2
캐시 된 컬렉션을 페이지 매김.
kentor 2019

-2

Virtual Dom은 반응에 의해 발명되지 않습니다. HTML dom의 일부입니다. 가볍고 브라우저 별 구현 세부 사항에서 분리됩니다.

가상 DOM을 React의 로컬 및 단순화 된 HTML DOM 사본으로 생각할 수 있습니다. React가이 추상 세계 내에서 계산을 수행하고 "실제"DOM 작업을 생략 할 수 있습니다 (종종 느리고 브라우저에 따라 다름). 실제로 DOM과 가상 DOM 사이에는 큰 차이가 없습니다.

다음은 Virtual Dom이 사용되는 이유입니다 ( ReactJS의 소스 Virtual DOM ).

할 때 :

document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
  1. 브라우저는 HTML을 파싱해야합니다
  2. elementId의 자식 요소를 제거합니다
  3. DOM 값을 새로운 값으로 업데이트
  4. 부모와 자식의 CSS를 다시 계산하십시오.
  5. 레이아웃을 업데이트합니다. 즉, 화면에서 각 요소의 정확한 좌표
  6. 렌더 트리를 가로 질러 브라우저 디스플레이에 페인트

CSS와 변경된 레이아웃을 다시 계산하면 복잡한 알고리즘이 사용되며 성능에 영향을줍니다.

DOM 속성을 업데이트 할뿐만 아니라 가치. 알고리즘을 따릅니다.

이제 DOM을 10 번 직접 업데이트하면 위의 모든 단계가 하나씩 실행되고 DOM 알고리즘을 업데이트하면 DOM 값을 업데이트하는 데 시간이 걸립니다.

이것이 Real DOM이 가상 DOM보다 느린 이유입니다.


3
예를 들어, 직접 또는 가상 돔을 통해 돔을 수정하는 경우 마지막으로 두 경우 모두 돔을 변경합니다.
magallanes

두 경우 모두 dom을 업데이트하지만 가상 dom의 경우 키 (독특하게 알고리즘과 반응이 다릅니다) 필드 또는 요소 태그 만 업데이트합니다. dom 업데이트 또는 전체 dom을 완전히 새로 고치는 동안.
Hemant Nagarkoti

11
hackernoon.com/virtual-dom-in-reactjs-43a3fdb1d130 에서이 기사를 보았습니다. . 저자가 아닌 경우 소스를 지적하는 것이 좋습니다.
Jinggang

2
"이것이 Real DOM이 가상 DOM보다 느린 이유입니다." 아니, 당신은 단지 잘못입니다.
Roecrew
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.