\(@^0^@)/
[JS] 스크립트 defer, async 본문
브라우저는 HTML을 읽다가 내부, 외부 script 태그를 만나면 스크립트를 먼저 실행해야 하므로 내부의 DOM 작동을 멈추고, 외부는 스크립트를 다운받은 후 남은 페이지를 처리 함.
그래서, 이러한 동작 방식의 단점은
1. 스크립트에서는 스크립트 아래에 있는 DOM 요소에 접근 할 수 없으므로, DOM요소에 핸들러를 추가하는 등의 행위가 불가능 해짐.
2. 페이지 위쪽에 용량이 큰 스크립트가 있을 경우, 그 큰 스크립트를 다운받고 실행될 때 까지 스크립트 아래쪽을 볼 수 없음.
이러한 문제의 해결방안은
1. body 태그의 맨밑에 script 태그를 놓으면, 스크립트 위에 있는 요소들에 접근이 가능해짐.
하지만, HTML 문서 자체 용량이 클 경우, 브라우저가 HTML문서 전체를 다운로드 한 다음에 스크립트를 다운받게 하면 페이지가 정말 느려짐. (그러므로, 완벽한 해결책은 아님)
2. async : 속성이 붙은 스크립트는 페이지와 완전히 독립적으로 동작 (비동기 스크립트 또는 async 스크립트 라고 불림)
- 백그라운드에서 다운로드 됨. 따라서, HTML 페이지는 async 스크립트 다운이 완료되는 것을 기다리지 않고,
페이지 내의 콘텐츠를 처리하고 출력함. (하지만, async 스크립트 실행 중에는 HTML 파싱을 멈춤) - 페이지 구성이 끝난 후에 async 스크립트 다운로딩이 끝난 경우, DOMContentLoaded는 async 스크립트 실행 전에 발생할 수 있음 ( 페이지 구성이 끝나기 전에 다운로드 된 경우엔, DOMContentLoaded가 async 스크립트 실행 후에 발생할 수도 있음)
- 다른 스크립트들은 async 스크립트를 기다리지 않고, async 스크립트 또한 다른 스크립트 들을 기다리지 않음.
이러한 특징들 때문에, 페이지에 async 스크립트가 여러개 있을 경우 실행 순서가 제각각이 되고, 실행은 다운로드가 끝난 스크립트 순으로 진행 됨.
3. defer : 속성이 있는 스크립트를 백그라운드에서 다운로드 (지연스크립트 또는 defer 스크립트 라고 불림)
따라서, defer 스크립트를 다운로드 하는 도중에도 HTML 파싱이 멈추지 않음.
그리고, defer 스크립트 실행은 페이지 구성이 끝날 때까지 지연 됨.
- defer 스크립트는 페이지 생성을 절대 막지 않는다.
- defer 스크립트는 DOM트리가 완성된 후 실행되지만, DOMContentLoaded 이벤트 발생 전에 실행 됨.
- defer 스크립트는 일반 스크립트와 마찬가지로 HTML에 추가된 순(상대순, 요소순)으로 실행 됨.
- defer 속성은 외부 스크립트에만 유효함. <script>에 src가 없으면 defer 속성은 무시 됨.
- 스크립트가 실행되기 전에 페이지가 화면에 출력되므로, 사용자는 그래픽 관련 컴포넌트들이 준비되지 않은 상태에서 화면을 보게 될 수 있음. 따라서, '로딩 인디케이터'가 있어야 함.
4. Dynamic : 동적 스크립트는 기본적으로 'async' 스크립트처럼 행동함 ( 동적 스크립트 또는 dynamic 스크립트 라고 불림)
- 동적 스크립트는 그 어떤 것도 기다리지 않고, 그 어떤 것도 동적 스크립트를 기다리지 않음.
- 먼저 다운로드 된 스크립트가 먼저 실행 (load-first-order)
- script.async=false 를 추가하면, 문서에 추가된 순서대로 실행 됨.
-
function loadScript(src) { let script = document.createElement('script'); script.src = src; script.async = false; document.body.append(script); } // async=false이기 때문에 long.js가 먼저 실행됨. // async=false가 없었다면, 크기가 작은 small.js가 먼저 실행 됨. loadScript("/article/script-async-defer/long.js"); loadScript("/article/script-async-defer/small.js");
공통점 : async와 defer 스크립트는 다운로드 시 페이지 렌더링을 막지 않는다 ( 베스트 : async 와 defer를 적절히 사용 )
차이점 :
순서 | DOMContentLoaded | |
async | load-first order. 문서 내 순서와 상관없이 먼저 다운로드된 스크립트가 먼저 실행 됨. | 비동기 스크립트는 HTML 문서가 완전히 다운로드되지 않은 상태라도 로드 및 실행될 수 있음. 스크립트 크기가 작거나 캐싱 처리 되어있을 때 혹은 HTML 문서 길이가 아주 길 때 발생. |
defer | 문서에 추가된 순 | 지연 스크립트는 문서 다운로드와 파싱이 완료된 후에, DOMContentLoaded 이벤트 발생 전에 실행 됨. |
※ 참고 : https://ko.javascript.info/script-async-defer
'TIL' 카테고리의 다른 글
[JS] PadStart(), PadEnd() (0) | 2021.09.29 |
---|---|
[JS] 좌표 CSS, JS / client, page (0) | 2021.09.22 |
[JS] Number 와 parseInt의 차이점 (0) | 2021.09.11 |
[JS] JS 동작원리 (stack, Queue, event loop) (0) | 2021.09.08 |
jQuery 쌩기초 (0) | 2021.09.08 |