
html에 javascript를 추가하는 방법은 간단하다.
아래와 같이 script 태그를 이용하면 javascript를 실행시킬수 있다.
<script>
console.log("hello world");
</script>
또는 아래와 같이 외부 javascript 파일을 참조시켜 추가 하는 법도 있다.
// script.js
console.log("hello world");
// index.html
<script src="script.js"></script>

그렇다면 아래와 같이 Dom 에서 엘리먼트를 조회하는 코드를 작성해보자

button 엘리먼트를 잘 조회 하여 콘솔에 출력이 되었는가?
❌ 아니다! 찾지 못했다는 의미의 null 가 출력될 것이다.

이는 html 구문을 해석할때 순서대로 해석하기 때문인데
말그대로 위 부터 차례대로 해석하기 때문에 먼저나온 id로 요소를 조회하는 코드가 먼저 실행되고
버튼이 나중에 렌더링 되기 때문에 버튼을 getElementById로 조회할수 없는 것이다.
아주 당연한 말이다. 그저 태그를 뒤에 위치 시키기만 하면 해결이 되긴한다.
하지만 이는 해당 스크립트보다 위에 있는 요소들이 분석및 렌더링 되어야만 스크립트의 로드 및 구문 분석이 늦어지는 단점이 존재한다…
dom 의 body가 모두 로드 되고 실행할 콜백을 넣어주는 방식이 있다.


위 방법으로 해결되긴 하지만 코드가 한번 들여쓰기 되야 하고 좀 귀찮은 느낌이 있다.
좀더 쌈뽕한 방법이 없을까?
위 DOMContentLoaded 이벤트는 인라인 스크립트를 사용할때사용하는 방법이다
하지만 코드를 작성하다보면 인라인 스크립트 보다는 외부 javascript 파일을 참조하여 html 코드를 구성할때가 많다.
// index.html
<script src="index.js"></script>
<button id="a">This is button</button>
// index.js
const button = document.getElementById("a");
console.log(button);
위처럼 구성시 script 태그에 defer 또는 async 속성을 부여하면 우리가 원하는 동작을 기대할수 있다.
// index.html
<script src="index.js" async defer></script>
<button id="a">This is button</button>
aysnc 속성은 페이지의 순서에 구애받지 않고 로드, 실행된다.
아래와 같은 여러개의 스크립트는 로드, 실행 순서를 보장받지 못한다.
<script src="index1.js" async></script>
<script src="index2.js" async></script>
<button id="a">This is button</button>
// index1.js
console.log(1);
// index2.js
console.log(2);

또는

하지만 defer는 스크립트 순서에 종속적이기 때문에 순서를 보장받는다.
<script src="index1.js" defer></script>
<script src="index2.js" defer></script>
<button id="a">This is button</button>