
HTML이 렌더링 중에 스크립트를 만나면 어떻게 되는지 살펴보자
1) HTML을 파싱하여 DOM 트리 생성
2) CSS를 파싱하여 CSSOM 트리 생성
3) JavaScript를 파싱하여 AST 생성
4) 렌더 트리 생성
5) 레이아웃 및 페인트 진행
💥 결론부터 얘기하면 렌더링이 멈춘다!
CSS의 경우 DOM 트리를 변경하지 않기 때문에 문서 파싱을 기다리거나 중단하지 않는다.
반면에 JS에 경우 DOM 트리에 있는 요소에 접근하기 때문에 JS가 실행되면 렌더링을 멈추는 것이다.
HTML 렌더링 과정 중 <script> 태그를 만나면 진행중인 HTML 파싱을 중단하고 JS를 파싱하기 위해 JS 엔진으로 제어 권한이 넘어간다.
JS 파싱과 실행이 종료되면 제어 권한이 다시 렌더링 엔진으로 넘어가 중단된 시점부터 다시 파싱을 시작한다.
스크립트 파일을 먼저 로드하면 브라우저는 다른 작업을 할 수 없기 때문에 제대로 된 레이아웃이 구성되지 않은채 사용자 뷰를 제공하게 된다. 사용자 경험(UX)을 저하시킨다.
1) 스크립트 소스는 HTML <body> 끝에 둔다.
2) JS와 HTML 파싱을 비동기적으로 진행한다. (async & defer)
async와 defer은 모두 <script> 태그의 속성이다.
두 개 모두 HTML 파싱과 JS 파일 로드를 비동기적으로 동시에 진행한다.
async는 JS 실행은 로드되면 바로 진행되며 HTML 파싱이 중단된다.
async는 JS 파일의 로드는 동기적으로 진행될 수 있지만, 로드 완료 즉시 JS 파일이 실행되어 순서를 보장하지 않는다.
defer은 HTML 파싱이 완료된 후, DOM이 생성된 이후에 JS가 실행된다.
단, 외부 스크립트에만 유효하다.(src 필요!)