브라우저 렌더링

Duboo·2021년 12월 10일
0
post-thumbnail

렌더링

렌더링이란
html, css, js 등 개발자가 작성한 문서(웹 페이지 구성을 위한 자료)를 해석하여 사용자의 장치에 맞게 그래픽 형태로 변환해 출력하는 과정입니다.

브라우저렌더링 엔진부가 설명
파이어폭스 FireFox게코 Gecko모질라 재단에서 만든 레이아웃 엔진
사파리 Safari웹킷 Webkit애플에서 개발한 오픈소스 현재는 웹킷2를 사용
크롬 Chrome블링크(Blink)애플의 웹킷 사용 중 웹킷을 fork해서 블링크(Blink) 엔진을 자체 구현 및 사용
익스플로러 IE트라이던트 Trident마이크로소프트의 레이아웃 엔진

크로스 브라우징 이슈 : 모든 브라우저가 같은 렌더링 엔진을 사용하지 않기 때문에 같은 소스를 사용하더라도 다른 결과가 보여질 수 있습니다. 렌더링 엔진이 다른 만큼 렌더링 과정도 차이가 있습니다.


ip 주소(Internet Protocol address)

사용자가 브라우저의 *UI 주소창을 통해 원하는 페이지(혹은 네트워크로 연결된 장치)를 찾기 위해서는 해당 페이지의 *ip 주소(Internet Protocol address)를 알아야합니다.

  • *UI(User Interface) : 이전/다음, 주소 표시줄, 북마크 메뉴, 새로고침 등..

  • *ip 주소 (Internet Protocol address) : 인터넷을 사용하는 모든 네트워크 장치들이 통신하기 위해 사용하는 특수한 번호

    • Example : 93.184.216.34
    • IP version 4 주소 : 줄여서 IPv4 주소는 오늘날 일반적으로 사용하는 IP 주소입니다.
    • IP version 6 주소 : 늘어나는 인터넷 사용에 의해 새로 도입된 방법입니다.
      • 32비트의 주소 공간을 제공하는 IPv4에 반해 IPv6는 128비트의 주소공간을 제공합니다.

도메인 네임 시스템(Domain Name System, DNS)

사용자가 ip 주소(93.184.216.34)를 외워서 사용하기란 많이 불편합니다.

DNS는 특정 컴퓨터(네트워크 장치)의 주소를 찾기 위해 사람이 이해하기 쉬운 도메인 이름을 숫자로 된 식별 번호(IP 주소)로 변환해줍니다.

  • Example : example.com ➡️ 93.184.216.34

사용자가 도메인 이름을 검색하게 되면 도메인과 ip 주소를 가지고 있는 저장소(Domain Name Server)에서 사용자가 검색한 도메인에 해당하는 ip 주소를 반환해줍니다.


case 1

만약 입력받은 도메인이 이미 방문한적이 있는 주소라면 DNS 서버에게 물어보고 찾아보고 하는 일이 자원적 낭비입니다.
따라서 브라우저는 도메인 요청이 일어나면 가장 먼저 로컬의 캐시 영역에서 해당 도메인에 맞는 ip 주소를 찾기 시작합니다.

  • 이것이 가능한 이유는 브라우저 엔진이 *자료 저장소(Data Persistence)와 정보를 공유하기 때문입니다.
  • *자료 저장소(Data Persistence) : 로컬 스토리지, 쿠키 등 클라이언트 사이드에서 데이터를 저장하는 영역입니다.

case 2

방문한적 없는 주소라면 DNS 서버에서 해당 ip 주소를 찾아 로컬 캐시 영역에 저장합니다.
다음에 다시 방문하게 된다면 case 1에 해당됩니다.

그렇게 브라우저는 DNS에게 받은 ip 주소에 해당하는 서버에 데이터를 요청하게 됩니다.

앞서 얘기한 *사용자 인터페이스(UI), *자료 저장소(Data Persistence)와 브라우저 엔진의 관계는 위와 같습니다.

  • 브라우저 엔진 : 사용자 인터페이스와 렌더링 엔진을 이어주는 다리 역할, 자료 저장소와 데이터를 공유
  • 렌더링 엔진 : html, css를 파싱해 화면에 표시하는 역할
  • 통신: HTTP 요청/응답을 위해 네트워크 호출에 사용
  • JS 엔진: 자바스크립트 코드를 해석하고 실행
  • UI 백엔드 : 기본적인 위젯을 그림

데이터 요청과 응답

이제 브라우저는 서버에게 데이터를 요청할 수 있고 서버는 요청에 맞는 응답을 할 수 있습니다.

*브라우저 = 클라이언트

HTTP

  • HTTP(HyperText Transfer Protocol) : 웹 브라우저와 웹 서버가 통신을 할 때 사용하는 통신 규칙(규약)
    • 웹 브라우저와 웹 서버가 알아들을 수 있는 공통적인 메세지로 크게 요청을 보낼 수 있는 Request와 응답을 위한 Response로 구분되어 있습니다.

해당 내용은 본 주제를 다루기에 너무 많은 내용이라 간략하게 정리합니다.


렌더링 과정

서버로부터 html, css, js, img 등.. 웹에 필요한 리소스를 다운로드 받습니다.

브라우저가 페이지를 렌더링하기 위해서는 *렌더링 트리(Rendering Tree)가 필요합니다.

렌더링 트리를 만들기 위해 html의 DOM 트리css의 CSSOM 트리가 필요합니다.

Pasing | DOM tree

서버로 부터 받아온 html 코드가 DOM 트리로 변환되는 과정입니다.
바이트 변환 ➡️ 토큰 식별 ➡️ 노드 변환 ➡️ DOM 트리 빌드

브라우저와 서버의 통신 과정에서 서버는 브라우저로부터 요청 받은 html 파일을 읽은 후 메모리에 저장한 뒤, 메모리에 저장된 바이트를 응답하게 됩니다.

  • 응답받은 바이트를 읽어 html 문서 내에 정의된 인코딩에 따라 문자열로 변환합니다.
    • 변환(Conversion) | UTF-8, euc-kr
  • 변환된 문자열은 W3C 표준에 따라 지정된 고유의 토큰(token)으로 변환합니다.
    • 토큰화(Tokenizing) | 각 토큰은 특별한 의미와 고유한 규칙을 가집니다. ex) <html>, <body>
  • 변환된 토큰을 속성 및 규칙을 정의하는 '객체'로 변환합니다.
    • 렉싱(Lexing) | 객체로 변환하여 node를 생성합니다.
  • 생성된 node는 html 요소간의 부자관계에 따라 트리 자료구조로 만들어집니다.
    • 즉, DOM이 생성 됩니다. DOM 생성(Dom construction)

위 과정을 Pasing한다 합니다.

  • 서버에게 받은 문서를 브라우저가 이해할 수 있는 구조로 변환하는 과정입니다.

DOM(Domcument Object Model)

브라우저는 html 마크업을 처리할 때 마다 위의 단계를 수행합니다.


Pasing | CSSOM tree

html 문서를 한줄씩 읽으며 순차적으러 파싱하며 DOM을 생성하던 중 css의 link 태그 혹은 style 태그를 만나게 되면 html 파싱을 중지한 뒤 css 파일을 서버에 요청/응답 후 css 파싱을 시작합니다.

css의 파싱 과정은 바이트 변환 ➡️ 토큰 식별 ➡️ 노드 변환 ➡️ CSSOM 트리 빌드로 동일합니다.


Pasing | Javascript

자바스크립트는 scirpt 태그로 분류되는데 렌더링 엔진이 해당 태그를 만나게 되면 모든 권한이 자바스크립트 엔진에게 넘어가며 자바스크립트를 파싱합니다.

이때 자바스크립트 엔진의 작동 방식에 대해서 알아야하는데, 자바스크립트 엔진은 연산 및 출력이 가능하도록 CPU가 이해할 수 있는 언어로 자바스크립트 코드를 파싱하여 html, css와 마찬가지로 *트리를 생성합니다.

자바스크립트 엔진의 작동 방식을 간략하게 살펴보자면 먼저 엔진이 실행할 자바스크립트 파일을 받으면 파싱, AST(Abstract Syntax Tree)를 구축하는 과정을 거치게됩니다. 다음으로 인터프리터가 코드를 읽으며 실행합니다.

  • 자바스크립트는 인터프리터 언어

자바스크립트에 대한 해당 내용은 중요한 내용이므로 간략하게만 정리하고 따로 글을 작성합니다.


Blocking Resource

Javascript

브라우저가 html 문서를 파싱 중 스크립트 태그를 만나면 자바스크립트 엔진에게 권한을 넘겨주기 때문에 html은 파싱을 중지합니다.

  • 파서를 강제로 중단 시키기 때문에 "파서 차단 리소스"(Parser Blocking Resource)라 부릅니다.

  • 즉, 자바스크립트가 실행되는 동안은 html을 파싱할 수 없기 때문에 웹페이지의 로딩이 늦춰질 수 있습니다.

  • 혹은 DOM이 완성되지 않은 상태에서 자바스크립트 코드가 DOM Api를 통해 DOM 조작을 시도하여 에러를 발생시킬 수 있습니다.

    • 생성되지 않은 DOM 노드를 읽거나 조작하는 것은 불가능하기 때문

html의 파싱이 끝난 뒤 다시 말해 <body> 태그의 최하단에 스크립트 태그를 넣는 이유가 해당 이유 때문입니다.

이러한 이슈 때문에 scirpt 태그에 async, defer 속성을 넣어 사용하는 방법도 있습니다.

해당 내용 또한 따로 글을 작성합니다.


css

반면 css의 link 태그는 <head>안에 정의합니다.

  • css는 Javascript와 비슷하지만 다른 "렌더링 차단 리소스(Rendering Blocking Resource)"입니다.

이유는 stylesheets의 경우 렌더링에 필수적인 요소이기 때문에 브라우저는 css 파일을 빠르게 다운로드하고 파싱하는게 중요합니다.

  • 렌더링에 필수적인 요소란, 사용자의 화면에 컨텐츠를 빠르게 렌더링하기 위함

  • css는 DOM 트리를 변경하지 않기 때문에 DOM 파싱을 중단하거나 하는 이슈가 발생하지 않습니다.

    • 하지만 css 파싱이 완료되지 못한 시점에서 자바스크립트 코드가 스타일 정보를 요청하게 된다면 스크립트 에러가 발생할 수 있습니다.
      • 위와 같은 문제를 해결하기 위해 브라우저별 다양한 해결책이 있습니다.

Rendering tree

DOM 트리와 CSSOM 트리가 만들어지면, 이 둘을 결합해서 렌더링 트리를 생성합니다.

  • 이 과정을 Attachment라 합니다.

렌더 트리의 생성은 최상단 부모 즉, DOM 트리의 루트 노드부터 시작하며 서치합니다.
구조와 텍스트 형태의 DOM 트리 최상단 노드부터 각 노드에 대해 CSSOM의 규칙을 적용하여 렌더 트리를 완성시킵니다.

이때 렌더 트리에는 페이지를 렌더링 하는데 필요한 노드만 포합됩니다.

  • display: none;과 같은 속성은 CSSOM 트리에만 포함되지 렌더 트리에는 포함되지 않는다는 의미입니다.
  • meta 태그와 실제로 보여지지 않는 태그도 포함되지 않습니다.


Layout or Reflow

이렇게 완성된 렌더 트리는 Layout 과정이 필요합니다.
브라우저의 뷰포트 내에서 각 노드들의 정확한 위치와 크기를 정확하게 캡처하는 Box 모델이 출력됩니다. 또한 %, vh, vw와 같은 상대적인 측정값의 속성값들은 모두 절대적인 px단위로 변환됩니다.

Painting

레이아웃이 완료되고 요소들의 위치 및 크기 그리고 스타일 계산이 완료된 렌더 트리를 사용해 브라우저는 각 노드 요소들을 실제 화면에 그리게 됩니다.

  • 해당 과정을 Painting(래스터화라고도 합니다.)이라 하며 당연히 일반적인 스타일 효과보다 복잡한 스타일 효과에 소요시간이 더 필요합니다.

Reflow, Repaint

대부분의 웹은 사용자에게 정적인 화면이 아닌, 동적인 화면을 제공합니다.
즉, 렌더링 과정이 끝나더라도 지속적으로 웹에는 변화가 일어납니다.

특정한 이벤트를 통해서 기존 노드들에게 변화가 생기면 렌더 트리 생성과 레이아웃 과정을 다시 수행해야하며 이러한 과정을 Reflow라 합니다.

Example : Reflow

  • 노드의 추가 및 제거
  • 뷰포트 변경 (전체화면에서 화면을 줄인다거나 반대의 경우)
  • 요소의 위치 변경, 크기 변경

대표적인 Reflow 속성들
position, width, height, margin, padding, border, border-width, font-size, font-weight, line-height, text-align, vertical-align, overflow


또한 이렇게 변경된 렌더 트리와 레이아웃을 실제로 화면에 그리기 위해 다시 한번 페인팅 과정이 필요합니다. 이를 Repaint라 합니다.

대표적인 Repaint 속성들

background, background-image, background-position, background-repeat, background-size, border-radius, border-style, box-shadow, color, line-style, outline,outline-color, outline-style, outline-width, text-decoration, visibilty

하지만 무조건 변경 사항이 생길 때마다 Reflow-Repaint가 일어나는것은 아닙니다.
레이아웃에 영향이 없을 경우에는 Repaint만 다시 수행합니다.

  • 당연히 Reflow에는 Repaint가 필요합니다.

렌더링 최적화

브라우저 렌더링이 빠를 수록 사용자는 쾌적한 UI/UX를 기대할 수 있습니다.
즉, 렌더링 최적화가 필요합니다.

Reflow 최소화
당연한 말이지만 렌더 트리와 레이아웃을 다시 수행해야 하는 Reflow는 최소화하는것이 좋습니다.

Reflow는 항상 Repaint를 불러옵니다. 하지만 Repaint는 Reflow없이 발생할 수 있기 때문에 되도록 Repaint만 발생하는 속성을 사용하는 것이 좋습니다.

프레임
사용자에게 부드러운 화면을 제공하기 위한 애니메이션은 렌더링 최적화는 반비례합니다.
애니메이션을 적은 시간/이동 단위로 사용하는 것보다 큰 시간/이동로 사용하는것이 Reflow를 줄일 수 있기 때문에 적당한 타협이 필요합니다.

영향을 받지 않는 노드를 최대한 사용하는것 즉 영향을 주는 노드들의 사용을 줄이는 방법 또한 좋은 방법입니다.

profile
둡둡

0개의 댓글