동기
비동기
async
defer
// JavaScript
<script>
const span2 = document.querySelector('.span');
console.log(span2);
</script>
// HTML
<span class="span">안녕하세요?</span>
// JavaScript
<script>
const span = document.querySelector('.span');
console.log(span); // output : <span class="span">안녕하세요?</span>
</script>
같은 코드임에도 불구하고 결과는 왜 다르게 나올까 ?
일반적으로 브라우저는 한줄씩 parsing한다
한줄씩 parsing 하다가 위의 코드처럼 script 태그를 만나면 parsing을 멈추고 script 파일을 다운 받아서 실행한 후에 이어서 남은 HTML을 parsing 한다.
즉 첫번째 script는 아직 parsing 하지도 않은 span 클래스명을 가진 요소를 선택할려고 했기 때문에 null이 나오고 두번째 script는 앞서 span 클래스명을 가진 요소를 parsing 하고 실행했기 때문에 정상적인 결과값이 나온다
위의 코드처럼 실행할려면 DOM을 따라 반드시 순서대로 실행되어야 할 때 용이한 코드라고 할 수 있다
그러면 script 파일을 무조건 body 끝에 넣으면 되겠네 ??
땡!!🤣
body 끝에 script 파일을 추가하면 HTML을 끝까지 parsing하고 마지막에 script 파일을 다운받고 실행한다
하지만 사용자가 웹과 상호작용을 시도하면 제대로 동작하지 않을 수도 있다
왜??
따라서 이런 동기적으로 하는 방법보다는 비동기적으로 하는게 좋다
어떻게 비동기적으로 불러오지??
async
, defer
!!// load 되는데 5초
<script src = 'main.js' async></script>
// load 되는데 1초
<script src = 'main2.js' async></script>
브라우저가 HTML을 parsing 하다가 async script를 발견하면 병렬로 다운 명령만 내리고 이어서 남은 HTML을 parsing 한다
async script 다운로드가 완료되면 진행중이던 HTML parsing을 멈추고 다운로드 된 async script를 실행한다
async script를 만나면 병렬로 명령을 내리기 때문에 시간절약이 가능하다
하지만 async script는 JS 파일이 여러개라면 먼저 다운로드가 끝난 JS를 먼저 실행한다. 즉 위의 코드처럼 main2.js의 다운로드가 먼저 끝나면 main2.js를 먼저 실행한다. 따라서 웹사이트가 JS 순서에 의존적이라면 좋지 않다
중요한 실행 순서 조정도 못하기 때문에 async는 권장하지 않는다
또 async script는 완전히 비동기로 불러오기 때문에 DOM이 모두 load된 경우에 발생하는 DOMcontentLoaded를 보장할 수 없다
Why?
🥰DOMcontentLoaded에 대한 자세한 설명은 제 벨로그에 있습니다🥰
그럼 진짜 뭐 쓰지..??
해결방법은 defer!!😘
// load되는데 5초
<script src="main.js" defer></script>
// load되는데 3초
<script src="main2.js" defer></script>
defer은 async와 비슷하게 HTML을 parsing하다가 병렬로 JS 파일을 다운 명령만 시키고 남은 HTML을 끝까지 parsing한다.
하지만 async와 제일 큰 차이점은 async는 JS 다운이 완료되면 그 내용이 즉시 실행되는 반면에 defer은 모든 HTML이 다운된 이후에 JS가 실행된다
위의 코드처럼 더 빨리 load되는 script가 있어도 선언한 순서에 따라 JS 파일이 실행된다
따라서 JS 파일을 전부 다운받은 뒤에 순서대로 실행하기 때문에 웹사이트가 JS 순서에 의존적일 때 좋으며 DOM 구성이 끝난 이후에 script 파일을 실행하기 때문에 async보다 좋다고 할 수 있다
결론적으로 가장 범용적으로 사용할 수 있는 속성은 defer인 것 같다
😍 코드 지적은 언제나 환영입니다. 읽어주셔서 감사합니다. 😍