JS addEventListner의 발생 시기

강정우·2022년 10월 14일
0

JavaScript

목록 보기
25/53
post-thumbnail
  • JS를 공부하다 addEventListner에 4가지 속성값이 들어있길래 찾아보다 정리한다.
    이벤트 리스너엔 크게 3가지의 주요 이벤트가 들어간다고 한다.

⚖️ definition

  1. DOMContentLoaded – 브라우저가 HTML을 전부 읽고 DOM 트리를 완성하는 즉시 발생한다.
    이미지 파일이나 스타일시트 등의 외부리소스(기타 자원)은 기다리지 않는다.
  2. load – HTML로 DOM 트리를 만드는 게 완성되었을 뿐만 아니라 이미지, 스타일시트 같은 외부 자원도 모두 불러오는 것이 끝났을 때 발생한다.
  3. beforeunload/unload – 사용자가 페이지를 떠날 때 발생한다.

⏲️ when?

  • 그럼 주로 언제 쓰이나?
  1. DOMContentLoaded – DOM이 준비된 것을 확인한 후 원하는 DOM 노드를 찾아 핸들러를 등록해 인터페이스를 초기화할 때
  2. load – 이미지 사이즈를 확인할 때 등. 외부 자원이 로드된 후이기 때문에 스타일이 적용된 상태이므로 화면에 뿌려지는 요소의 실제 크기를 확인할 수 있음
  3. beforeunload – 사용자가 사이트를 떠나려 할 때, 변경되지 않은 사항들을 저장했는지 확인시켜줄 때
  4. unload – 사용자가 진짜 떠나기 전에 사용자 분석 정보를 담은 통계자료를 전송하고자 할 때

📜 content

DOMContentLoaded

<script>
  function ready() {
    alert('DOM이 준비되었습니다!');

    // 이미지가 로드되지 않은 상태이기 때문에 사이즈는 0x0입니다.
    alert(`이미지 사이즈: ${img.offsetWidth}x${img.offsetHeight}`);
  }

  document.addEventListener("DOMContentLoaded", ready);
</script>

<img id="img" src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">
  • 만약 위와같은 코드가 있다고 해보자 이때 이미지가 잘 로드될까? 정답은 맞긴하지만 원하는 결과값은 안 나올 것이다. 왜? DOMContentLoaded은 외부리소스가 로드되기 전에 실행되기 때문에 img가 없는것으로 나온다는 것이다.
  • 브라우저는 HTML 문서를 처리하는 도중에 <script> 태그를 만나면, DOM 트리 구성을 멈추고 <script>를 실행합니다. 스크립트 실행이 끝난 후에야 나머지 HTML 문서를 처리하죠. <script>에 있는 스크립트가 DOM 조작 관련 로직을 담고 있을 수 있기 때문에 이런 방지책이 만들어 졌습니다. 따라서 DOMContentLoaded 이벤트 역시 <script> 안에 있는 스크립트가 처리되고 난 후에 발생합니다.

    즉, script는 body 태그 뒤에 쓰거나 제일 마지막 단에 쓰는 것이 좋다는 뜻이다.

예외

그런데 이 DOMContentLoaded가 외부 리소스를 기다리는 경우가 있는데 바로 스타일시트를 불러오는 태그 바로 다음에 스크립트가 위치하면 이 스크립트는 스타일시트가 로드되기 전까지 실행되지 않는다는 것이다.
이런 예외는 스크립트에서 스타일에 영향을 받는 요소의 프로퍼티를 사용할 가능성이 있기 때문에 만들어졌다. 스타일이 로드되고, 적용되고 난 다음에야 좌표 정보가 확정되기 때문에 자연스레 이런 제약이 생겼다고 한다.

load

  • window 객체의 load 이벤트는 스타일, 이미지 등의 리소스들이 모두 로드되었을 때 실행된다. load 이벤트는 onload 프로퍼티를 통해서도 사용할 수 있다.

onunload

  • window 객체의 unload 이벤트는 사용자가 페이지를 떠날 때, 즉 문서를 완전히 닫을 때 실행된다.
    참조
    전송 데이터는 64kb를 넘을 수 없다!

readystate

<script>
  log('초기 readyState:' + document.readyState);

  document.addEventListener('readystatechange', () => log('readyState:' + document.readyState));
  document.addEventListener('DOMContentLoaded', () => log('DOMContentLoaded'));

  window.onload = () => log('window onload');
</script>

<iframe src="iframe.html" onload="log('iframe onload')"></iframe>

<img src="http://en.js.cx/clipart/train.gif" id="img">
<script>
  img.onload = () => log('img onload');
</script>

result

  1. initial readyState:loading (1st)
  2. readyState:interactive (2nd)
  3. DOMContentLoaded (2nd)
  4. iframe onload (3th)
  5. img onload (4th)
  6. readyState:complete (4th)
  7. window onload (4th)
  • 분석
  • [1] document.readyState는 [3] DOMContentLoaded가 실행되기 바로 직전에 [2] interactive가 됩니다. 따라서 [3] DOMContentLoaded와 [2] interactive는 같은 상태를 나타낸다고 볼 수 있다.
  • [1] document.readyState는 [4] iframe, [5] img를 비롯한 리소스 전부가 로드되었을 때 complete가 된다.
    위 예시에서 우리는 [1] readyState의 값이 img.onload와 window.onload가 실행된 시점과 거의 동일한 시점에 complete로 바뀌었다는 것을 확인할 수 있다.
    [6] readyState의 값이 complete로 바뀐다는 것은 [7] window.onload가 실행된다는 것과 동일한 의미이다. 이 둘의 차이점은 window.onload는 다른 load 핸들러가 전부 실행된 후에야 동작한다는 것에 있다.

정리

  • 대부분 load 보다 ready 또는 DOMContentLoaded 를 사용하는 이유는 무엇인가?
    load 는 모든 리소스를 로드해야하기 때문에 DOMContentLoaded 가 먼저 발생된 후 발생한다.
    대부분 모든 리소스를 기다릴 필요가 없는 경우가 많기에, 단순히 빠른 실행을 위함이다.
    관련 이벤트를 하단에 작성하는 이유는 무엇인가?대부분 스크립트를 </body> 위에 작성하거나, 하단에 작성하는 경우가 많다.
    HTML 문서를 파싱하는 과정에서 script 태그를 만난다면, DOM 구축 작업이 중단된다.
    중단된 후, script 작업을 실행된 후에 다시 작업이 재실행되는 것이다. DOMContentLoaded 이벤트가 발생하는 시점이 script 작업 완료 시간만큼 지연된다는 의미이다.
    또한 상황에 따라, DOM 구축이 되지 않은 상태에서 DOM 을 가져오기 때문에, 정상적인 동작이 이루어지지 않는다.
profile
智(지)! 德(덕)! 體(체)!

0개의 댓글