[CS 스터디]브라우저 렌더링 정리

Yewon Jeong·2023년 5월 7일
0

CS 스터디

목록 보기
3/19

검색창에 www.google.com을 검색하면 dns를 통해 해당 서버의 ip 주소를 가져오고 ip에 해당하는 서버와 tcp 연결이 이루어지면 이 위에서 http 통신이 이루어져 html 문서를 가져오게 된다. 이 때 가져온 html 문서의 렌더링 과정 대해 정리해 보았다.

dns 관련 포스팅 -> https://velog.io/@jeongye01/CSDNS%EB%9E%80

tcp 연결 관련 포스팅 -> https://velog.io/@jeongye01/CS-%EC%8A%A4%ED%84%B0%EB%94%94-TCP-%EC%97%B0%EA%B2%B0-%EC%A0%95%EB%A6%AC

HTML과 CSS는 표준 명세가 존재하고 이는 W3C(World Wide Web Consortium)에서 지정한다. 모던 브라우저들은 이를 기반으로 HTML파일을 해석한다. 과거에는 브라우저들이 일부만 이 명세에 따라 구현하고 독자적인 방법으로 확장함으로써 많은 크로스 브라우징 이슈를 유발했다.


브라우저의 렌더링 과정

HTML,CSS,JS란?

  • HTML(HyperText Markup Language)은 웹 페이지의 구조와 콘텐츠를 정의하는 언어다. HTML은 마크업 언어이며, 태그(tag)를 이용하여 콘텐츠의 구조를 정의한다.
  • CSS(Cascading Style Sheets)는 웹 페이지의 스타일을 정의하는 언어다. HTML이 웹 페이지의 구조를 정의한다면, CSS는 디자인과 레이아웃을 담당한다. CSS를 사용하여 웹 페이지의 폰트, 색상, 배경, 여백 등을 조정할 수 있다. 또한, CSS를 이용하여 반응형 웹 디자인을 구현하거나, 애니메이션 효과를 적용할 수도 있다.
  • JavaScript는 동적인 웹 페이지를 만들기 위한 언어다. JavaScript를 이용하여 웹 페이지의 상호작용을 구현할 수 있다. 예를 들어, 버튼 클릭 시 콘텐츠를 보여주거나, 폼 제출 시 데이터를 검증하는 등의 기능을 구현할 수 있다.

  • html,css,js를 위 이미지 처럼 비유할 수 있다.

브라우저의 기본 구조

브라우저 렌더링 과정에 많은 엔진들이 관여한다.

  • 사용자 인터페이스(User Interface, UI) - 브라우저에서 사용자와 상호작용하는 부분으로 주소 표시줄, 메뉴바, 북마크 등이 포함된다.
  • 브라우저 엔진(Browser Engine) - 사용자 인터페이스와 렌더링 엔진 사이의 동작을 제어한다.
  • 렌더링 엔진(Rendering Engine): 요청한 콘텐츠를 표시. 예를 들어 HTML을 요청하면 HTML과 CSS를 파싱하여 화면에 표시한다.
  • 통신 - HTTP 요청과 같은 네트워크 호출에 사용됨. 이것은 플랫폼 독립적인 인터페이스이고 각 플랫폼 하부에서 실행됨.
  • UI 백엔드 - 콤보 박스와 창 같은 기본적인 장치를 그림. 플랫폼에서 명시하지 않은 일반적인 인터페이스로서, OS 사용자 인터페이스 체계를 사용.
  • 자바스크립트 해석기 - 자바스크립트 코드를 해석하고 실행.
  • 자료 저장소 - 이 부분은 자료를 저장하는 계층이다. 쿠키를 저장하는 것과 같이 모든 종류의 자원을 하드 디스크에 저장할 필요가 있다. HTML5 명세에는 브라우저가 지원하는 '웹 데이터 베이스'가 정의되어 있다.

❗동작과정❗

  1. 서버로 부터 받아온 html 문서를 렌더링 엔진이 parsing(해석)하여 dom 트리를 만든다.
  2. html parsing을 이어가다가 외부 스타일 파일을 로드하라는 link태그를 만나면(+스타일 태그,inline css) css 이를 중단하고 css파일을 로드하여 css parsing을 통해 csssom 트리를 만든다
  3. html parsing 도중에 스크립트 태그를 만나면 자바스크립트를 로드하고 실행(제어권이 렌더링 엔진에서 자바스크립트 런타임 환경으로 넘어간다.)하게 된다.이때 실행 되는 js는 dom과 cssom을 조작할 수 있음.
    3-1. +) 중간에 이미지 태그와 더불어 추가적인 리소스를 요청하는 태그를 만나면 html parsing을 중단하고 서버에 리소스를 요청한다.
  4. dom tree의 정보와 csssom tree의 정보가 합쳐서 render 트리가 만들어진다. render트리는 dom트리와 1:1로 대응하는 관계는 아니다. 예를 들어 "head" 요소와 같은 비시각적 DOM 요소는 렌더 트리에 추가되지 않는다. 또한 display 속성에 "none" 값이 할당된 요소는 트리에 나타나지 않는다.
  5. 렌더 트리를 기반으로 픽셀단위로 각 요소의 크기와 위치를 계산하는 "레이아웃 과정"(reflow) 이루어진다.
  6. 레이아웃 과정 후 이를 기반으로 사이즈와 크기를 제외한 css 속성(색,선,그림자 등)을 적용하는 paint 단계를 거쳐 화면에 문서가 출력된다.

렌더링 엔진은 좀 더 나은 사용자 경험을 위해 가능하면 빠르게 내용을 표시하는데 모든 HTML을 파싱할 때까지 기다리지 않고 배치와 그리기 과정을 시작한다. 네트워크로부터 나머지 내용이 전송되기를 기다리는 동시에 받은 내용의 일부를 먼저 화면에 표시하는 것이다.


DOM(document object model)

DOM은 html문서의 모든 요소를 노드 객체화 하여 트리 구조로 구성한 것이고,브라우저가 내부적으로 웹 페이지를 표현하는 방법일 뿐만 아니라 웹 개발자가 JavaScript를 통해 상호작용(DOM 조작)을 할 수 있는 데이터 구조이자 API이다.


위는 html 태그 구조이다. 이 태그는

  • p 요소 노드 (p 태그)
  • attribute 노드 (class="para" 부분)
  • 텍스트 노드 (TCPschool.com 부분)
    로 이루어져 있다. 그리고 텍스트 노드는 p노드의 자식 노그가 되고, attribute 노드는 p노드의 형제노드가 된다. 이런식으로 html 문서 전체를 parsing해 아래와 같은 dom 트리가 만들어 지는 것이다. 모든 자식노드는 부모의 속성을 상속 받는다.

    노드 종류
  • Document Node: dom 트리의 루트 노드. html 문서 당 document 노드는 유일하다.
  • Element Node : html 태그에 대응하는 노드
  • Attribute Node : html 태그 요소의 attribute를 가리키는 노드
  • Text Node : text 부분. 최하위 노드

Virtual DOM

우리가 사용하는 모던 웹서비스(ex.유튜브,당근 마켓 등등)들에서는 다양한 인터랙션들이 발생한다. 어떤 인터렉션("좋아요" 버튼 클릭, 댓글 달기, 장바구니 목록 담기 등)에 의해서 DOM에 변화가 발생하게 되면 Render Tree와 Layout을 재생성(reflow)하고 repaint 과정을 반복하게 된다. 따라서 dom 조작 횟수를 최소화시킬 필요가 있다.

Virtual DOM의 목적은 DOM 조작 횟수를 최소화하여 불필요한 리플로우(Reflow)와 리페인트(Repaint)를 방지하는 것이다.


Virtual DOM(DOM의 추상화 버전, dom 조작 api를 가지고 있지 않다.)은 원본 DOM을 복제한 가상의 DOM 구조를 생성하고, 변경 사항을 적용할 때마다 가상 DOM과 실제 DOM을 비교한다. 가상 DOM에서 변경 사항을 감지하면 해당 변경 사항만 실제 DOM에 반영한다. 이 과정에서 브라우저는 한 번만 렌더링을 하면 된다. 이렇게 하면 필요하지 않은 DOM 조작을 최소화하여 성능을 향상시킬 수 있다.
-> virtual dom에 변경 내역을 한번에 모으고(버퍼링) 실제 dom과 변경된 virtual dom의 차이를 판단한 후, 구성 요소의 변경부분만 찾아 dom fragment에 묶어 그에 따른 렌더링을 한번만 하게 됨.


CSS 렌더링 최적화

만약 CSS 규칙이 변경되면, 브라우저는 해당 요소들의 위치와 크기를 다시 계산해야 하며, 이 과정에서 reflow와 repaint가 발생할 수 있다. 그러나 reflow는 항상 일어나는 것이 아니기에 css 속성이 reflow와 repaint에 어떤 영향을 미치는지 알아둘 필요가 있다.


스크립트 태그 배치

1. 스크립트 태그를 제일 아래에 배치하는 이유

html 파싱은 위에서 부터 아래로 순차적으로 이루어는데 중간에 js를 만나 js를 실행하는 경우 이 js가 아직 만들어지지 않은 dom을 조작하려고 할 수 있는데 이때 예기치 못한 오류가 발생할 수 있다. 또 js 파일 실행이 오래걸리는경우 html css 파싱이 지체되어 화면가 콘텐츠표시 되지 않으면 좋지 않은 사용자경험을 유발 할 수 있다. 따라서 "특별한 설정"이 없는 자바스크립트 태그는 제일 밑에 두도록 한다.

2. async/defer attribute

혹은 스크립트를 제일 위에 두고 async or defer 옵션을 사용할 수 있다.

  • async : 자바스크립트 로드만 비동기로 실행하고 다운로드가 완료되면 js실행.(html 파싱 중단). 먼저 로드된 js 순서로 실행이 되므로 실행 순서 보장이 안된다.( 예기치 못한 오류가 발생)

  • defer : js 로드를 비동기로 하고 html이 모두 파싱 된후 마지막에 배치된 순서대로 js가 실행된다. 실행 순서가 순차적이기 때문에 보통 defer로 선언한다.


크로스 브라우징

필자는 지금까지 크롬브라우저와 사파리 기준으로 개발을 진행했었는데, 종종 같은 html css 코드인데, 사파리와 크롬에서 출력결과가 달랐다. 이 포스팅을 작성하면서 검색해보니 크롬은 Blink 렌더링 엔진을 사용하고 사파리는 Webkit 렌더링 엔진을 사용한다고 한다. 개인적으로 크롬이 좀 코드를 막(?) 적어도 의도한대로 잘 표현해 주었고 사파리는 조금 더 엄격하게 코드를 작성해야 의도한 대로 표현이 되었다.
결론적으로 각각의 렌더링 엔진의 차이로 인해 발생하는 크로스브라우징 이슈를 인지하고 여러 브라우저에서 테스트를 통해 더 나은 서비스를 만들 수 있도록 해야겠다. 그냥 브라우저들이 모두 좀 더 합심해서 통일성을 갖춰주면 좋겠다

참고
https://d2.naver.com/helloworld/5237120
https://legacy.reactjs.org/docs/faq-internals.html
https://velog.io/@suminllll/Reflow-RepaintNetwork

profile
일단 하는 중

0개의 댓글