[React] React 동작 방법 - Virtual DOM

조예진·2022년 7월 16일
2
post-thumbnail
post-custom-banner

📝 들어가기 전

프로젝트에서 React를 실제로 사용하고 있어서 React의 장점에 대해서는 어느 정도 파악하고 있다고 생각했다.

그런데 갑자기 의문이 들었다..!
화면 깜빡임 없이 변경사항만 부드럽게 화면에 표시해주는게 사용자 경험이 향상되는데 도움을 주는 건 알겠어,

근데 Virtual DOM은 왜 쓰는거지?
실제 DOM 조작이 왜 비효율적인거지?
어떤 부분 때문에 비효율적인거지?
등등..

브라우저 작동원리에 대한 이해도가 부족함에서 오는 의문들이었다.

그래서 이번 기회에 React의 작동원리도 제대로 짚고 넘어갈겸
브라우저 작동 원리 그리고 왜 DOM을 직접 조작하는게 비효율적인지에 대해서 공부해보려고 한다.

ps. 다른 분들이 잘 정리해놓은 글을 스스로 공부하기 위해 요약한 정도의 글이라
부족할 수 있다는 점 참고해주세요!


📍브라우저 랜더링을 위한 빌드업

  • User Interface: 주소 표시줄, 이전/다음 버튼, 북마크 메뉴 등. 요청한 페이지를 보여주는 창을 제외한 나머지 모든 부분
  • Browser Engine: User Interface와 Rendering Engine 사이의 동작을 제어
  • Rendering Engine: 요청한 콘텐츠를 표시, HTML을 요청하면 HTML과 CSS를 파싱 하여 화면에 표시함
  • Networking: HTTP 요청과 같은 네트워크 호출에 사용됨
  • Javascript Interpreter(또는 Engine): 자바스크립트 코드를 해석하고 실행함. 크롬에서는 V8 엔진을 사용함
  • Display Backend: 기본적인 위젯(콤보 박스 등..)을 그림
  • Data Persistence: Local Storage, 쿠키 등 클라이언트 사이드에서 데이터를 저장하는 영역

📍렌더링 엔진


🔺 chrome 브라우저 렌더링 엔진 workFlow

  • 요약
    • 렌더링 엔진의 역할은 요청받은 내용을 브라우저 화면에 나타내는 일

    • HTML, CSS, JavaScript 등의 파일을 브라우저가 화면에 표시할 수 있도록 변환하여 픽셀 단위로 나타냄

    • 렌더링 엔진은 브라우저마다 다르다. 그래서 같은 소스임에도 불구하고 브라우저마다 다르게 그려지는 크로스 브라우징 이슈가 발생하는 것이다.

      ㄴ 렌더링 엔진말고도 자바스크립트 엔진이 달라 발생할 수도 있긴 함

      알면 좋은 지식
      크로미움
        - 오픈소스 웹 브라우저
       	- v8 자바스크립트 엔진과 Blink라는 렌더링 엔진을 사용하는 브라우저
            - 크롬이 크로미움 기반으로 만들어진 브라우저?, 오픈 소스인 크로미움 브라우저 코드 위에 살을 덧붙여 개발되었다는 의미
              - Edge도 EdgeHTML 렌더링 엔진을 포기하고 크로미움 기반의 브라우저로 변경됨	
  • 동작 과정
    • HTML 문서 파싱해서 DOM 트리를 만들고
    • CSS 문서 파싱해서 CSSOM 트리 만들고
    • CSSOM, DOM을 이용하여 렌더 트리를 만듬
    • 렌더 트리 생성 끝나면 → Layout(Reflow)가 만들어짐
      • 각 노드가 화면의 정확한 위치에 표시하기 위해 위치와 크기를 계산하는 과정
    • paint 과정 실행됨
      • 계산된 위치와 크기 등의 스타일들이 실제 픽셀로 표시하는 과정

📍렌더링 최적화 방법

  • javascript
    • 자바스크립트는 파서 차단 리소스이다.
    • 브라우저는
      • 문서를 파싱하다가 자바스크립트를 만나면 진행하던 파싱을 중지하고
      • 자바스크립트 엔진에게 권한을 넘겨 자바스크립트를 파싱하고 실행한다.
    • 최적화 방법
      • 자바스크립트가 실행되는 동안 문서의 파싱은 중단되기 때문에 문서 파싱이 완료된 이후에 자바스크립트가 실행된다
      • 때문에 태그가 아닌 태그가 닫히기 바로 전에 사용되도록 하는 것이 좋다
      • 스크립트 비동기 처리가능 속성 : HTML5 스크립트 비동기로 처리하는 속성 추가됨
      1. async는 스크립트 리소스 다운로드가 완료된 시점에 스크립트가 실행되지만, defer는 HTML 파싱 하는 동안에 스크립트 다운로드하고 HTML 파싱이 완료되면 스크립트가 실행됩니다.
      2. async(default 값인 async=true일 경우)는 다운로드가 완료된 시점에 스크립트가 실행되어 스크립트 실행 순서를 보장할 수 없지만, defer의 경우 정의된 순서대로 스크립트가 실행됩니다.
  • CSS
    • 렌더링 차단 소스이다.
    • 안에 css를 정의해야하는 이유 - 렌더링을 할 때 반드시 필요한 리소스이기 때문에 브라우저가 빠르게 다운로드 받을 수 있도록 해줌
    • css는 DOM트리를 변경하지 않기 때문에 문서 파싱을 기다리거나 중단할 이유가 없다.
    • 그래서 자바스크립트에서 스타일 정보를 요청하는 경우 CSS가 파싱되지 않은 경우라면 스크립트 에러 발생 가능있음

📍 Virtual DOM

Virtual DOM이 필요한 이유

  • DOM에 변화가 생기면 랜더트리를 생성하고

    • 이 때 모든 요소들의 스탈일이 다시 계산된다. 위에서 말했던 레이아웃을 만들고 페인팅을 하는 과정이 다시 반복되는 것이다.
  • 복잡한 SPA는 DOM 조작이 많이 발생된다

    • DOM 조작이 많이 발생되면 문제는 무엇일까?
    1. 각 조작이 레이아웃 변화, 트리 변화와 렌더링을 일으킨다.

      → EX) 30개의 노드를 하나하나 수정하면 → 30번의 (잠재적인) 레이아웃 재계산과 30번의 (잠재적인) 리렌더링을 초래한다는 말이다.

    2. 반면에, Virtual DOM을 이용하면,

      → 인터렉션 발생 시 virtual DOM에서 먼저 적용시키고 최종 변화를 딱 한번만 실제 DOM에 적용시키는 것이다.

    3. Virtual DOM이 없이도 가능하긴 하다. 하지만 불편하다.

      	→ DOM fragment를 적용 후 실제 DOM에 주면 되지만
      	→ DOM fragment를 관리하는 과정을 수동으로 하나하나 다 작업해야하는데
      	virtual DOM은 어떤게 바뀌었는지, 어떤게 바뀌지 않았는지 자동으로 해준다
          

📍 Virtual DOM 의 역할

  • 어떤 인터렉션이 발생되면,
    1. 실제 DOM에 적용되기 전에 가상의 DOM에 먼저 적용시킨다.
    2. 그 후 최종적인 결과를 실제 DOM에 전달한다.
    → 이렇게 되면 실제 DOM은 최종 결과만 전달 받기 때문에 브라우저 내에서 발생하는 연산의 양이 줄어들고 성능이 개선된다.
  • DOM 관리를 Virtual DOM이 하도록 함으로써
    컴포넌트가 DOM 조작 요청을 할 때 다른 컴포넌트들과 상호작용을 하지 않아도 된다. 각 변화들의 동기화 작업을 거치치 않고 모든 작업을 하나로 묶어준다.

📍 React 장점

  • SPA로 사용자와의 인터렉션(상호작용)이 일어났을 때 화면 깜빡임 없이 변경사항만 부드럽게 화면에 표시해주는 사용자 인터페이스를 만들기 위한 JavaScript 라이브러리이다.

  • 데이터가 변경됨에 따라 적절한 컴포넌트만 효율적으로 갱신하고 랜더링한다.

    어떻게?

    위에 말했던 Virtual DOM 을 이용해서 갱신하다.
    인터렉션이 있을 때마다 DOM을 조작하면 브라우저의 연산 양이 늘어나기 때문에,
    React는 실제 DOM의 복제본으로 virtual DOM을 생성하여 인터렉션이 일어나면 Virtual DOM에서 먼저 데이터 갱신 여부를 체크하고, 변경된 사항을 반영한 후, 한번에 실제 DOM에 전달한다.


📝 참고

profile
블로그 이전 중 -> https://devjooj.tistory.com/
post-custom-banner

0개의 댓글