ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] Virtual DOM, React Diffing Algorithm
    codeStates front-end/React 2023. 3. 22. 19:04
    반응형

     

     

    목차

       

       

       

       

      📌  리액트 심화

       

       

       

      📍Virtual DOM

       

      React는 UI의 상태를 추적하고 변화가 일어난 요소들을 빠르게 업데이트 할 수 있도록 가상의 DOM 객체를 활용한다.

       

       

      Real DOM (Document Object Model)

       

      DOM은 문서 객체 모델은 의미, 문서 객체란? 브라우저가 JS와 같은 스크링팅 언어가

      html 태그들에 접근하고 조작할 수 있도록 문서를 트리 구조로 객체화 한 것을 의미한다.

      즉, DOM은 브라우저가 HYML 문서를 조작할 수 있도록 트리 구조화한 객체 모델이다.

       

       

       

      DOM의 조작 속도가 느려지는 이유

       

      트리는 "저장된 데이터를 더 효과적으로 검색"을 위해 사용, 그러므로 트리구조 된 DOM은 탐색속도는 빠르다.

      그러나 DOM이 변경되고 업데이트 된다는 것은 결국 브라우저의 렌더링 엔진 또는 리플로우를 한다는 것을 의미

      잦은 리플로우 발생 👉🏻👉🏻 성능을 떨어뜨리는 문제 👉🏻👉🏻 바뀐 부분만 비교해서 그 부분만 렌더링 할 수 있을까?

       

       

      🔗  Virtual DOM이란?

       

      React에서는 DOM 객체에 대응하는 가상의 DOM이 있다.

      상대적으로 무거운 DOM에 비해 React의 가상 DOM 객체는 JS객체로 이루어졌고, 동일한 속성을 갖고 있어

      "훨씬 가벼운 사본"이라교 표현할 수 있다.

       

       

      Virtual DOM의 형태

       

      가상 DOM은 추상화된 JS 객체의 형태를 갖고 있다.

       

       

      DOM 트리

       

      DOM 트리를 JS 객체로 표현

       

      const vDom = {
      	tagName: "html",
      	children: [
      		{ tagName: "head" },
      		{ tagName: "body",
      			children: [
      				tagName: "ul",
      				attributes: { "class": "list"},
      				children: [
      					{
      						tagName: "li",
      						attributes: { "class": "list_item" },
      						textContent: "List item"
      					}
      				]
      			]
      		}
      	]
      }

       

       

       

      🔗  Virtual DOM의 동작 과정

       

      예를 들어, 특정 썸네일 클릭 시, 모달 플레이어가 생성되는 경우를 생각해보면,

      DOM은 특정 썸네일을 찾기 위해 전체 DOM이 리렌더링 되는 반면에, 가상 DOM에 저장된 이전 상태와 현재 상태를 비교해

      특정 부분만 리렌더링 된다. 이때 react는 setState와 같은 메서드를 활용

       

       

       

      Virtual DOM은 빠르다?

       

      빠른 것은 맞지만, 모든 경우에서 그렇지는 않다. 때로는 DOM조작이 빠르다.

      최적화가 잘되어 있어야 렌데링 속도의 차이는 상이하다.

       

       

       

      📍React Diffing Algorithm

       

      기존 가상 DOM과 새로운 가상 DOM을 비교할 때, reactsms 효율적으로 갱신해야하기 때문에,

      두 가지 가정을 가지고 시간 복잡도의 새로운 휴리스틱 알고리즘을 구현한다.

       

      1. 각기 서로 다른 두 요소는 다른 트리를 구축할 것이다.
      2. 개발자가 제공하는 key 프로퍼티를 가지고, 여러 번 렌더링을 거쳐도 변경되지 말아야 하는 자식 요소가 무엇인지 알아낼 수 있을 것이다.

      여기서 React는 비교 알고리즘(Diffing Algorithm)을 사용한다.

       

       

      🔗  React가 DOM 트리를 탐색하는 방법

       

      기존 가상 DOM과 새로운 가상 DOM을 비교할 때, 트리의 레벨 순서대로 순회하는 방식으로 탐색

      같은 위치끼리 비교한다는 뜻, 너비 우선 탐색의 일종이다.

       

       

       

      다른 타입의 DOM 엘리먼트인 경우

       

      html 태그마다 규칙이 있어 부모 태그가 바뀌어 버리면 새로운 트리를 구축하기 때문에 이전의 DOM 노드들은 전부 파괴된다.

       

      <div>
      	<Counter />
      </div>
      
      //부모 태그가 div에서 span으로 바뀝니다.
      <span>
      	<Counter />
      </span>

       

       

      같은 타입의 DOM 엘리먼트인 경우

       

      타입이 바뀌지 않는다면, 최소한의 변경 사항만 업데이트한다. 가상 DOM을 사용하기 때문

       

      <div className="before" title="stuff" />
      
      //기존의 엘리먼트가 태그는 바뀌지 않은 채 className만 바뀌었습니다.
      <div className="after" title="stuff" />
      
      //React 두 요소를 비교했을 때 className만 수정되고 있다는 것을 알 수 있다.
      // before와 after는 각자 다른 스타일을 갖고 있다.
      //className이 before인 컴포넌트
      <div style={{color: 'red', fontWeight: 'bold"}} title="stuff" />
      
      //className이 after인 컴포넌트
      <div style={{color: 'green', fontWeight: 'bold"}} title="stuff" />

       

      두 엘리먼트를 비교했을 때 color만 바뀐것을 보고 react는 color 스타일만 수정하고

      다른 요소들은 수정라지 않는다. 이렇게 하나의 DOM 노드를 처리한 뒤 React는 뒤이어서 해당 노드들 밑의 자식들을

      순차적으로 동시에 순회하면서 차이가 발견될 때마다 변경한다. 이를 재귀적으로 처리한다고 표현한다.

       

       

      자식 엘리먼트의 재귀적 처리

       

      // 자식 엘리먼트가 변경이 된다고 가정
      <ul>
        <li>first</li>
        <li>second</li>
      </ul>
      
      //자식 엘리먼트의 끝에 새로운 자식 엘리먼트를 추가했습니다.
      <ul>
        <li>first</li>
        <li>second</li>
        <li>third</li>
      </ul>

       

      react는 위에서 아래 순으로 비교하면 바뀐 점을 찾는다.

      첫 번째 자식 노드들과 두 번째 자식 노드들이 일치하는 걸 확인한 뒤 세번째 자식 노드를 추가

      헌나 이는 비효율적일 수 있어, react는 key라는 속성을 지원

       

      키(key)

       

      key는 같은 레벨 형제 노드에서만 유일하면 되며, 배열의 경우는 비효율적으로 동작할 것이다.

       

      //key를 이용해 기존 트리의 자식과 새로운 트리의 자식이 일치하는지 아닌지 확인 가능
      <ul>
        <li key="2015">Duke</li>
        <li key="2016">Villanova</li>
      </ul>
      
      //key가 2014인 자식 엘리먼트를 처음에 추가합니다.
      <ul>
        <li key="2014">Connecticut</li>
        <li key="2015">Duke</li>
        <li key="2016">Villanova</li>
      </ul>

       

       

       

      반응형

      'codeStates front-end > React' 카테고리의 다른 글

      [React] React와 TDD  (0) 2023.03.29
      [React] 코드 분할  (0) 2023.03.23
      [React] 번들링과 웹팩  (0) 2023.03.20
      [React]Cmarket Redux  (0) 2023.02.27
      [React] Redux  (0) 2023.02.24

      댓글

    Designed by Tistory.