JS/React

[React] #7 리액트의 리랜더링 : Virtual DOM

emayom 2021. 8. 28. 17:44

리액트의 특징을 확인하면서

Virtual DOM 그러니까 VDOM의 개념을 알아봤었다!

 

오늘은 강의를 들으며 나왔던 코드를 통해

자바스크립트와 리액트의 리랜더링 방식의 차이에 대해 확실히 알아보자. 🤔

 

 

[React] 리액트 : #1 React ?

오늘은 리액트가 무엇이고 왜 리액트인지를 알아보는 시간을 가지려고한다. 👨🏻‍🎨 리액트 == 자바스크립트 라이브러리 React, Angular, Vue 알지 못하더라도 셋 중 하나 이상은 꼭 들어봤을 것

emayom.tistory.com


 

리랜더링 ?

 

랜더링은 사용자에게 View를 보여주는 것을 의미한다.

 

바닐라 자바스크립트의 경우

변경 사항이 있을 때마다 새로 그려나가며

전반적인 DOM 엘리먼트들을 다시 그려 화면에 표시해줬다.

결국 단순 랜더링 과정이 반복되는 것이다!

 

 

하지만,

리액트는 초기 랜더링과 리랜더링 두 개념이 존재한다!

 

초기 랜더링 과정을 거치고 나면 기존 DOM 상태를 메모리에 기억해두고

수정이 일어날 경우 VDOM이라는 추상적인 개념을 통해

랜더링 된 결과물과 비교하여 리랜더링 과정을 거치게 된다.

이후엔 수정된 부분만 부분적으로 업데이트하는 것이다!

 

이러한 과정을 리랜더링이라고 하는데

전체 뷰를 변형하는 것이 아닌 일부분을 새로운 요소로 갈아 끼우는 방식이기 때문에

이렇게 뷰를 업데이트하는 과정을 '조화 과정(Reconciliation)'을 거친다'라고 표현한다.

 

 

 

+)

아래에 링크된 리액트 공식 문서에서는 tick이라는 함수를 정의해

setInterval(tick, 1000)을 통해 매 초마다 바뀐 시간을 랜더하도록 보여준 예시가 있다!

개발자 도구까지 보여주며 자세하게 설명해준다! 참고하자.

 


 

이제 정말 코드를 작성해보자. (tmi ...✳︎)

 

1초마다 버튼 내부의 숫자가 바뀌도록 코드를 작성했다.

오늘도 리액트 코드는 동일하게 CDN unpkg 코드를 넣어서 html 내부에서 작성할 것이다!

 

// Vanilla JS
<div id="root"></div>
<script>
    const root = document.getElementById("root");
    
    //random()
    function random() {
      const number = Math.floor(Math.random() * (10 - 1) + 1);
      const element = `
        <button>
          ${number}
        </button>
        `;
      root.innerHTML = element;
    }
    
    setInterval(random, 1000);
</script>
//CDN unpkg
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

<div id="root"></div>

//JSX
<script type="text/babel">
  const root = document.getElementById("root");
  
  function random() {
    const number = Math.floor(Math.random() * (10 - 1) + 1);
    const element = <button>{number}</button>
    ReactDOM.render(element, root);
  }
  
  setInterval(random, 1000);
</script>

 

 

분명 같은 기능을 하는 코드이지만 코드를 직접 실행해보면

 

바닐라 자바스크립트 코드는

루트 엘리먼트인 <div>를 포함한 엘리먼트들이 매초 새로 만들어져 다시 그려지는 반면,

 

리액트는 버튼의 내부의 속성(props)만

즉, 숫자만 바뀌고 있는 것을 확인해볼 수 있다.

 

 

 

 

 

 

React Element == Immutable

 

React 엘리먼트는 불변 객체(Immutable)이다.

 

위에서 우리는 함수를 1초마다 실행시키며

계속 새로운 엘리먼트를 넘겨줬다. 

하지만 ? 모두 반영되며 새로 생성하거나 변경되지는 않았다.

 

만약 우리가 다른 타입의 루트 엘리먼트를 넘겨주었다면

변하는 것이 아니라 이전의 트리는 버리고 아주 새로 작성했을 것이다!

 

 

 

여기서 알아야 하는 부분은

우리는 ReactDOM.render()로 리액트에 전달만 할 뿐 

변경을 판단하고 반영하는 것은 리액트에서 알아서 하는 것이다.

 

 

 

비교 알고리즘 (Diffing Algorithm)

 

리액트는 재조정(변경 반영)을 위한

비교 알고리즘(Diffing Algorithm)이라는 기준을 가지고 있다.

 

조금 더 자세하게 알아보자면,

가장 먼저 루트(root) 엘리먼트부터 비교하게 된다.

 

루트 엘리먼트가 다르다면 ?

이전 트리를 버리고 완전히 새로운 트리를 구축한다.

하지만 위의 코드는 루트 엘리먼트의 타입이 같기 때문에 타입이 변경되지 않았다.

 

루트 엘리먼트 타입이 같다면 ?

Key를 먼저 비교한 후 → 속성(props)을 비교한다.

동일하게 같으면 유지, 다르다면 변경사항을 반영하는 것이다.

 

 

 

+)

여기까지 리액트의 리랜더링 과정에 대해 알아봤다.

VDOM을 이용하여 부분적으로 업데이트한다는 사실은 알고 있었지만,

어떤 기준으로 어떻게 판단하는지까지 확실하게 알 수 있었다 ! 

 

리액트,,,, 재미따 ,,, 🤓

 


 

 

재조정 (Reconciliation) – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

⚠️ 아래 내용은 모두 개인적인 참고 / 기록을 위한 용도입니다. 참고해주시고 편안하게 봐주세요 :)  ⚠️
***    혹시라도 잘못된 정보가 있다면  언제든지 알려주시면 감사하겠습니다  !    ***