사이트 검색

어떤 이야기를 찾고 있나요?

제목이나 내용으로 검색해 보세요.

script 태그는 어느 곳에 위치하는 것이 좋을까?

NoHackSoftware Engineer

자바스크립트를 불러오는 방법

HTML 문서를 작성하면서 자바스크립트 파일을 포함시켜야 할 때, 가장 기본적인 방법으로 head 안에 script 태그를 넣는 방법이 있습니다. 대충 아래와 같은 코드가 나오겠지요?

<!doctype html>
<html lang="ko">
<head>
<title>Document</title>
<script src="main.js"></script>
</head>
<body></body>
</html>

위 코드에 의해 우리는 HTML 문서에서 자바스크립트 코드를 불러와 사용할 수 있습니다. 하지만 이 코드에는 약간의 문제가 있는데, 이를 이해하기 위해서는 HTML 문서가 파싱(Parsing)되는 과정을 알아야 합니다. HTML 문서는 위에서부터 아래로 파싱이 진행되며, 중간에 script 태그를 만나면 파싱을 잠시 중단하고 스크립트를 먼저 불러오게 됩니다. 그리고 이 과정이 끝나면, 다시 HTML 파싱을 재개하는 식으로 동작합니다.

동작 과정을 그림으로 보면 다음과 같습니다.

기본 script 태그의 로딩과 실행 흐름
기본 script 태그의 로딩과 실행 흐름

언뜻 보기에는 큰 문제가 없어 보이지만, 다음과 같은 단점이 있습니다.

  • 자바스크립트 용량이 크면 화면이 표시되기까지 시간이 오래 걸릴 수 있습니다.

그렇기 때문에 script 태그는 몇 가지의 다른 방법들로 사용하게 됩니다.

body 최하단에 작성하기

<!doctype html>
<html lang="ko">
<head>
<title>Document</title>
</head>
<body>
<script src="main.js"></script>
</body>
</html>

이렇게 body 태그 맨 밑에 script 태그를 작성하게 되면, 다음과 같이 동작합니다.

body 마지막에 둔 script 태그의 로딩 흐름
body 마지막에 둔 script 태그의 로딩 흐름

이 방법은 웹페이지를 전부 불러온 이후, 스크립트를 가져오기 때문에 사용자가 웹페이지를 보기까지 지연되는 시간이 없습니다. 하지만 자바스크립트를 마지막에 불러오기 때문에, 그 전에 웹페이지의 동적인 요소들이 올바르게 동작하지 않을 수 있습니다.

async 속성 사용하기

<!doctype html>
<html lang="ko">
<head>
<title>Document</title>
<script async src="main.js"></script>
</head>
<body></body>
</html>

이 방법은 script 태그 안에 async 속성을 적어줌으로써, HTML 파싱 과정과 문서 내의 모든 자바스크립트 Fetching 과정이 비동기로 진행될 수 있게 합니다. 그리고 Fetching이 완료된 스크립트가 있으면, 그때서야 HTML 파싱을 잠시 중단하고 Fetching이 완료된 순서대로 Execution을 진행합니다.

async를 사용한 script 태그의 로딩 흐름
async를 사용한 script 태그의 로딩 흐름

확실히 HTML 문서 파싱과 Fetching이 병렬로 진행되기 때문에, 속도가 빨라져 단점이 해결된 것처럼 보일 수 있습니다. 하지만 async는 Fetching이 완료된 순서대로 스크립트를 실행하기 때문에 스크립트간에 의존성 문제가 발생할 수 있습니다.

예를 들어 A와 B라는 스크립트가 있는데, B는 A안에 있는 코드를 참조하고 있습니다. 그렇다면 이 두 파일을 HTML 문서에 불러오려 한다면, 반드시 A가 먼저 불러와져야 합니다. 하지만 async는 순서를 보장하지 않는 특성 때문에, B가 먼저 실행되어 올바르게 동작하지 못 할 수 있습니다.

defer 속성 사용하기

<!doctype html>
<html lang="ko">
<head>
<title>Document</title>
<script defer src="main.js"></script>
</head>
<body></body>
</html>

deferasync와 사용 방법이 동일하지만, 동작 방식에 약간의 차이가 있습니다.

deferasync처럼 다운로드와 HTML 파싱이 병렬로 진행됩니다. 다만 불러온 스크립트는 HTML 문서의 파싱이 끝난 뒤 실행되며 문서에 작성된 순서도 보장합니다.

결론 🎉

defer를 사용한 script 태그의 로딩 흐름
defer를 사용한 script 태그의 로딩 흐름

DOM에 의존하거나 실행 순서가 중요한 스크립트에는 defer가 잘 맞습니다. 다른 스크립트와 독립적으로 동작하는 분석 도구처럼 실행 순서가 중요하지 않은 경우에는 async가 적합합니다. type="module"인 스크립트는 별도로 지정하지 않아도 기본적으로 지연 실행됩니다.

참고 자료

'스토리 - Web'의 다른 글

0