ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [CS Study] 브라우저 랜더링 과정
    네트워크/CS Study 2024. 2. 14. 22:39
    개요

    1. WHY?
    2. 브라우저 랜더링 과정
    3. Reflow / Repaint
    4. CRP

     

    ✅ why?


    📦 내가 느끼는 브라우저 랜더링이  중요한 이유

    • 대부분의 프로그래밍 언어는 운영체제 또는 가상머신에서 실행되지만 자바스크립트의 경우 클라이언트에서 실행되기에 랜더링 과정을 통해서 어떻게 실행되는지 파악해야한다.(Node.js에서 실행시에는 다름)
    • 브라우저에서 HTML, CSS, JS는 함께 실행된다.
    • 화면이 그려지는 원리에 대해 파악함으로써 어느 부분에서 문제가 일어났는지 예측할 수 있고 이를 토대로 효율적이고 의도에 맞게 코드를 작성할 수 있다.
    • 사용자 경험을 향상시키기 위한 성능 최적화 시에 어떤 부분을 얼마만큼 최적화 시켰는지 최적화 시킬 수 있는 요소는 어떤 것이 있는지 알 수 있다.

    클라이언트에서 실행되는 언어인만큼 랜더링 과정과 원리에 대해 파악을 하고 어떻게 뼈대가 만들어지고 살이 붙어지는 지를 파악해서 의도한대로 코드가 실행되는 상황만 만났으면 좋겠습니다.

     

     

     

    브라우저 랜더링 과정


     

    1. 문서 파싱 (Document Parsing / scripting)
    2. 랜더 트리 구축 (Render Tree Construction / rendering)
    3. 레이아웃 (Layout) / 리플로우 (Reflow)
    4. 페인팅 (Paint) / 레스터화 (Rasterization)
    5. 합성 (Compositing)

     

     

    📦 문서 파싱 (Document Parsing)

    크게 HTML 파싱과 CSS 파싱으로 나뉘며 각각의 과정을 통해 DOM 트리와 CSSOM 트리가 생성 되며 이를 합쳐 Render 트리를 생성하는 과정이다.

     

    🎉 파싱(Parsing)과 렌더링(Rendering)

    더보기

    파싱

    주어진 데이터의 구조를 이해하고, 필요한 정보를 추출하거나 다른 형식으로 변환하는 것을 목적으로 하는 동작으로 일련의 문자열을 의미 있는 토큰으로 분해하고, 이 토큰들의 구조를 분석하여 주어진 규칙이나 문법에 따라 그 의미를 이해하는 과정

    랜더링

    HTML, CSS, JS로 작성된 문서를 파싱하여 브라우저에 시각적으로 출력하는 과정

    브라우저 랜더링 과정

     

     


     

    HTML 파싱

    DOM 트리는 브라우저가 HTML 문서를 불러온 후 파싱하여 생성하는 모델을 의미한다. HTML문서는 문자열로 이루어진 순수 텍스트로 브라우저가 HTML 페이지를 이해하고, 변경, 업데이트가 가능한 Object 형식으로 변환하는 과정이 HTML 파싱이다. 이후 생긴 DOM트리는 Object의 트리로 구조화되어 있다.

    HTML 파싱 과정

     


     

    CSS 파싱

    랜더링엔진은 순차적으로 한줄씩 파싱하며 DOM을 생성하는데 이때 중간에 CSS를 로드하는 <link>나 <style>을 만나면 DOM 생성을 일시 중단한다. 이후 브라우저는 DOM을 만들 듯 CSS를 이해할 수 있는 형식인 CSSOM으로 변환하며 이 과정을 CSS 파싱이라 한다. CSS 파싱이 완료 된 이후  HTML 파싱이 중단된 시점으로 돌아가 HTML 파싱을 시작한다.

     

    • 랜더링 엔진은 HTML을 파싱하여 DOM을 생성하다 CSS를 로드하는 <link>나 <style>을 만나면 DOM 생성을 일시 중단한다.
    • 웹브라우저는 <link>를 통해 외부 CSS파일을 로드하거나 <style> 내에 포함된 인라인CSS를 읽어온다.
      React에서는 style 속성을 통해 객체 리터럴 형태로 전달하는 방식
    • 로드된 CSS코드는 파싱과정(바이트-문자-토큰-노드-CSSOM)을 거치면서 CSSOM으로 변환된다.
    • CSS 파싱이 완료되면 HTML 파싱을 재개하여 DOM 트리를 생성한다.

    🎉 CSS  규칙

    더보기

    브라우저는 최종 스타일을 계산할 때 하향식으로 규칙을 적용하는데 이 방식은 가상 상위의 body에 적용된 스타일을 body 하위의 모든 노드에 적용 후 구체적인 규칙을 적용하는 방식이다. 이러한 적용은 일반적인 CSS규칙 → 구체적인 CSS규칙 순으로 적용된다.

    CSS 규칙

    위 이미지를 보면 body tag 하위에  font-size에 대한 값이 설정이 되는 것을 알 수 있다. 하지만 body > span과 body > p > span 중 display와 color에 대한 값은 각각 적용이 되는 곳이 있고 되지 않는 곳이 있다. 이는 cascading 룰을  이용해서 스타일을 세분화하기에 나오는 특징이다

    cascading
    중요도, 명시성, 소스 순서에 기반하여 우선순위를 결정하는 규칙으로써, 개발자가 복잡한 스타일시트를 작성할 때 일관성 있고 예측 가능한 스타일 적용을 보장하고, 효율적인 스타일 관리를 할 수 있게 도와주며 CSS규칙은 아래로 종속되는 특징이 있다. 

     


     

    랜더 트리 생성(Render Tree Construction)

    브라우저는 독립적인 두 개체인 DOM과 CSSOM을 병합하여 화면에 픽셀을 랜더링하기 위한 마지막 단계 최종적으로 브라우저에 표기될 것들만 선별되어 생성된다.
    생성된 랜더 트리는 표시되는 각 요소의 레이아웃을 계산하는데 사용되고 픽셀을 화면에 랜더링하는 페인트 프로세스에 대한 입력으로 처리가 되며, 이러한 단계를 이해하고 각각을 최적화하는 것이 중요하다.

    • DOM 트리의 루트에서 시작해서 노드 각각을 읽으며 표시를 한다.(사용자에게 보여지지 않아도 되는 메타 태그나 스크립트 태그 등의 노드는 표시되지 않고, display: none;과 같은 CSS를 통해 숨겨진 일부 노드 또한 트리에서 생략된다.)

    - 픽셀

    더보기

    단순히 화면에 그려지는 가장 작은 단위의 색상의 정보를 뜻하며 이러한 픽셀의 조합을 통해 화면을 구성하고, 해상도와 색상의 표현에 직접적인 영향을 주는 요소이다.

    - visible: hidden; vs display: none;

    더보기

    전자는 요소가 보이지 않지만 레이아웃에서 공간은 차지하는 반면 후자의 경우 요소가 보이지도 레이아웃에 포함이 되지도 않는다.

     


     

    자바스크립트 파싱과 실행

    CSSOM과 DOM을 생성했던 것처럼 랜더링 엔진이 <script>를 만나게 되면 실행중이던 HTML 파싱이 중단되고 제어권이 자바스크립트 엔진으로 넘어가게 된다. 이후 파싱과 실행이 종료가 되면 HTML 파싱이 중단된 시점부터 다시 DOM 생성을 재개한다.
    • 크게 3단락으로 나눌 수 있으며, <script>의 위치는 성능에 영향을 미친다.
    • 소스코드를 토큰으로 분해하고 파싱해서 AST라는 추상적인 구문 트리로 생성한 뒤 인터프리터가 읽을 수 있도록 바이트코드를 생성하여 실행한다. 이때 자바스크립트 코드에 DOM이나 CSSOM을 변경하는 DOM API가 사용된 경우 변경된 상태로 다시 렌더 트리가 생성되며 리렌더링 되고 일한 과정을 각각 리플로우와 리페인팅이라고 한다.

    자바스크립트 파싱 과정

    🎉 <script>의 위치에 따른 성능 변화

    더보기

    body tag의 아래에 위치하는 것이 좋은 이유

    랜더링 엔진의 제어권이 넘어가는 현상으로 인해 성능적으로 아래에 위치할 때가 더 좋다는 의견도 있지만 아래의 이미지를 보면 사실은 에러가 발생하지 않기 위해 아래쪽에 위치해야한다는 결론이 나온다. DOM API에서 조작하고자 하는 Node가 생성되지 않은 경우가 있기에 이러한 상황을 방지하기 위해서는 body tag의 아래에 위치시키는 것이 좀 더 권장된다.

     

    하지만 필수인 것은 아니다. 그이유로는 하단에 위치한 경우에는 어쨌든 JS파일에 의존적인 페이지일 경우에는 불완전한 페이지를 보이기 때문이다.

    그렇기에 상황에 맞춰서 사용하면 된다.

     


     

    레이아웃(Layout)

    랜더 트리의 각 노드에 대한 실제 위치와 크기를 계산한다. 각 요소가 화면의 어느 위치에 어떤 크기로 표시될지 결정하는 단계
    • 레이아웃이 결정되면 화면에 픽셀을 그려진다.
    • position이나 size가 여기서 계산된다.
    • 페이지의 내용이 변경되어 요소의 위치나 크기가 변할 경우, 리플로우가 발생하여 계산이 다시 수행된다.

     


     

    페인팅(Paint)

    레이아웃 단계에서 계산된 정보를 바탕으로 각 요소(랜더 트리의 요소)를 실제로 화면에 그린다. 색상, 이미지, 텍스트 등의 시각적인 내용이 처리된다.

     


     

    합성(Compositing)

    복잡한 페이지의 경우 여러 레이어로 구성될 수 있으며, 이러한 레이어들은 별도로 렌더링된다. 이러한 레이어들을 최종적으로 하나의 페이지로 합치는 단계 주로 z-index의 계산을 통해서 최종 레이어를 결정한다고 보면 되는 단계

     

     

     브라우저 렌더링이 반복되는 경우


    리액트는 state와 props의 변화에 따라서 리렌더링이 일어나게 된다. 브라우저의 경우에는 아래 3가지 경우에 리랜더링이 일어나는데 이러한 리렌더링은 성능에 악영향을 주는 요소이기에 최대한 줄이기 위해 주의해야한다.

    • 자바스크립트에 의한 노드 추가 또는 삭제
    • 브라우저 창의 라사이징에 의한 뷰포트 크기 변경
    • HTML 요소의 레이아웃에 변경을 발생시키는 스타일 변경

     

     

     

    Reflow vs Repaint


    최종적으로 브라우저에 페이지가 그려진 후 특정 액션이나 이벤트에 따라 HTML요소의 크기나 위치 등의 레이아웃 수치가 변함으로 그에 영향을 받는 자식노드나 부모노드들이 포함되어 Layout(Reflow)과정을 다시 수행하며 이후 변동된 값을 통해 RePaint를 통해서 화면에 다시 그려주게 된다.

     

    📦 Reflow

    • 브라우저 리사이징 시 (viewport 크기 변경)
    • 노드 추가 또는 제거
    • 요소의 위치, 크기 변경
    • 폰트 변경과 이미지 크기 변경
    Reflow가 일어나는 대표 속성
    position, width, heigth, left, top, right, bottom, margin, padding, border, border-width, float...
    • position: fixed와 같은 경우 영향을 받는 노드가 전혀 없고 이렇게 영향을 받는 노드를 최소화하는 것이 좋다. (absolute, relative)

    2. Repaint

    Reflow가 발생했을 시에는 무조건 Repaint가 발생하지만 background-color나 opacity와 같이 위치나 크기가 변경되는 요소가 아ㅣ닌경우에는 Repaint만 일어난다.
    Repaint가 일어나는 대표 속성
    background, background-image, background-position, color, opacity...

     

     

     

     


     중요 랜더링 경로 (CRP, Critical Rendering Path)

    브라우저가 HTML, CSS 및 Javascript를 화면에 랜더링 된 픽셀로 변환하는 과정
    랜더링 경로를 최적화함으로 최초 페이지 랜더링에 걸리는 시간을 단축시킬 수 있다.

    1. 브라우저가 서버에게 HTML 파일을 요청하고 서버는 응답한다. (request / response)
    2. 서버에게 받은 HTML 파일을 로딩한다. (Loading)
    3. HTML을 한줄 한줄씩 읽어서 DOM과 CSSOM으로 변환한다. (Scripting)
    4. DOM과 CSSOM을 결합하여 랜더 트리를 형성한다. (Rendering)
    5. 각 노드의 위치 및 크기 계산을 한다. (Layout)
    6. 화면의 픽셀로 변환한다. (Painting)

    Construction Part: 브라우저가 이해할 수 있는 브라우저만의 언어로 바꾸는 작업 파트

    Operation Part: 랜더 트리를 이용해 구조 형성 및 배치 계산을 하여 화면의 픽셀로 변환하는 파트

     

    📦 최적화 포인트

    • Javascript나 CSS로 DOM요소를 조작할 때 Construction Part에서만 발생하는 것이 좋다.
    • Reflow가 발생하면 새롭게 계산을 하기에 성능이 좋지 않으니 Repaint만 발생하게끔 하는 것이 좋다. (Reflow 최소화)
    • 자원로드 순서를 관리하고, 파일 사이즈를 줄이며 어떤 자원을 먼저 로드할지 정함으로 페이지 로드 속도를 개선할 수 있다.
    • 자원 다운로드를 연기함으로 중요 자원들의 수를 최소화하기 (Lazy loading)
    • 각 요청에 대한 파일 사이즈에 따라 필수적인 요청 횟수 최적화하기 (code splitting)
    • 다운받을 중요 에셋의 우선순위를 결정함으로 순서를 최적화하고, 중요 경로 길이 최소화하기

    csstriggers 사이트를 통해 레이아웃 엔진 별 Operation의 유무를 확인할 수 있다  

     

     

     

    📌 reference

    댓글

Designed by Tistory.