async & defer

Sjin·2021년 1월 2일
0

브라우저가 HTML 파일을 파싱할 때는 위에서부터 한줄씩 순차적으로 읽습니다. 이 때, <script> </script> 태그를 만나면 파싱하던 것을 멈추고, script를 다운받고 실행하는 과정을 처리합니다. 이 과정이 끝나면 다시 파싱을 이어나갑니다. 그래서 이 <script> </script> 태그를 어디에 선언하고, 어떻게 선언하는지에 따라 속도와 성능에 차이가 생깁니다.

<head>
  ...
  <script src=""></script>
</head>

위에서 설명했듯이 스크립트를 만나면, 파싱을 멈추고 스크립트를 다운로드합니다. 이후, 실행까지 끝나야 파싱을 이어나갑니다. 이 방법은 아래에 있는 DOM 요소에 접근할 수 없습니다. 또한, 스크립트 파일이 무겁다면 다운 받을때까지 사용자는 스크립트 아래의 내용을 볼 수 없습니다.

body의 마지막

<body>
  ...
  <script src=""></script>
</body>

이 방법을 사용할 경우 script가 가장 마지막에 다운로드를 받기 때문에 위에 있는 요소를 접근할 수 있고, 사용자는 페이지에서 콘텐츠를 볼 수 있습니다. 하지만 이 방법도 완벽한 해결책이 아닙니다. 만약 페이지가 자바스크립트에 많이 의존적인 상태에서 스크립트 파일이 무겁다면, 사용자는 페이지를 볼 순 있어도 자바스크립트를 이용한 동적인 페이지를 온전히 이용할 수 없습니다.

이러한 방법을 해결하기 위해서는 script의 속성 중에 asyncdefer를 이용하는 것입니다.

header + async

<head>
  <script async src=""></script>
</head>

스크립트 파일을 다운로드 받을 때, html 파싱을 멈추지 않고 병렬적으로 수행한다 것이 가장 큰 차이점입니다. 파싱을 멈추지 않기 때문에 다운로드 받는 시간을 절약할 수 있습니다. 다운로드가 완료되면 파싱을 멈추고 실행을 합니다.

이 방법의 문제점이 있습니다. 첫째, 다운로드가 완료된 순서대로 실행하기 때문에 사용자가 의도한 순서대로 실행되지 않습니다. 가령 스크립트 a와 b가 있다고 가정해보겠습니다. a는 무거운 스크립트이고, b는 가벼우면서 a에 의존적인 스크립트입니다. b가 가볍기 때문에 먼저 다운로드가 완료되어 실행됩니다. a에 의존적이기 떄문에 a 스크립트를 이용해야하는데 a는 아직 다운로드 중이라서 이용할 수 없습니다.

둘째, 스크립트가 실행될 때, html 파싱이 멈추기 때문에 문제가 생길 수 있습니다. 스크립트에서 DOM을 조작해야 하는데 아직 파싱 중이기 때문에 조작하려는 요소가 DOM에 없을 수도 있습니다.

셋째, 아직 실행할때는 파싱을 멈추기 때문에 낭비되는 시간이 존재합니다. 이러한 점을 보완할 수 있는 속성이 defer입니다.

header + defer

<head>
  <script defer src=""></script>
</head>

async와 마찬가지로 스크립트를 다운로드 과정은 병렬적으로 수행합니다. 차이점은 다운로드만 받고 실행은 하지 않고 대기하고 있습니다. 이후, html 파싱이 완료되면 사용자가 정의한 순서대로 스크립트가 실행됩니다. 그래서, async와 같은 문제점이 발생하지 않습니다.

conclusion

네가지 방법 중에서 header - defer를 이용하는 방법이 가장 효율적입니다.

profile
웹뷰 개발에 관심 많은 Front-end 개발자입니다.

0개의 댓글

Powered by GraphCDN, the GraphQL CDN