[JS] DOMContentLoaded, load 차이점

POLO·2024년 1월 29일
0
post-thumbnail

DOM 요소 렌더링 전 가져오기 오류

DOM 요소를 자바스크립트로 렌더링 하는 경우, 해당 요소를 사용하는 스크립트 작성 시에 해당 요소가 없다는 오류를 심심찮게 볼 수 있다.

아래 코드를 돌려보면 오류가 표시될까?

const body = document.querySelector('body');
const newElement = document.createElement('div'); 
newElement.className = 'new';
body.appendChild(newElement);

변수 body를 null로 인식하는 문제가 발생했다.
이 문제가 발생하는 원인은 첫 번째로 script 파일을 head 요소에서 불러왔기 떄문이다.
head 요소에서 불러온 스크립트는 body 요소 보다 먼저 읽기 때문에 아직 안 만들어진 body를 불러올려고 하면 당연히 null이 반환될 수 밖에 없다.

이 문제는 해당 script 파일을 head가 아닌 body요소에서 가져오는 것으로 변경을 하면 간단하게 해결 할 수 있다.

오류가 표시되지 않고 body 요소에 새로운 요소가 추가되었다.

그렇다면 head 요소에서 script 파일을 가져올 때 body 요소에서 가져온 것 처럼 오류를 없앨 수는 없을까?
DOMContentLoaded, load 이벤트를 사용하면 가능하다!

DOMContentLoaded

브라우저는 DOM 트리 구성을 위한 HTML 파싱 -> 스타일과 HTML 규칙이 포함된 렌더 트리 구축 -> 렌더 트리를 정해진 순서대로 배치 -> 배치한 렌더 트리 화면에 그리기 의 렌더링 과정을 거친다.

일반적으로 브라우저는 HTML을 파싱하는 도중 스크립트 구문을 만나면 파싱을 잠시 멈추고 스크립트를 실행한다.

이러한 브라우저의 동작때문에 head 요소에 있는 script 파일은 body 요소보다 먼저 읽히게 되어 위(DOM 요소 렌더링 전 가져오기 오류)와 같은 문제가 발생하게 된다.

DOMContentLoaded 이벤트는 DOM 요소 렌더링이 끝나면 트리거 되기 때문에 아래와 같이 코드를 작성해 주시면 head 요소에서 script를 실행해도 body 요소를 읽을 수 있게 된다.

document.addEventListener("DOMContentLoaded", () => {
    const body = document.querySelector('body');
    const child = document.createElement('div'); 
    child.className = 'child';
    parent.appendChild(child);
    body.appendChild(parent);
    const parent = document.createElement('div'); 
    parent.className = 'parent';
});

DOMContentLoaded 이벤트는 DOM 요소 렌더링 중에 스크립트를 만나면 스크립트를 실행을 모두 완료한 후 트리거 된다.

아래와 같은 코드가 실행되면 어떤 순서로 출력될까?

window.addEventListener('DOMContentLoaded', () => {
    console.log('DOM 콘텐츠 로드가 완료되었습니다.');
})

console.log('스크립트 내의 5초 타이머');
setTimeout(()=> {
    console.log('스크립트 내의 5초 타이머 완료');
    document.body.appendChild(document.createElement('div'));
}, 5000)

for(let i = 0; i <=1000000000; i++) {
    
}
console.log('반복문 종료');

DOMContentLoaded 이벤트가 반복문이 종료됨과 동시에 트리거된 걸 볼 수 있다.

이는 비동기작업(setTimeout 등)이 DOMContentLoaded를 막지 않기 때문이다.
DOMContentLoaded를 막는 건 동기 작업 뿐이다.

load

DOMContentLoaded 이벤트는 DOM 요소만 신경쓰는 반면 load 이벤트는 문서 내의 리소스(스크립트, 이미지, HTML 등)가 모두 로드되었을 때 트리거된다.

페이지가 가지고 있는 이미지와 스크립트 용량이 클수록 렌더링이 오래 걸리기 때문에 DOMContentLoaded로도 충분히 해결 가능할 때, load를 사용하는 일은 없도록 해야 한다.

0개의 댓글