New

DOMContentLoaded를 쓰는 이유

lshjju 2026. 6. 10. 10:27

아래 코드를 보면 

    document.addEventListener('DOMContentLoaded', function() {
    
    }

 

이 코드가 있습니다.

쉽게 설명하자면 돔을 모두 로드한 후에 스크립트를 실행하라는 안전장치 입니다.

많은 분들이 이걸 꼭 써야 하냐고 궁금해 합니다.

그래서 반드시 사용해야 하는 코드인지 설명 드리겠습니다.


  <script>

    document.addEventListener('DOMContentLoaded', function() {
      const checkbox = document.querySelector('#agree');
      const proceedButton = document.querySelector('#proceed');

      checkbox.addEventListener('change', function() {
        if (this.checked) {  
          proceedButton.classList.remove('disabled');  
          proceedButton.classList.add('enabled');  
          proceedButton.disabled = false;  
        } else {  
          proceedButton.classList.remove('enabled');  
          proceedButton.classList.add('disabled');  
          proceedButton.disabled = true;  
        }
      });
    });

    </script>

 

코드 출처 - Do it! 자바스크립트 웹 표준의 정석


 

결론부터 말씀드리면, 무조건 사용해야 하는 것은 아닙니다.


상황과 스크립트의 위치에 따라 쓰지 않아도 완전히 안전한 경우가 있습니다.

과거에는 필수 권장사항처럼 쓰였지만, 최근 모던 웹 개발에서는 이를 대체할 수 있는 더 깔끔한 방법들이 있어서 무조건 감싸서 쓰지는 않는 추세입니다.

왜 이 이벤트가 필요했고, 어떤 경우에 생략할 수 있는지 명확하게 정리해 드릴게요!


1. DOMContentLoaded를 쓰는 근본적인 이유

브라우저는 HTML 문서를 위에서부터 아래로 한 줄씩 읽으며 화면을 그립니다(파싱). 그런데 HTML 태그를 다 읽기도 전에 JavaScript가 실행되어 document.querySelector('#agree')를 실행하면 어떻게 될까요?

브라우저는 아직 #agree라는 태그가 존재한다는 사실을 모르기 때문에 null(아무것도 없음)을 반환하고, 뒤이어 나오는 코드에서 에러(Cannot read properties of null)가 발생합니다.

DOMContentLoaded는 "HTML 문서 전체를 다 읽고 DOM 트리가 완성될 때까지 기다렸다가 이 안의 코드를 실행해줘!"라고 브라우저에게 부탁하는 안전장치입니다.


2. 안 써도 완전히 안전한 상황 2가지

만약 아래의 2가지 상황 중 하나에 해당한다면 DOMContentLoaded로 코드를 감싸지 않아도 전혀 문제가 없습니다.

① <script> 태그가 </body> 바로 직전에 있을 때

HTML 문서의 가장 최하단(화면을 구성하는 태그들이 모두 나온 뒤)에 스크립트를 작성하면, 브라우저가 이미 위쪽의 HTML 태그들을 모두 읽은 상태이기 때문에 에러가 나지 않습니다.

HTML
 
<body>
  <input type="checkbox" id="agree">
  <button id="proceed">진행하기</button>

  <script>
    // DOMContentLoaded가 없어도 HTML을 이미 다 읽었기 때문에 안전합니다!
    const checkbox = document.querySelector('#agree');
    const proceedButton = document.querySelector('#proceed');
    // ... 이하 로직
  </script>
</body>

② 외부 스크립트 파일에 defer 속성을 사용할 때 (가장 권장됨)

최근 모던 웹 개발에서는 스크립트를 HTML 내부에 직접 적기보다 외부 파일(script.js)로 분리하여 <head> 태그 안에 넣는 방식을 선호합니다. 이때 defer라는 속성을 붙이면 DOMContentLoaded와 정확히 똑같은 효과를 냅니다.

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

defer 속성을 사용하면 script.js 파일 안에서는 DOMContentLoaded 이벤트 리스너로 코드를 감싸지 않고 바로 document.querySelector를 사용해도 안전합니다.


3. 요약 및 권장사항

작성 방식 DOMContentLoaded 필요 여부 비고
<head> 안에 일반 <script> 작성 필수 안 쓰면 에러 발생
</body> 직전에 스크립트 작성 선택 (생략 가능) 과거 표준 방식, 안전함
<head> 안에 <script defer> 작성 불필요 (생략 권장) 현재 모던 웹 개발의 표준 권장사항

따라서 질문 주신 코드가 HTML 문서의 맨 아래(</body> 앞)에 위치해 있거나, defer 속성이 붙은 외부 스크립트 파일이라면 감싸고 있는 document.addEventListener('DOMContentLoaded', ...) 문장을 지우고 알맹이 코드만 남겨두셔도 무방합니다. 코드가 훨씬 간결해질 거예요!