브라우저 렌더링(Rendering)

MyeonghoonNam·2021년 2월 11일
3

브라우저

목록 보기
2/2

렌더링(Rendering)이란 ?

렌더링이란 HTML, CSS, JavaScript등 개발자가 작성한 문서를 브라우저에서 그래픽 형태로 출력하는 과정을 말합니다. 즉, 클라이언트(사용자)에서 서버로부터 여러 파일을 받아 브라우저에 나타나는 과정을 말합니다.

브라우저 기본 구조

렌더링을 이해하기 위해 브라우저의 구조를 살펴보자.

각 구성 요소는 다음과 같은 역할을 하고 있다. 물론 구조는 브라우저마다 조금씩 다를 수 있다.

  • 사용자 인터페이스: 주소 표시줄, 이전/다음 버튼, 북마크 등 페이지 뷰 이외의 다른 부분
  • 브라우저 엔진: 사용자 인터페이스와 렌더링 엔진 사이 동작 제어
  • 렌더링 엔진: HTML, CSS를 파싱해 화면에 요청한 컨텐츠를 표시
  • 통신: HTTP요청과 같은 네트워크 호출에 사용됨
  • JS 엔진: 자바스크립트 코드를 해석하고 실행
  • UI 백엔드: 기본적인 위젯(콤보 박스 등)을 그림
  • 자료 저장소: 자료를 저장하는 계층으로 쿠키 등을 저장하는 웹 데이터베이스

렌더링 엔진

렌더링 엔진은 위에서 설명한 것처럼 요청받은 내용을 브라우저 화면에 표시해주는 역할을 한다. 브라우저마다 사용하는 렌더링 엔진이 각각 다르기 때문에, 모든 브라우저가 동일한 소스를 화면에 동일하게 그려주지 않고 엔진마다 읽을 수 있는 코드의 버전도 다릅니다.

렌더링 엔진 동작 과정

  • 렌더링 엔진은 HTML 문서를 파싱 하여 DOM 트리를 만들고, CSS 문서를 파싱 하여 CSSOM 트리를 만듭니다.
  • DOM과 CSSOM을 이용하여 렌더 트리를 만듭니다.
  • 렌더 트리 생성이 끝나면 렌더 트리의 배치가(Layout, Reflow라고 부름) 시작됩니다. 이 과정은 각 노드가 화면의 정확한 위치에 표시하기 위해 위치와 크기를 계산하는 과정을 말합니다.
  • 마지막으로 계산된 위치과 크기 등의 스타일들을 실제 픽셀로 표현하는 그리기 과정이 시작됩니다. 이 과정을 Paint라고 합니다.

렌더링 엔진 상세 동작 과정

상세과정을 통하여 더 자세히 이해해보자.

위의 그림은 Webkit 엔진의 렌더링 동작 과정입니다. (크롬 브라우저는 사파리 브라우저에서 사용하는 Webkit을 사용하다가 버전 28 이후 Webkit 소스를 Fork 하여 Blink 엔진을 만들어 사용하고 있습니다.)

  • HTML을 파싱하여 DOM 노드들을 만든 후 병합하여 DOM 트리를 만듭니다.
  • CSS를 파싱하여, CSSOM 트리(Style Rules)를 만듭니다.
  • DOM 트리와 CSSOM 트리를 사용하여, Attachment라는 과정을 통해 Render 트리를 생성합니다.
  • Render 트리를 배치(Layout)합니다.
  • Render 트리를 화면에 그립(Painting)니다.

이제 동작 과정에서의 주요 처리 기능인 Parser, Attachment, Layout, Panting에 관하여 알아보자.

1. Parser

  • 파싱은 서버로부터 전송받은 문서의 문자열을 브라우저가 이해할 수 있는 구조로 변환하는 과정을 파싱이라고 합니다. 이러한 파싱 과정이 Parser에서 이루어 집니다.

  • DOM(Documnet Object Model) 트리 생성

    위의 렌더링 엔진의 상세 동작 과정에서 말한 DOM 트리를 파싱하는 과정이다.

  1. 변환(Conversion): HTML의 원시 바이트(raw bytes)를 읽어와 해당 파일에 지정된 인코딩(UTF-8 등…)에 따라 문자열로 변환하는 과정입니다.
  2. 토큰화(Tokenizing): 문자열을 HTML5 표준에 따라 고유 토큰(, 등, 꺽쇠괄호로 묶인 문자열)으로 변환합니다. 각 토큰은 특별한 의미와 고유한 규칙을 가집니다.
  3. 렉싱(Lexing): 토큰을 해당 속성 및 규칙을 정의한 객체(Nodes)로 변환합니다.
  4. DOM 생성(Dom construction): HTML은 상위-하위 관계로 정의할 수 있어, 트리 구조로 나타낼 수 있습니다. 렉싱 과정을 거쳐 생성된 노드들을 트리 구조로 변환합니다.

    위 4가지 과정을 걸치면 최종적으로 아래와 같은 DOM트리가 생성되어집니다.

  • CSSOM(CSS Object Model) 트리 생성

    위의 렌더링 엔진의 상세 동작 과정에서 말한 CSSOM 트리를 파싱하는 과정이다.

    브라우저는 DOM을 생성하는 동안 외부 CSS를 참조하는 <link> 태그를 만나게 되면 브라우저에 리소스를 요청합니다. CSS의 원시 바이트(raw bytes)가 문자열로 변환된 후 차례로 토큰과 노드로 변환되고 마지막으로 CSSOM(CSS Object Model)이라는 트리 구조를 만듭니다.

    CSSOM이 트리 구조를 가지는 이유는 하향식으로 규칙을 적용하기 때문입니다. 최종 스타일을 계산할 때 브라우저는 해당 노드에 적용 가능한 가장 일반적인 규칙으로 시작해 더 구체적인 규칙을 적용하는 방식입니다.

    위의 CSSOM 트리 그림을 보시면 하양식 규칙 적용을 좀 더 쉽게 이해할 수 있습니다. body 태그 내에 있는 span 태그 안에 포함된 텍스트의 크기는 16px이고 색상은 빨간색입니다. 하지만 span 태그가 p 태그의 하위인 경우 해당 콘텐츠는 표시되지 않습니다.

  • 참고 (JavaScript는 어떻게 처리할까 ?)

    자바스크립트는 렌더링 엔진이 아닌 자바스크립트 엔진이 처리한다. HTML 파서가 <script> 태그를 만나면 자바스크립트 코드를 실행하기 위해서 DOM 트리 생성 프로세스를 중단하고 자바스크립트 엔진에 제어 권한을 넘기게 된다.(즉, 진행하던 html 문서 파싱을 중지 그렇기에 보통 자바스크립트를 <head> 태그가 아닌 <body> 태그가 닫히기 바로 전에 사용되도록 하는 것이 좋습니다.)
    자바스크립트 엔진은 <script> 태그 내의 js 코드와 src 속성에 정의된 js파일을 로드하고 파싱하여 실행. 자바스크립트의 실행이 완료되면 다시 HTML 파서로 제어 권한을 넘기고 브라우저가 중지된 시점부터 DOM 생성을 재개.

    이러하듯 렌더링 과정에서의 성능을 개선하기 위해 <script> 태그에 defer 속성을 주면, 문서 파싱은 중단되지 않고 문서 파싱이 완료된 이후에 자바스크립트가 실행됩니다. 이렇듯 HTML5에서 스크립트를 비동기로 처리하는 속성(defer, async)에 대해서는 아래 나의 다른 포스팅을 참고해보자.

    Script 태그의 async와 defer

2. Attachment

CSSOM 트리와 DOM 트리를 결합하여, 표시해야 할 순서로 내용을 그려낼 수 있도록 하기 위해 렌더 트리를 형성합니다. 이 과정을 Attachment라고 합니다. 렌더 트리는 페이지에 표시되는 모든 DOM 콘텐츠와 각 노드에 대한 모든 CSSOM 스타일 정보를 가지고 화면에 표시되는 각 노드의 위치를 계산하는 Layout 과정에에 사용되고 픽셀을 화면에 그리는 Paint 과정에도 사용됩니다. (렌더링 엔진 상세 동작 과정 이미지 참고)

렌더 트리를 생성하려면 브라우저는 대략 3가지 작업을 수행합니다.

  1. DOM 트리의 루트에서 시작하여 화면에 표시되는 노드 각각을 탐색합니다.
    화면에 표시되지 않는 일부 노드들(script, meta 태그 등..)은 렌더 트리에 반영되지 않습니다.
    CSS에 의해 화면에서 숨겨지는 노드들은 렌더 트리에 반영되지 않습니다. 위의 예시에서 span 노드의 경우 display:none이 설정되기 때문에 렌더 트리에 반영되지 않습니다.
  2. 화면에 표시되는 각 노드에 대해 적절하게 일치하는 CSSOM 규칙을 찾아 적용합니다.
  3. 화면에 표시되는 노드를 콘텐츠 및 계산된 스타일과 함께 내보냅니다.

참고 : DOM 트리와 렌더 트리의 관계
렌더 트리 구축의 1번에서 잠깐 이야기 한 것처럼 화면에 표시되지 않는 노드들은 렌더 트리에 포함되지 않습니다. 예를 들어, 태그와 같은 비시각적 DOM 노드는 렌더 트리에 추가되지 않습니다.

뿐만 아니라 CSS로 인해 display 속성에 none 값이 할당된 노드들을 렌더 트리에 추가되지 않습니다. 하지만, visibility:hidden은 렌더 트리에 포함됩니다. visibility 속성에 hidden 값이 할당된 노드는 화면에 공간을 차지하기 때문에 렌더 트리에 포함됩니다.

3. Layout

렌더 트리가 생성되고, 기기의 뷰포트 내에서 렌더 트리의 노드가 정확한 위치와 크기를 계산하는 과정을 Layout이라고 합니다. 모든 상대적인 측정값은 화면에서 절대적인 픽셀로 변환됩니다. 즉 CSS에 상대적인 값인 %로 할당된 값들은 절대적인 값은 px 단위로 변환 됩니다.

4. Painting

렌더 트리의 각 노드를 화면의 실제 픽셀로 나타내는 과정을 Painting 이라고 합니다. Painting 과정 후 브라우저 화면에 UI가 나타나게 됩니다.

요약

지금까지 이야기했던 내용들을 핵심만 요약하여 5가지로 정리해 보면

  1. HTML 마크업을 처리하고 DOM 트리를 빌드 합니다. (DOM 파싱)
  2. CSS 마크업을 처리하고 CSSOM 트리를 빌드 합니다. (CSS 파싱)
  3. DOM 및 CSSOM을 결합하여 렌더 트리를 형성합니다. (Attachment)
  4. 렌더 트리에서 레이아웃을 실행하여 각 노드의 형태(크기, 위치 등)를 계산합니다. (Layout)
  5. 개별 노드를 화면에 페인트 합니다. (Painting)

위의 5단계를 걸쳐 브라우저는 화면에 렌더링 하게 됩니다.

렌더링 최적화 - Reflow, Repaint 줄이기

  • Reflow
    어떤 액션이나 이벤트에 따라 html 요소의 크기나 위치등 레이아웃 수치를 수정하면 그에 영향을 받는 자식 노드나 부모 노드들을 포함하여 Layout 과정을 다시 수행하게 된다. 이렇게 되면 Render Tree와 각 요소들의 크기와 위치를 다시 계산하게 되고, 이 과정을 Reflow라고 합니다.
  • Repaint
    렌더링 과정에서도 알 수 있듯이 Reflow 과정만으론 화면에 실제로 반영되지 않는다. Reflow 과정이 일어난 후, 화면에 다시 그리는 작업을 Repaint라고 한다.

    하지만 반드시 Reflow 와 Repaint가 같이 일어나는 것은 아니다. background-color, visibility 등 레이아웃에 영향을 주지 않는 스타일 속성이 변경되었을 경우에는 Repaint만 발생한다.

참고자료

profile
꾸준히 성장하는 개발자를 목표로 합니다.

0개의 댓글