본 포스팅은 저자 이웅모님의 '모던 자바스크립트 deep dive를 참고하였습니다.
🐬렌더링이란?
브라우저가 html, css, 자바스크립트로 작성된 텍스트 문서를 브라우저에 시각적으로 출력하는 것.
구글에 렌더링에 대해서 찾아보면 다양한 그림들이 나온다.
🐣렌더링 수행과정
1. 주소창에 www.goole.com 입력 -> dns가 실제 서버를 찾아준다.
2. html, css, 자바스크립트, 이미지, 폰트 등 렌더링에 필요한 리소스를 서버에 요청하면 응답을 받는다.
2. 브라우저의 렌더링 엔진이 응답받은 html, css를 파싱하여 DOM과 CSSOM 생성하고 결합, 렌더 트리 생성.
3. 브라우저의 자바스크립트 엔진이 응답받은 자바스크립트를 파싱, 이 때 자바스크립트가 DOM API를 통해 DOM이나 CSSOM을 변경할 수 있음. 변경되면 다시 렌더트리로 결합됨.
4. 렌더 트리를 기반으로 HTML 요소 레이아웃을 계산, 브라우저 화면에 HTML 요소 페인팅.
1. 요청? 응답?
브라우저 주소창에 주소를 입력하여 엔터를 누른다 = 요청!
우리가 보낸 URL의 호스트 이름 (www.주소.com) 이 DNS 를 통해 IP 주소로 변환되고 해당 IP 주소를 갖고 있는 서버에게 요청을 전송한다.
서버에서는 암묵적인 룰로 index.html(정적페이지) 을 응답시킨다.
만약 다른 정적 파일, 예를 들어 json을 요청하려면 해당 파일의 경로와 파일이름을 통해 서버에 요청하면 응답시킨다!
(이부분이 바로 path)
주소를 간단히 뜯어보면 다음과 같다.
http://www.app.com:80/src/data/data.json
🔴HOST 🟢PORT 🔵PATH
그럼 정적 파일만 요청, 응답하는가? 자바스크립트는 동적으로 서버에 데이터를 요청할 수 있다!
내가 무슨 요청과 응답을 받았는지 보고 싶으면 개발자 도구의 network 패널을 적극 활용하도록 하자.
network 패널을 켜놓고 페이지를 새로고침 해보면 확인할 수 있다.
그런데, 확인해보면 index.html 뿐만 아니라 css, 자바스크립트, 이미지, 폰트 파일 까지 응답된다는 것을 알 수 있다.
브라우저의 렌더링 엔진은 link, img, script 태그 등을 만나면 html 파일 파싱을 멈추고, 알아서 리소스 파일을 서버로 요청하기 때문.
2. dom
브라우저는 html과 css등의 리소스를 요청받고나서, 파싱한다. 이들은 텍스트의 구조를 가지기 때문에 브라우저가 자기가 알아들을 수 있게 자료구조인 객체로 변환하여 메모리에 저장한 것이 DOM이다. ( 뜻은 document object model)
다음은 자세한 과정들.
1. HTML은 바이트 형태에서 문자열로 변환됨.
2. 문자열인 HTML 문서를 읽어 들임. 그리고 토큰들로 분해 (문법적 의미를 갖는 코드의 최소 단위)
3. 토큰들을 객체로 변환. 노드들을 생성한다.
4. HTML 태그들은 중첩관계를 가진다. 부자 관계 (부모태그, 자식태그) 를 갖는다. 이 관계들을 반영하여 노드들을 트리 자료 구조로 구성한다. 이 트리 자료 구조가 = DOM
어려운 말 보다, DOM이 HTML 태그들을 파싱하여 나온 결과물들이라고 생각하면 된다.
이제껏 우리가 작성한 HTML 파일들은 전부 저런 트리 구조의 DOM을 가지고 있었다는 것.
3. CSSOM
브라우저는 html 파일을 맨 윗줄부터 순서대로 파싱하는데, DOM을 생성하다가 CSS를 불러오는 link 태그나 style 태그를 만나면 DOM 생성을 일시 중단하게 된다.
그리고 link 태그의 href에 지정된 위치에 css 파일을 요청하여 HTML 처럼 파싱과정을 거쳐 CSSOM을 생성한다.
(CSS Object Model)
이 css 파싱이 완료되면 html 파싱으로 돌아가서 DOM 생성으로 복귀.
4. 렌더 트리
이제 렌더링 엔진은, 위에서 얘기한 DOM + CSSOM을 렌더 트리로 결합시킨다.
렌더 트리는 말그대로 렌더링을 위한 트리 자료 구조이다. 그래서 오직 렌더링 할 노트들만 포함된다
렌더링 안할 태그는 포함할 필요가 없다
이 렌더링 과정들은 여러번 실행될 수 있는데, 재 실행되는 만큼 성능에 영향을 주게 된다.
👉재 렌더링 될 수 있는 예시들
자바스크립트에 의한 노드 추가 또는 삭제
브라우저 창의 리사이징에 의한 뷰포트 크기 변경
HTML 요소의 레이아웃(위치, 크기)에 변경을 발생시키는 것들(width,margin,padding,border,display,position 등)
🤷♀️이러한 사항들을 알고있다면 브라우저 성능을 최적화 하는 데 활용할 수 있을 것이다. (좋은 코드!)
5. 자바스크립트 파싱과 실행
우리가 자바스크립트를 사용하는 이유를 간단하게 얘기해보자면, 브라우저의 렌더링 산출물인 DOM을 활용하여 DOM을 동적으로 조작하기 위해서이다. 한마디로 인터렉티브한 웹페이지를 만들 수 있다.
언급했듯이, 렌더링 엔진은 script 태그를 만나면 렌더링을 일시정지하고, 자바스크립트 엔진이 작동된다.
자바스크립트 엔진이 자바스크립트를 파싱하고, AST라는 걸 생성하고, AST를 기반으로 바이트 코드를 생성하여 실행한다. 파싱이 완료되면 다시 중단 지점부터 렌더링 엔진이 작동되고 HTML 파싱 -> DOM 생성을 하게 된다.
(AST= abstract syntax tree, 추상적 구문 트리)
자바스크립트 엔진은 코드를 파싱하여 컴퓨터가 알아들을 수 있는 언어로 변환하고 실행해준다.
예를 들어 크롬은 그 유명한 Node.js의 V8 엔진을 사용한다.
그럼 우리가 자바스크립트에서 DOM API를 활용하여 script 코드를 실행했다고 하자. 이 때 DOM과 CSSOM이 변경되고 변경된 것들이 다시 렌더 트리로 결합된다. 렌더트리는 레이아웃, 페인트 과정을 거쳐 브라우저의 화면에 다시 렌더링한다. (리플로우, 리페인트)
🔹리플로우
레이아웃 계산을 다시 하는 것, 노드 추가/삭제, 요소 크기/ 위치변경 등 레이아웃에 영향을 주는 변경이 있을 때 실행
🔹레이아웃
뷰포트 내에서 노드들의 위치와 크기를 계산하는 동작, 화면에 어떤 위치? 어떤 크기? 로 표시될지 계산
🔸리페인트
리플로우 유무와 상관없이, 재결합된 렌더 트리를 다시 페인트 하는 것,
레이아웃 변경이 없는 실행은 리페인트만 실행함.
(예시로는 visibility: hidden, color 변경)
마지막으로, script 태그의 파싱은 HTML 태그의 렌더링을 중단시키고 작동되기 때문에 script의 위치에 따라 DOM 생성이 지연될 수 있다는 것을 의미한다.
만약 DOM 생성이 완료되지 않은 상태에서 자바스크립트가 DOM을 조작하면 에러가 발생할 수 있다.
그래서 우리는 HTML 문서 내에서 script 태그의 위치를 가장 아래로 놓는 것이 좋다.
🤖더 알아보면 좋은것들!
✔️async/defer 어트리뷰트
✔️브라우저 렌더링과 최적화
'공부 > http' 카테고리의 다른 글
[aws] ec2, mongo db + react 프로젝트 배포하기 (0) | 2022.05.17 |
---|