브라우저 렌더링 과정
1. DOM 트리 생성
렌더 엔진이 HTML을 파싱하여 DOM 노드로 이루어진 트리 생성
2. render 트리 생성
- css 파일과 inline 스타일을 파싱하여 DOM + CSSOM = render 트리 생성
- 시각적인 구조를 나타냄
3. Layout (Reflow)
뷰포트 내에 생성된 render 트리의 각 노드들이 스크린에서의 좌표에 따라 위치 결정
4. Paint (Repaint)
실제로 화면에 그리기
문제
- 어떤 인터랙션으로 DOM에 변화가 발생하면 render 트리가 그때마다 재생성됨
- 변화가 발생하면 모든 요소들의 스타일을 다시 계산하고 똑같은 과정을 반복해야 함
- 최근에는 SPA에서 DOM 트리를 즉각적으로 많이 변경하는 경우가 생김
- 전체 페이지를 서버에서 매번 보내주는 것이 아니라 브라우저단에서 자바스크립트가 관리하기 때문에 DOM 조작을 더 효율적으로 할 수 있게끔 최적화가 필요하여 생긴 Virtual DOM
Virtual DOM
- 기존 DOM의 친구이자 복사본
- HTML DOM의 추상화 버전
- 실제 DOM 오브젝트와 같은 속성을 갖고 있지만, 실제 DOM이 갖고 있는 API는 갖고 있지 않음
- 데이터가 변경되면 전체 UI는 Virtual DOM에 렌더링 됨
- 이전 Virtual DOM에 있던 내용과 업데이트 후의 내용을 비교하여 바뀐 부분만 실제 DOM에 적용시킴
- 즉, Virtual DOM에 변경사항이 반영되면 원본 DOM에 필요한 변화만 반영되어 전체 real DOM을 바꾸지 않고 업데이트 가능
- Virtual DOM은 HTML 객체에 기반한 자바스크립트 객체로 표현할 수 있음
- 위는 DOM이 아닌 메모리 상에서 동작하여 더 빠름
- Virtual DOM 트리는 실제 렌더링 되지 않기 때문에 연산 비용이 적음
- 즉, 모든 변화를 하나로 묶어서 딱 한 번만 실행시키기 때문에 실제 DOM 리렌더링에 비해 효율적임
- DOM fragment의 변화를 묶어서 적용한 다음, 기존 DOM에 던져주는 과
정
- Virtual DOM은 이 과정을 자동화, 추상화해 놓은 것에 불과함
React와 Virtual DOM
재조정
UI의 가상적인 표현을 메모리에 저장하고 React DOM과 같은 라이브러리에 의해 실제 DOM과 동기화
JSX
- 각 컴포넌트에서 return 되는 element를 JSX문법으로 작성
- 자바스크립트 확장 문법
- 리턴시키면
babel
은 JSX를 React.createElement() 호출하여 컴파일 함
- react element는 내부적으로 객체로 표현될 수 있음
- Virtual DOM 객체 구성형태와 비슷함
light
& immutable
& stateless
: 상태를 가지지 않고, 불변하며, 상태를 가지지 않음
- 불변성 덕분에 비교하고 업데이트하기 쉬워짐
- react element는 ReactDOM의 render에 의해서 실제 DOM 요소가 됨
- React는 이를 이용하여 DOM을 구성하고 항상 최신 상태로 유지
- react element는 불변하므로 한번 요소를 만들면 데이터가 변해도 그 자식이나 속성을 맘대로 변경할 수 없음
- 각 element는 해당 순간의 UI를 스냅샷 형태로 보여줄 뿐임
- 따라서 UI를 업데이트할 수 있는 유일한 방법은 새로운 요소를 만들어 ReactDom.render()로 전송하는 것 뿐임
- 모든 React DOM 오브젝트는 그에 대응하는 Virtual DOM 오브젝트가 있음
- 그 Virtual DOM 오브젝트는 DOM 오브젝트 하나하나에 매핑됨
- 데이터가 업데이트 되면 바뀐 데이터를 바탕으로 React.createElement()를 통해 JSX element를 렌더링함
- 이때 각각 모든 Virtual DOM 오브젝트가 빠르게 업데이트 되어 비용이 많이 들지 않음
Diffing 알고리즘
- Virtual DOM이 업데이트 되면 React는 Virtual DOM을 업데이트 이전의 Virtual DOM 스냅샷과 비교하여 어떤 Virtual DOM이 바뀌었는지 확인함
- element의 속성 값만 변한 경우 속성 값만 업데이트하고, 태그나 컴포넌트가 변경된 경우라면 해당 노드를 포함한 모든 하위 노드를 unmount, 제거한 뒤에 새로운 Virtual DOM으로 대체
- 업데이트 마무리된 이후에 딱 한 번 실제 DOM에 이 결과를 업데이트 함
1. 전체 Virtual DOM이 업데이트 됨
+ 버튼을 누르면 이미지 태그 요소가 하나 추가되고 바뀐 데이터에 따라 전체 Virtual DOM이 업데이트 됨
2. Virtual DOM을 업데이트 이전의 시점과 비교
3. 실제로 바뀐 부분만 real DOM에서 바꿈
새로운 이미지 태그만 real DOM 트리에 렌더링 됨
4. real DOM에서의 변화가 스크린에 그려짐
전체 DOM 트리가 처음부터 다시 그려지는 것이 아니라 Virtual DOM의 도움을 받아 이미지 태그가 하나 추가된 부분만 새로 그려지게 됨
Virtual DOM이 DOM보다 무조건 빠를까?
- NO, 정보 제공만 하는 웹페이지라면 인터렉션이 발생하지 않아(DOM 트리 변화가 발생하지 않음) 일반 DOM의 성능이 더 좋을 수도 있음
- SPA로 제작된 큰 규모의 웹 페이지는 Virtual DOM을 사용해서 브라우저의 연산 양을 줄여 성능을 개선할 수 있음