defer
, async
스크립트란?
script
태그에 추가될 수 있는 속성이다.- HTML 코드를 보면,
<script defer src="a.js"></script>
혹은<script async src="a.js"></script>
와 같은 구문을 볼 수 있다.
- HTML 코드를 보면,
- 역사를 알면, 이러한 속성 값들이 왜 생겼는지 알 수 있다. 역사를 살펴보며 천천히 배워보자.
script
태그의 특징
- 초기의 브라우저 자바스크립트는 아주 짧고 간단한 스크립트 코드를 넣기 위해 존재했다. 그런데 동적인 웹의 발달로 자바스크립트 코드는 아주 길게 변했다.
- 브라우저는 DOM 을 생성하다가도
script
태그를 만나면,script
태그의 내용부터 해석하는 방식으로 동작했다.
script
태그의 특징 때문에 생긴 문제
- 초기에 의도한대로
head
태그에 자바스크립트 코드를 몰아넣으니 DOM 을 생성하기도 전에 자바스크립트를 해석하느라 페이지 로딩 속도가 매우 느려지는 현상이 일어났다. - 자바스크립트 코드에서
head
아래에 있는 DOM 요소를 제어하는 행위도 타이밍이 맞지 않아서 불가능해졌다.
임시방편 해결책: body
태그 끝에 script
를 위치시키기
<html>
<head>
<!-- CSS, 메타정보, 타이틀 등 -->
</head>
<body>
<!-- DOM 요소 -->
<script></script>
</body>
</html>
- 더이상 DOM 로드를 막지 않는다.
- 다만 여전히 아주 큰 HTML 페이지에 대해서는 많은 지연이 발생한다.
- 특히 상대적으로 통신이 느린 모바일 환경에서 더 부각될 것이다.
defer
의 등장
script
태그에defer
속성을 붙이면 백그라운드에서 스크립트를 다운받는다.- 백그라운드에서 돌기 때문에 스크립트 다운로드 중에도 HTML 파싱이 멈추지 않는다.
- 페이지 컨텐츠는 즉시 출력된다.
defer
속성이 추가된 스크립트는 DOM 이 준비된 이후에 실행된다.- 하지만
DOMContnetLoaded
이벤트가 발생되기 전에 실행된다.
- 하지만
<html>
<head>
<!-- CSS, 메타정보, 타이틀 등 -->
<script defer src="a.js"></script>
<script>
document.addEventListener("DOMContentLoaded", () =>
console.log("`defer` 스크립트가 실행된 후 실행된다.")
);
</script>
</head>
<body>
<!-- DOM 요소 -->
</body>
</html>
defer
의 특징
- 작은 스크립트가 먼저 다운로드 될 수 있지만, 실행은 순서대로 된다.
- 스크립트는 병렬적으로 다운로드 되기 때문에 작은 스크립트가 먼저 다운로드 완료될 수 있다.
- 다만, 스크립트 실행 순서는 문서에 추가된대로 되어야 한다고 정의되어 있기 때문에 실행은 추가된 순서대로 실행된다.
defer
가 동작하지 않는 경우
- 인라인 스크립트로 이루어진 경우,
defer
가 동작하지 않는다.
<script defer>
document.getElementById("hello").innerHTML = "HELLO!";
</script>
async
의 등장
defer
와 마찬가지로 백그라운드에서 다운로드된다.async
는 완벽히 독립적으로 동작한다.DOMContentLoaded
전, 후 아무 때나 실행될 수 있다.- 스크립트들 끼리도 실행 순서가 보장되지 않는다.
async
실행 중에는 HTML 파싱이 멈추게 된다.
<html>
<head>
<!-- CSS, 메타정보, 타이틀 등 -->
<script async src="a.js"></script>
<script>
document.addEventListener("DOMContentLoaded", () =>
console.log("실행 순서가 보장되지 않는다.")
);
</script>
</head>
<body>
<!-- DOM 요소 -->
</body>
</html>
async
의 특징
- 실행 순서의 보장 없이 먼저 로드된 것이 먼저 실행된다.
- 이를
load-first order
라고 한다.
- 이를
- DOM 에 전혀 영향을 받지 않는 서드파티 스크립트를 삽입할 때 아주 유용하다.
google analytics
같은 것이 좋은 예다.
동적 자바스크립트
- 약간 괴기한 문법이 있다.
- 보통
async
와 동일한 특징을 갖는다.load-first order
를 갖는다.
let script = document.createElement("script");
script.src = "/a.js";
document.body.append(script);
async = false
script.async = false
로 설정해주면, 추가한 순서대로 실행된다.a.js
후에b.js
가 실행될 것이다.
function loadJS(src) {
let script = document.createElement("script");
script.src = src;
script.async = false;
document.body.append(script);
}
loadJS("/a.js");
loadJS("/b.js");
async
와 defer
비교
async
- 백그라운드에서 다운받아진다.
load-first order
로 순서 없이 먼저 로드된 것이 먼저 실행된다.DOMContentLoaded
를 신경쓰지 않는다.
쓰임새: DOM 이나 실행 순서에 연관 없는 스크립트
ex) 방문자 수 카운터, 광고 관련 스크립트
defer
- 백그라운드에서 다운받아진다.
- 문서에 추가된 순서대로 실행된다.
- DOM 이 로딩을 끝낸 후에 실행된다.
쓰임새: DOM 이 로드된 이후에 순서대로 실행되어야 하는 스크립트
ex) UI 렌더 스크립트
그림으로 살펴보기
type="module"
이 속성에 추가되면?
- 타임라인이 조금 달라지는데, 아무것도 안붙이면
defer
와 동일한 타임라인을 갖는다.defer
와 다르게src
속성을 이용한 스크립트가 아닌 인라인 스크립트 (<script></script>
) 에도 적용이 된다.
- 추가적으로
async
를 붙이면,async
와 매우 흡사하게 동작한다.
반응형
'자바스크립트 > 개념' 카테고리의 다른 글
자바스크립트 이벤트(Event) 객체와 커스텀 이벤트 (Custom Event) 란? (0) | 2023.07.07 |
---|---|
자바스크립트가 문자열을 표현하는 방식 (feat.UTF-16) (0) | 2023.03.06 |
매크로 태스크 (Macro Task) 와 마이크로 태스크 (Micro Task) 란? (0) | 2023.02.13 |
자바스크립트의 실행 컨텍스트 (Execution Context) 란? (0) | 2023.02.05 |
Lexical Scope (렉시컬 스코프) 란? (자바스크립트의 스코핑 방식) (0) | 2023.02.02 |