Window load

박찬욱·2023년 5월 20일
0

Web APIs

목록 보기
5/12
post-thumbnail

🌐브라우저의 렌더링 과정

파싱과 렌더링

  • 파싱은 텍스트 문서를 읽어서 파스 트리 ( DOM tree, CSSOM tree ) 로 생성하는 과정을 의미한다.
  • 렌더링은 파싱된 것을 브라우저에 시각적으로 출력하는 것을 말한다.

브라우저는 다음과 같은 과정을 거쳐 렌더링을 수행한다.

  1. 브라우저는 HTML, CSS, JS, 이미지, 폰트 파일 등 렌더링에 필요한 리소스를 요청하고 서버로부터 응답을 받는다.
  2. 브라우저의 렌더링 엔진은 서버로부터 응답된 HTML, CSS를 파싱 하여 DOM treeCSSOM tree 를 생성하고 이들을 결합하여 Render tree 를 생성한다.
  3. 브라우저의 자바스크립트 엔진은 서버로부터 응답된 자바스크립트를 파싱 하여 AST (Abstract Syntax Tree) 를 생성하고 바이트코드로 변환하여 실행한다. 이때 자바스크립트는 DOM API 를 통해 DOM 이나 CSSOM 을 변경할 수 있다. 변경된 DOMCSSOM 은 다시 렌더 트리로 결합된다.
  4. Render tree 를 기반으로 HTML 요소의 레이아웃을 계산하고 브라우저 화면에 HTML 요소를 페인팅한다.

후에 이 과정과 관련된 자세한 내용을 포스팅하겠다.


자바스크립트 파싱에 의한 HTML 파싱 중단

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script src="main.js"></script>
  </head>
  <body>
  </body>
</html>

브라우저는 동기적으로, 즉 위에서 아래 방향으로 순차적으로 HTML, CSS, 자바스크립트를 파싱하고 실행한다. 이 때, HTML을 파싱하다가 CSS와 JS를 로드하는 코드를 만나면 HTML의 파싱이 중단되었다가 CSS와 JS가 파싱된 후에 다시 HTML 파싱을 이어간다.

위의 경우에는 main.js의 파싱과 실행 이전까지는 DOM의 생성이 일시 중단된다. DOM은 HTML이 모두 파싱되고 난 후에 생성되기 때문이다. 이때 자바스크립트 코드에서 DOM API를 이용해 DOM이나 CSSOM을 변경하는 경우에는 문제가 발생할 수 있다. DOM이나 CSSOM이 이미 생성되지 않은 상태에서 조작하려고 하기 때문이다.

✅ 해결책

이러한 문제를 회피하기 위해서는 body 요소의 가장 아래에 자바스크립트를 위치시키는 것은 좋은 아이디어다. 그 이유는 다음과 같다.

  • DOM이 완성되지 않은 상태에서 자바스크립트가 DOM을 조작하면 에러가 발생할 수 있음
  • 자바스크립트 로딩/파싱/실행으로 인해 HTML 요소들의 렌더링에 지장받는 일이 발생하지 않아 페이지 로딩 시간이 단축된다.

script 태그의 async/defer 어트리뷰트

해당 속성은 외부 자바스크립트 파일을 src 어트리뷰트를 통해 로드하는 경우에만 사용할 수 있다. 즉, 인라인 자바스크립트에는 사용할 수 없다.

asyncdefer 어트리뷰트를 사용하면 HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적 으로 동시에 진행된다. 하지만 자바스크립트의 실행 시점에 차이가 있다.

async 어트리뷰트

HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행된다. 단, 자바스크립트의 파싱과 실행은 자바스크립트 파일의 로드가 완료된 직후에 진행되며, 이때 HTML 파싱이 중단되고, 자바스크립트 실행이 완료되면 다시 진행된다.
순서 보장이 필요한 script 태그에서는 async 어트리뷰트를 지정하지 않아야한다. 왜냐하면 script 태그를 먼저 적던 나중에 적던 빨리 로드되는 자바스크립트부터 먼저 실행되기 때문에 순서가 보장되지 않는다.

<script async src='extern.js'></script>

👍 defer 어트리뷰트

async 어트리뷰트와 다른 점은 자바스크립트의 파싱과 실행이 HTML 파싱이 완료된 후, 즉 DOM 생성이 완료된 직후 (이때 DOMContentLoaded 이벤트가 발생한다.) 에 진행된다. 따라서 DOM 생성이 완료된 이후 실행되어야 할 자바스크립트에 유용하다.

<script defer src='extern.js'></script>

Window load의 대비밀

앞선 개념에서 DOMContentLoaded 이벤트가 잠깐 나왔다. 브라우저의 이벤트에는 DOMContentLoaded, load, beforeunload, unload 가 있다.

  • DOMContentLoaded

    • 앞서 설명한 것처럼 HTML 파싱이 완료된 직후, 즉 DOM tree 생성이 완료된 직후에 발생하는 이벤트이다.
  • load

    • HTML 뿐만 아니라 css, images 등 모든 리소스 자원들이 파싱이 완료된 후에 발생하는 이벤트이다.
  • beforeunload

    • 말 그대로 브라우저가 unload하기 직전에 발생하는 이벤트이다.
  • unload

    • 모든 리소스 자원들이 unload 되고 발생하는 이벤트이다.

해당 이벤트들은 브라우저가 로드되고 언로드될 때 실행하고 싶은 작업이 있으면 유용하게 사용할 수 있다.

  • 예시
window.addEventListener("DOMContentLoaded", () => {
		console.log("HTML 파싱이 완료되었습니다.");
});
profile
대체불가능한 사람이다

0개의 댓글

관련 채용 정보