ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] 리액트 Virtual DOM
    ReactJS 2022. 11. 30. 23:24

    1. DOM이란 ?

    “DOM은 HTML, XML document와 상호작용하고 표현하는 API이다. DOM은 browser에서 로드되며, Node(이하 노드) 트리(각 노드는 document의 부분을 나타낸다)로 표현하는 document 모델이다. ex. element, 문자열, 혹은 코멘트” -MDN-

     

    프로그램이 문서 구조, 스타일 및 내용을 변경할 수 있도록 문서를 노드와 객체로 나타냅니다. 

    위 사진을 보고 HTML이 DOM이라고 생각할 수 있지만 그렇지는 않습니다. IDE에서 작성한 HTML은 DOM이 아니고

    작성된 HTML 문서가 브라우저에 의해 해석되어 실제 문서를 나타내는 노드 트리가 DOM입니다. 이렇게 하는 이유는 프로그래밍 언어가 페이지와 상호 작용할 수 있게 하기 위해서 입니다. DOM API는 JavaScript와 같은 스크립팅 언어를 이용해서 해당 문서에 노드 추가, 삭제, 변경, 이벤트 처리, 등 수정을 가능케 합니다. 우리가 Javascript로 프로젝트를 하며 사용했던 document.getElementById, document.querySelector, document.addEventListener 등이 DOM API입니다.

     

    2-1. DOM을 조작했을 때 브라우저가 동작하는 방식

    1. DOM Tree 생성 : 브라우저가 HTML을 전달 받으면 브라우저의 렌더 엔진이 이를 파싱해서 DOM 노드로 이루어진 트리를 만듭니다.
    2. Render Tree 생성 : 외부 css파일과 각 엘리먼트의 스타일을 파싱합니다. 스타일 정보를 사용하여 DOM트리에 따라 새로운 트리, 렌더 트리를 만듭니다. 이 과정을 구체적으로 말하자면, 노드의 스타일을 처리하는 과정을 "attachment"라고 부르는데, DOM트리의 모든 노드들은 "attach"라는 메소드가 있고, DOM 트리의 노드들의 attach 메소드가 이 과정에서 실행됩니다. attach 메소드는 스타일 정보를 계산해서 객체 형태로 반환합니다. 이 과정은 동기적 작업이며, DOM 트리에 새로운 노드가 추가되면 그 노드의 attach 메소드가 실행됩니다. 렌더 트리 과정에선 각 요소들의 스타일이 계산되고 이 계산되는 과정에서 다른 요소들의 스타일 속성들을 참조합니다.
    3. Layout (reflow) : 렌더 트리가 만들어지고 나면 각 노드들은 스크린의 좌표가 주어지고 정확히 어디에 나타나야 할지 위치가 주어집니다.
    4. Painting 렌더링된 요소들에 색을 입히는 과정, 트리의 각 노드들을 거쳐가며 paint 메소드를 호출합니다.

    2-2. 문제가 되는 상황

    복잡해지는 구조, 사용자의 인터랙션 등 웹 사이트들이 고도화되면서 위의 과정이 반복되는 횟수가 늘어날수록 비효율적이 됩니다. 예를들어 30개의 노드를 하나 하나 수정하면 30번의 레이아웃 재계산과 30번의 리렌더링을 초래합니다.

     

    3-1. Virtual DOM

    Virtual DOM은 DOM을 직접 조작하지 않고 변경사항을 하나의 가상 돔에 모았다가 DOM에 한 번에 보내는 기술입니다.

    DOM 조작의 연산 비용을 줄일 수 있는 방법으로 나온 대안이 Virtual DOM입니다.

    React는 실제 DOM의 변경 사항을 빠르게 파악하고 반영하기 위해 내부적으로 가상 DOM을 만들어서 관리합니다. Virtual DOM은 일종의 DOM 캐싱, DOM 버퍼링이라고 할 수 있습니다. 가상 DOM은 DOM이 생성되기 전에 아래와 같은 비교 과정을 수행합니다.

     

    연산이 끝나고 그 최종 변화를 실제 DOM에 던져줍니다. 모든 변화를 하나로 묶어서 딱 한 번만 주는거기 때문에

    레이아웃 계산과 리렌더링의 규모는 커지겠지만 DOM 연산의 횟수가 줄어듭니다. 만약 virtual DOM을 통한 절차를 거치지 않았다면 전체 노드가 빨간색 (변화 대상)이 되었을 것 입니다. DOM 조작 자체가 문제가 되는 것은 아니지만 사소한 변경사항에도 전체가 리렌더링된다면 효율적인 연산은 아니겠지요.

     

    요약하자면뷰에 변화가 있을 때 실제 DOM에 적용되기 전에 가상의 DOM에 먼저 적용시키고 그 최종적인 결과를 실제 DOM으로 전달해줍니다. 이는 브라우저 내에서 발생하는 연산의 양을 줄여줍니다.

     

    3-2. Virtual DOM에 대한 오해

    Redux 창시자이자 React 개발팀원인 Dan Abramov 의 트윗에도 나와있다시피 “리액트가 DOM보다 빨라서 사용한다”는 잘못된 사실입니다. 게다가 3-1의 과정은 Virtual DOM이 없어도 이루어질 수 있습니다. 그럼에도 리액트와 virtual DOM을 사용하는 이유는 3-1과 같은 관리 과정을 수동으로 하나하나 작업할 필요없이, 자동화하고 추상화해주기 때문입니다.

     

    → “리액트에서 감지한 변화들을 모아 DOM에 전달한다”는 흐름은 아래 내용들을 이해하는데 도움이 됩니다.

    공통 : 리액트가 컴포넌트의 변화를 감지해야 렌더링을 시킬 수 있는데 리액트가 컴포넌트를 감지하는 방법을 이해하지 못하고 리액트에서 권장하는 방법에 맞춰 사용하지 않으면 리액트가 변화를 감지하지 못할 수 있습니다.

     

    1. setState로만 값을 변경해줘야 하는 이유 = 불변성을 유지해야 하는 이유
      • 설명객체 비교시 판단 근거는 객체의 메모리 주소인데 직접 값을 수정하면 메모리 주소가 동일하여 리액트는 변화를 감지하지 못합니다. 상태 변경을 추적하고 변경에 따라 구성요소를 다시 렌더링하려면 setState를 사용해야 합니다. map, filter, spread 문법을 사용해서 새로운 배열을 반환하라는 이유도 그것때문입니다.
      • 값이 변경 되었다는걸 판단하기 위해 리액트는 객체로 저장된 state를 비교 연산합니다.
    2. react에서 props로 key를 넘겨줘야 하는 이유 
      • 설명고유한 Key값이 없다면 모든 데이터를 비교해야 하지만, Key가 있으면 Key값만 비교하여 Key가 추가 됐는지, 삭제 됐는지만 비교하면 돼서 불필요한 렌더링을 없애줍니다.

Designed by Tistory.