문서 객체 모델(Document Object Model, DOM)은 웹 페이지 내의 모든 콘텐츠(HTML)를 계층화시켜 객체로 나타내는 모델이다.
객체의 접근방식 중 dot notation을 사용하여 document 객체에 접근하는 것으로 시작된다. 이 document 객체를 사용해서 페이지의 내용을 변경하거나 html 요소를 새로 만들거나 클래스를 부여하거나 스타일을 부여하는 등 여러가지 작업을 할 수 있다.
DOM 객체 트리 구조를 시각화한 자료이다. 각각의 태그는 요소 노드(element node) 혹은 그냥 요소라고 하며 트리 구조를 구성한다. root 노드인 html을 기준으로 head, body라는 자식 노드가 있고 나무 가지처럼(트리 구조) 계속 자식 노드들이 형성되어 있다.
document.body.style.background = 'blue';
// body 의 배경을 파랑색으로 변경
document.body로 body에 접근한 예시이다. 이처럼 document 라는 진입점에서 출발하여 원하는 요소 노드에 접근하는 대표적인 함수가 몇 가지 있다.
document.getElmentById()
document.getElementsByClassName()
document.getElementsByTagName()
document.querySelector()
document.querySelectorAll()
위의 함수들을 사용하여 원하는 요소에 접근한 후 해당 요소를 변경할 수 있다.
const myFirstClass = document.getElementsByClassName('myClass')[0];
const contactEmail = document.getElementById('contactEmail');
myFirstClass.innerHTML = '퍼스트 클래스'
contactEmail.style.color = 'green'
위의 코드를 해석하면, 'myClass'라는 클래스 이름을 갖는 요소들 중 첫번째 요소에 접근한 후 '퍼스트 클래스'라는 문자를 입력했다. 그리고 'contactEmail'이라는 id 이름을 갖는 요소에 접근하여 배경색을 초록색으로 변경했다.
getElemntsByClassName 에서는 elements(복수형)이므로 'myClass' 에 해당하는 요소를 담은 컬렉션이 반환된다. 따라서 여러 개 중 첫 번째에 접근하기 위해 [0]과 같이 배열의 요소에 접근하는 것처럼 하나를 특정해야 한다. 반면 id는 고유한 값이기 때문에 getElementById 와 같이 접근하는 것 만으로 하나의 요소에 접근할 수 있다.
브라우저는 HTML을 읽다가 <script>
태그를 만나면 DOM 생성을 멈추고 스크립트를 먼저 실행한다. 이런 브라우저의 동작 순서 때문에 다음과 같은 문제가 발생한다.
<script>
는 해당 스크립트 아래에 있는 DOM에 접근할 수 없게 된다.용량이 크지 않은 웹페이지의 경우, <script>
태그는 <body>
의 최하단에 위치시켜 모든 컨텐츠가 다 보여지고 나서 스크립트 파일이 실행되도록 할 수 있다. 이렇게 하면 스크립트 위에 있는 요소에 접근할 수 있고, 페이지 컨텐츠 출력을 막지 않게 된다.
그런데 이 방법은 완벽한 해결책이 될 수는 없다. HTML 문서 자체가 아주 큰 경우를 가정해보면 브라우저가 HTML 문서 전체를 다운로드 한 다음에 스크립트를 다운받게 하면 페이지가 정말 느려지게 된다.
이런 문제를 해결할 수 있는 <script>
속성이 있는데, 바로 defer와 async이다.
<script defer src=""></script>
<script async src="https://long.js"></script>
<script async src="https://small.js"></script>
위치상으론 small.js가 아래이긴 하지만 long.js보다 먼저 다운로드된다면 먼저 실행된다. 이렇게 먼저 로드가 된 스크립트가 먼저 실행되는 것을 'load-first order’라고 부른다.
https://developer.mozilla.org/ko/docs/Web/API/Document_Object_Model/Introduction
https://ko.javascript.info/script-async-defer