일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- S3
- socket io
- git
- 채팅
- TypeScript
- wetube
- Vue
- SAA
- crud
- async
- docker
- SSA
- pandas
- MongoDB
- node
- react
- lambda
- 카톡
- AWS
- NeXT
- 중급파이썬
- flask
- 파이썬
- merge
- RDS
- EC2
- dict
- Props
- 튜플
- Class
- Today
- Total
초보 개발자
JS파일 가져오기 defer, async 본문
test.js라는 파일을 index.html에서 사용하려고한다.
index.html에서 test.js를 가져와보자!
아래의 이미지들은 index.html, test.js, error콘솔을 나타내고 있다. test.js에서는 DOM을 사용하여 해당 버튼을 클릭하면 alert창이 나오도록 설계하였다. 그리고 error콘솔은 의도대로 되지 않고 에러가 발생한 모습이다.
null에서 addEventListener라는 프로퍼티를 찾을 수 없다고한다. 나는 분명 testBtn을 설정해주었는데 말이다.
그럼 testBtn이라는 것을 console에 찍어 보도록 하자.
역시 null이라고 나온다. 이상하다. 나는 분명 testBtn을 정의해주었고 html에서도 분명히 존재하는데 말이다.
이렇게 에러가나는 이유는 시점의 차이이다.
index.html은 순차적으로 파일을 읽어내려간다.
script가 실행될때에는 아직 HTML을 렌더링 하지 않은 상태이기에, DOM에 접근할 수 없는 상태이다.
접근할 수 없는 상태에서 접근을 하려고하니 NULL이 선언이 된 것이고,
NULL인데도 불구하고 프로퍼티를 찾으려고하니 에러가 발생했던 것이다.
해결방법 1 🔨
body 최 하단에서 script를 로드한다. 위에서 부터 내려온다고 하였으니 html을 다읽은 뒤 script를 읽으면 DOM에 접근할 수 있을 것이다.
잘 실행이 되는 것을 확인할 수 있다.
해결방법 2 ⚾
load 이벤트 리스너 등록이다.
window.onload : HTML파싱 DOM생성 그리고 외부 콘텐츠 (images, script, css , etc )가 로드된 후 발생하는 이벤트이다.
script파일이 body위에 있기에 먼저 실행이 되는 것은 맞지만, onload이벤트 리스너를 사용하였기 때문에 모든 html요소가 파싱이 된 후에 load이벤트가 실행이 되기에 DOM에 접근할 수 있게 되는 것이다.
여기서 만약 img가 1000개가 있다고 가정해보자, 그럼 img가 1000개 다 로드 된 후에 저 onload가 실행이 되는데 사실 저 onload함수에는 img와 관련이 없기에 비효율적일 수 있다.
이 때 사용할 수 있는 이벤트는 DOMContentLoaded이다. HTML파싱 DOM생성 후 발생하는 이벤트이다.
다시 말해서 외부 콘텐츠가 로드되는 것은 기다리지 않는다.
Script load 1 🎇
앞서 우리가 사용했던 방식이다. HTML이 위에서부터 아래로 쭉 읽어나가면서 script를 만나면 HTML파싱을 멈추고 script를 가져온 뒤 script를 실행시킨다. 이 후에 script가 실행이 끝나면 멈춘 부분부터 다시 HTML을 파싱해나가기 시작한다.
앞서 testBtn이 null인 이유도 이러한 이유 때문이었다고 말하였다.
하지만 body태그 최하단에 script를 넣게 되면 위와 같이 HTML파싱이 다 끝난 뒤에 script파일을 읽고 실행시키기 때문에 원활히 의도한대로 흘러갈 수 있었던 것이다.
그런데 이 방법도 효율적이진 않다. 왜냐하면 HTML파싱이 다 끝난 뒤에서야 script파일을 읽어오기 때문이다.
HTML파싱 중에 script파일을 읽어온다면 ( 실행은 안시킴 ) 좀더 효율적이지 않을까?? 여기서 제목에서 사용한 defer와 async의 개념이 나온다. 이 두 속성을 활용하면 JS파일을 효과적으로 가져올 수 있다.
Script load 2 defer🎁
defer속성은 HTML 파싱과 함께 비동기로 JS파일을 불러온다. HTML 파싱이 완료된 후 JS코드를 실행한다.
HTML파싱을 하다가 Script태그를 만나면 파싱을 멈추지 않고 동시에 script파일을 가져온다. 그 이후 실행은 HTML 파싱이 끝난 후에 Script가 실행이 된다. 따라서 원활히 가져올 수 있다.
.
test.js를 위와같이 바꾸고 실행시켜보면 잘 실행이 되는 것을 확인할 수 있다.
Script load 3 async 🎁
defer과 마찬가지로 HTML 파싱과 함께 비동기로 JS파일을 불러온다.
HTML파싱이 완료되지 않았더라도, 먼저 로딩되는 JS파일부터 실행이 시작된다.
JS파일을 실행할 때는 HTML 파싱이 중단된다.
script를 일반적으로 두었을 경우에는 script파일을 만나 읽어오는 것부터 실행시킬 때 까지 HTML파싱을 중지 시켰다면
async를 사용하면 sciprt파일을 만나 읽어올 때는 HTML파싱을 유지하고 script파일을 다 읽어와서 실행시킬 때에는 HTML파싱을 멈춘다.
따라서 우리가 의도한 대로 원활히 이루어 지지 않을 수 있다. async를 사용할때에는 꼭 필요한 경우에 사용하는 것이 좋을 것 같다.
일반적으로 script파일을 불러올때에는 defer속성이 효과적이다.
'이것 저것' 카테고리의 다른 글
이클립스 단축기 (0) | 2022.07.18 |
---|---|
this란 무엇인가? (0) | 2022.06.21 |
DOM? BOM? ( feat. CSSOM ) (0) | 2022.06.12 |
AWS EC2 Ubuntu 18.04 NODE 설치 하기 16.x버전 (0) | 2022.05.23 |
pm2로 node 배포! (0) | 2022.05.15 |