https://www.youtube.com/watch?v=BWprng2Jpvc
- 브라우저의 주요 기능은 사용자가 자원을 서버에 요청하고 요청한 자원을 브라우저에 표시하는 것입니다.
- 웹 브라우저에 URL을 입력하면 웹 서버라 불리는 프로그램이 웹 브라우저에 웹 페이지를 제공합니다.
웹 브라우저가 웹서버에 웹 페이지를 달라고 하는것 : 요청(request)
요청한 웹 페이지를 웹 브라우저에 제공하는 것 : 응답(response)
- 보통 웹 브라우저와 웹 서버는 다른 컴퓨터에 위치합니다.
- 웹 서버가 다른 컴퓨터에서 실행되고 있기 때문에, 웹 브라우저가 웹 서버에 연결하려면, 웹 서버가 실행중인 컴퓨터의 주소를 알아야 하는데, 이 주소를 IP 주소라 합니다.
- 각 컴퓨터는 IP주소를 가지고 있습니다.
- 그런데 IP주소는 192.168.0.1 과 같은 숫자들로 구성되어 있어서 외우기 쉽지 않습니다.
- 이런 이유로 IP 주소 대신에 "velog.io/@thyoondev"과 같이 사람이 기억하기 좋은 도메인 이름을 사용합니다.
- 웹 브라우저와 웹 서버는 IP 주소를 이용하여 연결하기 때문에 도메인 이름을 IP 주소로 변환할 필요가 있는데, 이 때 사용하는 것이 바로 **DNS(Domain Name Server)**입니다.
- 웹 브라우저에서 URL을 입력하면, 웹 브라우저는 도메인 이름에 해당하는 IP 주소를 DNS에 요청하고, DNS는 IP주소를 응답으로 제공한다.
- DNS로 부터 IP 주소를 받으면, 웹 브라우저는 3번 과정처럼 IP 주소를 이용해서 웹 서버에 연결한 뒤 URL에 해당하는 웹 페이지를 요청하고, 웹 페이즈를 응답받게 됩니다.
- 일반적으로 네트워크 프로그램에서 요청하는 쪽을 클라이언트(Client)라고 부르고, 요청을 받아 알맞은 기능이나 데이터를 제공하는 쪽을 서버(Server)라고 부릅니다.
- 브라우저의 주요 기능은 사용자가 선택한 자원을 서버에 요청하고 브라우저에 표시하는 것입니다.
- 브라우저의 사용자 인터페이스는 다음과 같은 요소들이 일반적입니다.
- URI를 입력할 수 있는 주소 표시 줄
- 이전 버튼과 다음 버튼
- 북마크
- 새로 고침 버튼과 현재 문서의 로드를 중단할 수 있는 정지 버튼
- 홈 버튼
- 먼저 브라우저의 구성 요소를 그림으로 보면
- 각 구성 요소는 다음과 같은 역할을 하고 있습니다.
- 물론 구조는 브라우저마다 조금씩 다를 수 있습니다.
- 사용자 인터페이스: 주소 표시줄, 이전/다음 버튼, 북마크 등 페이지 뷰 이외의 다른 부분
- 브라우저 엔진: 사용자 인터페이스와 렌더링 엔진 사이 동작을 제어
- 렌더링 엔진: HTML, CSS를 파싱해 화면에 요청한 컨텐츠를 표시
- 통 신: HTTP요청과 같은 네트워크 호출에 사용됨
- JS 엔진: 자바스크립트 코드를 해석하고 실행
- UI 백엔드: 기본적인 위젯(콤보 박스 등)을 그림
- 자료 저장소: 자료를 저장하는 계층으로 쿠키 등을 저장하는 웹 데이터베이스
- 크롬은 대부분의 브라우저와 달리 각 탭마다 별도의 렌더링 엔진 인스턴스를 유지하는 것이 주목할만합니다.
- 각 탭은 독립된 프로세스로 처리됩니다.
- 렌더링 엔진은 위에서 설명한 것처럼 요청받은 내용을 브라우저 화면에 표시해주는 역할을 합니다.
- 브라우저마다 사용하는 렌더링 엔진이 각각 다르기 때문에, 모든 브라우저가 동일한 소스를 화면에 동일하게 그려주지 않고 엔진마다 읽을 수 있는 코드의 버전도 다르기 때문에 크로스 브라우징 이슈가 발생하곤 합니다.
- 파이어폭스는 게코(Gecko), 사파리는 웹킷(Webkit), 크롬의 경우 웹킷을 사용하다가 웹킷을 Fork하여 블링크 엔진을 자체적으로 구현하여 사용합니다.
- 각각의 렌더링 엔진들은 웹 표준에 따라서 개발자들이 작성한 문서를 브라우저에 보여주지만, 개발 진척도나 별도 규칙에 따라 지원하는 표준이 다르거나 렌더링 알고리즘과 방식에 차이가 있을 수 있습니다.
- 다음은 렌더링 엔진의 기본적인 동작 과정입니다.
- 그러면 이 과정에 대해 웹킷 엔진을 기준으로 좀 더 자세하게 알아보겠습니다.
- DOM(Document Object Model), CSSOM(CSS Object Model) 생성 (Parsing)
- HTML을 파싱하여 DOM 노드를 만듭니다.
- 이 DOM 노드들을 병합하여 DOM 트리를 만듭니다.
- CSS를 파싱하여, CSSOM(CSS Object Model) 트리를 만들게 됩니다.
- 브라우저는 렌더링 할 문서를 HTML과 CSS로 나눠서 읽게 됩니다.
- 이때 HTML과 CSS는 단순한 텍스트이므로 각각 연산과 관리가 가능하도록 HTML Parser와 CSS Parser를 사용해 관리가 가능한 Object Model로 만듭니다.
- 일련의 과정들이 점진적으로 진행된다는 것을 아는 것이 중요합니다.
- 렌더링 엔진은 좀 더 나은 사용자 경험을 위해 가능하면 빠르게 내용을 표시하는데 모든 HTML을 파싱할 때까지 기다리지 않고 배치와 그리기 과정을 시작합니다.
- 네트워크로부터 나머지 내용이 전송되기를 기다리는 동시에 받은 내용의 일부를 먼저 화면에 표시하는 것입니다.
- HTML 파싱과 DOM 생성 과정
- 서버는 브라우저로부터 요청받은 HTML 파일을 읽어드린후 > 메모리에 저장하고 > 그 메모리에 저장된 바이트(101101000100…)을 응답합니다.
- 브라우저는 응답받은 바이트 형태의 문서를 meta태그의 charset 어트리뷰트에 지정된 인코딩방식(UTF-8)에 따라 문자열로 반환합니다.
- 문자열로 변환된 HTML문서를 이번에는 문법적 의미를 갖는 코드의 최소 단위인 토큰(token)으로 분해합니다.
- 토큰들의 내용에 따라 객체로 변환하여 각 노드들을 생성합니다. (문서 노드, 요소 노드, 어트리뷰트 노드, 텍스트 노드)
- HTML은 요소 간의 부자 관계인 중첩 관계를 갖는데, 이를 반영하여 모든 노드들을 트리 구조로 구성하여 DOM을 만듭니다.
- CSS파싱과 CSSOM 생성 과정
- 렌더링 엔진은 HTML문서를 한줄 한줄 순차적으로 파싱하며 DOM을 생성합니다.
- 그러다 CSS를 로드하는 link태그 혹은 style태그를 만나면 DOM생성을 중지한 후 CSS파싱의 결과물인 CSSOM을 생성하는 과정을 진행합니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"> // 여기까지 해석 후,
<link rel="stylesheet" href="style.css">
//link를 만나면 DOM생성을 중지하고 CSS파일을 서버에 요청한 후 응답받아 CSS파싱을 시작한다.
...
- CSS파싱 과정은 바이트 > 문자 > 토큰 > 노드 > CSSOM 생성 순으로 HTML의 파싱과정과 동일합니다.
- 자바스크립트 파싱 과정
- 렌더링 엔진은 HTML 문서를 한 줄씩 순차적으로 파싱하다가 자바스크립트 파일을 로드하는 script 태그를 만나면 DOM 생성을 일시 중단합니다.
- script 태그의 src에 정의된 자바스크립트 파일을 서버에 요청하여 응답받으면 자바스크립트 코드를 파싱하기 위해 자바스크립트 엔진에게 제어권을 넘깁니다.
- 자바스크립트 파싱이 끝나면 렌더링 엔진으로 다시 제어권을 넘기고 DOM 생성을 이어나갑니다.
- 만약 생성되지 않은 DOM을 조작한다면 에러가 발생할 수 있습니다.
- 따라서 body 요소 아래에 자바스크립트를 위치 시키거나 DOM 생성이 완료된 시점에 자바스크립트가 실행되도록 합니다.
- 자바스크립트 코드를 토크나이저가 어휘 분석하여 문법적 의미를 갖는 코드의 최소 단위인 토큰들로 분해하는데 이것을 토큰나이징이라 합니다.
- 파서가 토큰들을 구문분석하여 AST(Abstract Syntax Tree : 추상 구문 트리)로 파싱합니다.
- 바이트 코드 생성기가 AST를 바이트코드로 변환합니다.
- 인터프리터에 의해 바이트코드를 실행합니다.
- 렌더 트리 구축 (Attachment)
- CSSOM 트리와 DOM 트리를 결합하여, 표시해야 할 순서로 내용을 그려낼 수 있도록 하기 위해렌더 트리를 형성합니다.
- 이 과정을 Attachment라고 합니다.
- 렌더 트리는 화면에 표시되는 각 노드의 위치를 계산하는 레이아웃에 사용되고 픽셀을 화면에 그리는 페인트 과정에도 사용됩니다.
- DOM과 CSSOM을 결합하여 렌더트리 생성
- 렌더 트리를 생성하려면 브라우저는 대략 3가지 작업을 수행합니다.
- DOM 트리의 루트부터 노드 각각을 모두 탐색합니다.
- 이 때 화면에 표시되지 않는 일부 노드들(script, meta 태그 등..)은 렌더 트리에서 제외됩니다.
- 또한 CSS 속성 중 display:none 같이 화면에서 숨겨지는 속성도 렌더 트리에 반영되지 않습니다.
- 화면에 표시되는 각 노드에 대해 적절하게 일치하는 CSSOM 규칙을 찾아 적용합니다.
- 화면에 표시되는 노드들은 콘텐츠 및 계산된 스타일과 함께 렌더트리로 생성됩니다.
렌더 트리 배치 (Layout or Reflow)
- 렌더 트리가 생성되고, 기기의 뷰포트 내에서 렌더 트리의 노드가 정확한 위치와 크기를 계산합니다.
- 이때 모든 상대적인 값이 픽셀값으로 변환됩니다.
- CSS에 상대적인 값인 %,rem,vh으로 할당된 값들은 절대적인 값인 px단위로 변환 됩니다.
- 이 과정을 배치(Layout) 또는 Reflow라고 합니다.
렌더 트리 그리기 (Paint)
- 렌더 트리의 각 노드를 화면의 실제 픽셀로 나타낼 때 Painting메서드가 호출됩니다.
- Painting 과정 후 브라우저 화면에 UI가 나타나게 됩니다.
그리기 순서
- 실제로 요소가 stacking contexts에 쌓이는 순서는 아래와 같습니다.
- 스택은 뒤에서 앞으로 그려지기 때문에 이 순서는 Painting에 영향을 미칩니다.
- 블록 렌더러가 쌓이는 순서는 다음과 같습니다.
- 배경 색
- 배경 이미지
- 테두리
- 자식
- 아웃라인
- 페인트 단계에서 메인 스레드는 페인트 기록(paint record)을 생성하기 위해 레이아웃 트리를 순회합니다.
- 페인트 기록은 '배경 먼저, 다음은 텍스트, 그리고 직사각형'과 같이 페인팅 과정을 기록한 것입니다.
- JavaScript로 canvas 요소에 그림을 그려 봤다면 이 과정이 익숙할 것입니다.
동적 변경
- 브라우저는 변경에 대해 가능한 한 최소한의 동작으로 반응하려고 노력합니다.
- 예를 들어 div요소 한 개의 색깔이 바뀌면 해당 요소의 리페인팅만 발생합니다.
- 요소의 위치가 바뀌면 요소와 자식 그리고 형제의 리페인팅과 재배치가 발생합니다.
- DOM 노드를 추가하면 노드의 리페인팅과 재 배치가 발생합니다.
- html 요소의 글꼴 크기를 변경하는 것과 같은 큰 변경은 캐시를 무효화하고 트리 전체의 배치(Layout)와 리페인팅이 발생합니다.
Reflow와 Repaint
- 렌더링 과정을 모두 마친 후 최종적으로 브라우저에 페이지가 그려집니다.
- 하지만 특정 액션이나 이벤트에 따라 HTML요소의 크기나 위치 등의 레이아웃 수치가 변하면 해당 요소의 영향을 받는 자식 노드나 부모 노드들을 포함하여 Layout(Reflow)과정을 다시 수행하게 됩니다.
- 이럴경우 각 요소들의 크기와 위치를 다시 계산하게 되는데 이 과정을 Reflow, 그리고 Reflow 된 렌더 트리를 다시 화면에 그려주는 과정을 Repaint라고 합니다.
- Repaint(Redraw)는 화면에 변화가 있을 때 화면을 그리는 과정.
- Reflow(Layout)는 뷰포트 내에서 렌더 트리의 노드의 정확한 위치와 크기를 계산하는 과정.
- Repaint가 발생하는 경우는 화면이 변경되는 모든 경우.
- Reflow가 발생하는 경우는 화면의 구조가 바뀌었을 경우.
Repaint
- 화면의 구조가 변경되었을 때에는 Reflow 과정을 거쳐 화면 구조를 다시 계산한 후 Repaint 과정을 통해 화면을 다시 그립니다.
- 즉 화면의 구조가 변경되었을 때에는 Reflow와 Repaint 모두 발생합니다.
- 화면의 구조가 변경되지 않는 화면 변화의 경우 Repaint만 발생합니다.
- 예를 들면 opacity, background-color, visibility, outline 등의 스타일 변경 시에는 Repaint만 동작합니다.
Reflow
- 위에서 말한 것처럼 렌더 트리와 각 요소들의 크기와 위치를 다시 계산해주는 과정을 Reflow라고 합니다.
- Reflow가 일어나는 대표적인 경우는 다음과 같습니다.
- DOM 노드의 추가, 제거
- DOM 노드의 위치 변경
- DOM 노드의 크기 변경(margin, padding, border, width, height 등..)
- CSS3 애니메이션과 트랜지션
- 폰트 변경, 텍스트 내용 변경
- 이미지 크기 변경
- offset, scrollTop, scrollLeft과 같은 계산된 스타일 정보 요청
- 페이지 초기 렌더링
- 윈도우 리사이징
- 이외에도 화면의 구조가 변경되었다면 Reflow가 발생한다고 이해하면 됩니다.
- 웹 브라우저의 통신과정부터 브라우저의 동작원리까지 알아보았습니다.
- 브라우저가 더 렌더링을 빠르고 효율적으로 할 수 있게 개발하기 위해서는 Reflow과정을 최소화 시키는 것이 좋습니다.
- Reflow가 발생하면 Repaint가 일어나기 때문에 렌더링 최적화에 좋지 않은 영향을 줍니다.
- 따라서 Reflow를 최소화 하는 고민을 하면서 프론트개발을 한다면 웹 브라우저의 렌더링 과정을 조금 더 최적화 할 수 있습니다.
참고사이트
'Question' 카테고리의 다른 글
이력서관련 질문 리스트 (1) | 2022.10.24 |
---|---|
상태란 무엇이고 왜 상태관리를 할까요? (0) | 2022.10.23 |
DOM과 virtualDOM의 차이 (0) | 2022.10.22 |
react를 사용하는 이유 (0) | 2022.10.21 |