Skip to content

Commit

Permalink
📝 docs: 38-3장 브라우저의 렌더링 과정 38.7 ~ 38.9 정리
Browse files Browse the repository at this point in the history
  • Loading branch information
nincoding committed Jan 12, 2024
1 parent f668249 commit 3b9d718
Showing 1 changed file with 102 additions and 0 deletions.
102 changes: 102 additions & 0 deletions docs/38_브라우저의 렌더링 과정/한수지.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,105 @@ V8엔진의 경우 자주 사용되는 코드는 터보팬이라 불리는 컴
만약 코드의 사용 빈도가 적어지면 다시 디옵티마이징하기도 한다.

---

### 📌 38-7. 리플로우와 리페인트

자바스크립트 코드에 DOM API를 사용하면 DOM이나 CSSOM을 변경할 수 있다.

이때 **변경된 DOM과 CSSOM은 다시 렌더트리로 결합**되고 **변경된 렌더 트리를 기반으로 레이아웃과 페인트 과정**을 거쳐 **브라우저의 화면에 다시 렌더링**한다.

이를 **리플로우, 리페인트**라고 한다.

![](https://velog.velcdn.com/images/ninto_2/post/4a13beb5-32bb-4660-94fe-76ba911dcc68/image.png)

- `리플로우` : 레이아웃 계산을 다시 하는 것을 말한다.

- 노드 추가/삭제, 요소의 크기/위치 변경, 윈도우 리사이징 등 레이아웃에 영향을 주는 변경이 발생한 경우에 한하여 실행된다.

- `리페인트` : 재결합된 렌더 트리를 기반으로 다시 페인트를 하는 것을 말한다.

리플로우와 리페인트가 반드시 순차적으로 동시에 실행되는 것은 아니다.

레이아웃에 영향이 없는 변경은 리플로우 없이 리페인트만 실행되기 때문이다.

---

### 📌 38-8. 자바스크립트 파싱에 의한 HTML 파싱 중단

> **렌더링 엔진과 자바스크립트 엔진**은 병렬적으로 파싱을 실행하지 않고, **직렬적으로 파싱을 수행**한다.
▼ HTML 파싱과정에서 블로킹이 발생하는 코드

![](https://velog.velcdn.com/images/ninto_2/post/073f3825-7f5f-4727-9f83-3b3a81c0f457/image.png)

**브라우저는 동기적**으로,

**위에서 아래 방향으로 순차적**으로 **HTML, CSS, JS를 파싱하고 실행**한다.

이때, JS를 파싱하고 실행하는 `script 태그의 위치`에 따라 `HTML 파싱이 블로킹`되어 `DOM 생성이 지연`될 수 있기 때문에 주의가 필요하다.

🔎 **script 태그의 올바른 위치**

> `script 태그를 body 요소의 가장 아래`, 즉 `닫는 body 태그 바로 위에 위치`시켜야한다.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<!-- HTML 마크업 작성 -->

<!-- body 요소의 가장 아래 script 태그 작성 -->
<script src="app.js"></script>
</body>
</html>
```

이렇게 하면, JS가 실행될 시점에 이미 **렌더링 엔진이 HTML 요소를 모두 파싱하여 DOM 생성을 완료한 후**가 된다.

**DOM이 완성되지 않은 상태에서 JS가 DOM을 조작하는 에러가 발생할 우려가 없어짐**과 동시에, JS가 실행되기 이전에 DOM생성이 완료되어 렌더링되므로 **페이지 로딩 시간이 단축된다는 이점**도 있다.

---

### 📌 38-9. script 태그의 async/defer 어트리뷰트

> **DOM 생성이 중단되는 문제를 근본적으로 해결**하기 위해선, `script 태그에 async와 defer 어트리뷰트를 추가`해준다.
async와 defer 어트리뷰트는 `src 어트리뷰트를 통해 외부 JS 파일을 로드하는 경우에만 사용 가능`하다.
(src 어트리뷰트가 없는 인라인 JS에는 사용불가능)

```html
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script async src="ex1.js"></script>
<script defer src="ex1.js"></script>
</head>
```

async와 defer 어트리뷰트를 사용하면 **HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행**된다.

하지만 이 둘은 자바스크립트의 실행 시점에 차이가 있다.

🔎 **async 어트리뷰트**

![](https://velog.velcdn.com/images/ninto_2/post/b19ede45-e371-4499-b2c7-625cef990551/image.png)

async 어트리뷰트를 사용한 경우, 자바스크립트의 파싱과 실행은 `자바스크립트 파일의 로드가 완료된 직후 진행`되며, 이때 HTML 파싱이 중단된다.

async 어트리뷰트를 script 태그에 지정하면 **태그의 순서와는 상관없이 로드가 완료**된다.

따라서, `순서 보장이 필요한 경우 async 어트리뷰트를 지정하지 않아야`한다.

🔎 **defer 어트리뷰트**

![](https://velog.velcdn.com/images/ninto_2/post/50280bac-0610-4f97-96a6-5c6e7bbd5557/image.png)

defer 어트리뷰트를 사용한 경우, 자바스크립트 파싱과 실행은 `HTML 파싱이 완료된 직후, 즉 DOM 생성이 완료된 직후(이때 DOMContentLoaded 이벤트 발생) 진행`된다.

따라서, `DOM 생성이 완료된 이후 실행되어야 할 자바스크립트 유용`하다.

0 comments on commit 3b9d718

Please sign in to comment.