script 태그의 선언 위치와 차이점 (async 와 defer 비교)

javascript를 공부하다보면 javascript를 불러오고 작성할 수 있는 태그인 <script></script>를 html의 head 부분 또는 body 태그 마지막 부분에 작성하는것을 볼 수 있다. 

JavaScript를 불러오는 script 태그는 head 태그 안쪽에도 작성할 수 있고, body 태그 안쪽에도 작성할 수 있는데 여러 강의나 예제들 마다 위치를 다르게 작성하여 어디에 선언하는게 좋은것인지 찾아보게 되었다.

head 태그 또는 body 태그에 작성해도 되지만 코드가 효율적으로 동작하기 위해서는

defer 키워드를 사용하여 head 태그 안쪽에서  script 태그를 작성하는 것이다.

<head>
<script defer src="index.js"></script>
</head>


아래에는 그동안 볼 수 있었던 방식의 단점들을 알아보았고 왜 defer 키워드를 사용하여 head 태그 안쪽에 작성해야하는지 알아보았다.



첫번째 : head 태그 안쪽에 script 태그를 작성하는 경우

head 태그안에 작성했을때 문제점을 보면 웹브라우저가 html 문서를 해석할 때 왼쪽에서 오른쪽으로, 위에서 아래로 순차적으로 수행되는데  

head 태그에 작성한 script 태그를 만나면 그 안에 작성된 javascript 코드들을 해석하고 처리하게되는데, 이러한 작업이 끝날때까지 아래에 작성된 다른 html 코드들이 수행되지 못해 화면을 출력하는데까지 시간이 느려지게 된다.

추가적으로 js파일 내부 코드 중에 html 태그에 접근하여 태그를 조작하도록하는 함수들이 존재하는경우 head 태그 안에 script 태그를 작성하면 

body 안에 작성된 태그들이 생성되기 이전에 즉, DOM트리가 완성되기 이전에 함수를 실행하게되면서 함수안에서 접근하고있는 해당 태그들에 접근하지 못하게 되고 오류가 발생하게 된다.



두번째 : body 태그 안쪽 맨아래 끝부분에 작성하는 경우

body 태그 끝에 작성하는 경우 html 요소들을 모두 파싱하고 준비 된 다음에 스크립트를 만나서 스크립트를 서버에서 받아오고 실행한다.

첫번째에서 언급했던 문제점인 DOM 트리가 완성되기 이전에 js파일 내부에 작성된 DOM 조작 함수들이 실행되어 오류가 발생되는것을 방지할 수 있지만 이러한 방법에도 문제가 존재한다.

사용자가 기본적인 컨텐츠를 빨리 볼 수 있다는 장점은 있지만 만약에 사이트가 자바스크립트에 상당히 의존적이라면 

즉, 사용자가 의미있는 컨텐츠를 보기 위해서는 자바스크립트를 통해서 서버로부터 받아와야 한다던지 또는 DOM 요소를 더 이쁘게 꾸며준다던지 하는 경우에는 

사용자가 정상적인 사이트를 보기위해서는 js파일을 해석하고 수행해야하는데 시간이 소요되므로 역시나 성능면에서 단점이 될 수 있다.



세번째 : head 태그안에 async 키워드를 사용하는 경우

head 태그안에 async 키워드를 사용하는 방법이다. aync를 사용하면 비동기적으로 코드를 실행하게 되므로 해당 스크립트를 만나면 뒤에서 js파일을 해석하고있고 그 밑에 작성된 나머지 html 태그를 해석하게 된다.

html 태그를 해석하다가 async 키워드와 함께 작성된 js파일이 다운로드가 완료되면 html 해석을 잠시 멈추고 다운로드 완료된  js파일을 실행하고 이어서 멈춰있던 나머지 html 태그를 해석하게된다. 

역시 해석을 잠시 멈추는 동안의 시간때문에 사용자에게 화면이 출력되는 시간이 느려지게되고 위에서 말했듯이 js파일에서 DOM을 조작하는 기능들이 작성되어있다면 아직 완전히 로딩되지 못한 html의 요소들로 인해 해당 DOM에 접근하지 못하게되어 문제가 발생할 수 있다.


⭐️네번째 : defer 키워드를 사용하는 경우

위에서 살펴본 세가지 방법의 모든 단점들을 그복할 수 있는 방법은 head 태그안에 script 태그를 작성하고 script 태그안에 defer 키워드를 사용하는 방법이다.

head 태그안에 script 태그에 defer키워드를 사용하면 script 해석을 비동기적으로 수행하고

html 코드를 순차적으로 실행하다가 html 코드들이 모두 파싱되어 해석이 완료되면 비동기적으로 수행된 script 태그의 js파일들이 마지막에 작성된 순서대로 실행된다.

즉, 비동기적으로 수행되므로 중간에 해석이 멈추는것을 방지할 수 있으며, html 코드 해석이 완료된 뒤에 비동기적으로 수행된 js파일이 실행되므로 DOM 조작 문제 또한 해결할 수 있다. 




async와 defer의 차이점

위에서 언급했지만 간단히 차이점을 확인해보면

async를 사용하면 비동기적으로 여러개의 스크립트가 작성 순서와는 상관없이 다운로드되며, html 코드를 해석하는 동안이더라도 먼저 완료된 스크립트가 도중에 실행되어 순서가 중요시되는 경우 스크립트 순서가 바뀌어 실행되므로 문제가 될 수 있다. (DOM 트리 생성 이전에 DOM에 접근하여 문제 발생 가능성 존재)

반면에 defer는 html을 파싱하는 동안 비동기적으로 js파일을 다운로드하고 html 파싱이 완료되면 작성된 순서대로 스크립트를 실행하게되므로 지연이 덜 발생하며 스크립트 실행 순서가 중요시되는 경우에 aysnc와는 달리 스크립트 순서가 바뀌어 실행되는 문제를 방지할 수 있다.






댓글