DOM

DOM(Document Object Model)

Posted by yunki kim on August 3, 2021

  웹 페이지의 내용을 js로 다룰때는 단순히 내용을 문자열로 다루는 것 보다 어떠한 덩어리로 조작하는 것이 더 쉽다. 이를 위한 것이 DOM이다.

  DOM은 HTML, XML문서를 프로그램에서 이용하기 위한 API이며 트리 구조를 사용한다. 이때 이 트리를 DOM트리라 한다. 구조 자체가 트리인 만큼 DOM트리 안에서 각 객체를 노드라 하며 어떤 노드와 다른 노드와의 관계는 트리에서 사용하는 관계와 같다(부모, 자식 등).

  DOM 사양은 W3C에 의해 Level1~3으로 정의되 있다.

DOM Level 1

  DOM Level1은 Core, HTML이 두 가지 모듈로 구성되 있다.

모듈 설명
Core HTML에 한정되지 않은 일반적인 DOM 조작에 대한 사양
  getElementsByTagName - 태그명을 지정해 요소를 구한다
  createElement - 요소를 작성한다
  appendChild - 요소를 삽입한다
HTML HTML 문서 특유의 메서드에 대한 사용

DOM Level 2

 DOM Level2는 Level1의 모듈을 가지면서 이벤트 처리에 관한 Events 모듈이 들어 있다. CSS 또 한 여기에 정의되 있다. IE8이하는 Level2를 따르지 않고 파이어폭스, 크롬은 Level2를 거의 완벽하게 지원한다.

모듈 설명
Core Level1 Core의 확장
HTML Level1 HTML의 확장
Views 문서의 표시 상태에 대한 사양
Events 캡처링, 버블링, 이벤트 취고 등의 이벤트 시스템의 사양
Style stylesheet에 대한 사양
Traversal and Range DOM트리를 따라가는 방법이나 범위 지정에 대한 사양

DOM Level3

  DOM Level3은 아직 권고 단계에 있지 않다. 하지만 최신 브라우저 에서는 Events 모듈에 정의된 내용이 구현되 있다.

모듈 설명
Core Level2 Core의 확장
Load and Save 문서 구조 읽고 쓰기에 대한 사양
Validation 문서 구조가 타당한지를 검증하기 위한 사양
XPath XPath에 대한 사양
Events Level2 Events의 확장, 키보드 이벤트 지원

 

요소, 노드

  요소와 노드는 상속 관계에 있고, 노드가 상위 타입이다. 노드에는 nodeType이라는 속성이 존재하는데 이 값이 ELEMENT_NODE(1)인것이 요소이다. 다음은 HTML문서에서 주로 사용되는 노드이다.

노드 노드 타입 상수 노드 타입의 값 인터페이스
요소 노드 ELEMENT_NODE 1 Element
속성 노드 ATTRIBUTE_NODE 2 Attr
텍스트 노드 TEXT_NODE 3 Text
코멘트 노드 COMMENT_NODE 8 Comment
문서 노드 DOCUMENT_NODE 9 Document

 

Document 객체

  Document 객체는 DOM 트리에서 루트 노드 이다. Document객체는 documentElement property or body property에 대응하지만 특정 태그에 대응되지는 않는다. Document객체를 해당 HTML문서 전체를 표현한다.

  Document객체는 js안에서 document 전역 변수로 접근할 수 있으며 document는 window 객체의 프로퍼티로 존재 한다. 하지만 window 객체는 전역 객체 이므로 해당 프로퍼티에 접근할 때에는 window를 생략해도 된다.

 

getElementsByTagName()

  getElementsByTagName은 Document.getElemetById()와는 다르게 Document객체와 Element객체 양쪽의 메서드이다. getElementById()는 Document 객체에만 존재한다. 따라서 특정 Element 객체에 대해 getElementsByTagName()을 실행하면 해당 Element 객체의 자손 노드 가운데 특정 태그 명을 지닌 요소를 구한다.

  라이브 객체(또는 Live Collection)

    getElementsByTagName()을 사용 시 주의할 점이 있다. 이를 사용하면 NodeList객체가 구해 진다는 점이다. NodeList는 유사 배열, 즉 배열의 형태를 띄고 있지만 배열이 아닌 객체이다. 여기서 NodeList는 라이브 객체이며 라이브 객체는 DOM 트리에 대한 참조를 가지고 있기 때문에 DOM의 변경 사항을 실시간으로 반영 한다. Element.childNodes또한 라이브 객체를 반환 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="foo">
    <span>first</span>
    <span>second</span>
</div>
<script>
    const elems = document.getElementsByTagName('span');
    console.log(elems.length);//2
    const newSpan = document.createElement('span');
    newSpan.appendChild(document.createTextNode('third'));
    const foo = document.getElementById('foo');
    foo.appendChild(newSpan);
    console.log(elems.length);//3
</script>
cs

    라이브객체는 다음과 같이 반복문을 실행할 때 문제가 생긴다. 아래와 같이 코드를 작성하면 라이브 객체의 특성 때문에 무한루프를 돌게 된다.

1
2
3
4
5
6
7
const divs = document.getElementsByTagName('div');
let newDiv;
for(let i = 0; i < divs.length; i++) {
    newDiv = document.createElement('div');
    newDiv.appendChild(document.createTextNode('new div'));
    divs[i].appendChild(newDiv);
}
cs

      라이브 객체의 성능

       라이브 객체를 성능상으로 좋지 않다. 따라서 라이브 객체를 한번 slice()를 사용해 Array로 변환 후 사용하는 편이 성능상 뛰어 나다. 라이브 객체는 성능 면에서 문제가 있으므로 라이브러리에서는 Array로 변환하고 나서 반환하는 것도 있다

    NodeList외에도 HTMLCollection은 라이브 객체이다. DOM Level 1에 정의되 있는 HTMLCollection은 다음과 같다.

HTMLCollection 설명
document.images 문서 안의 img 요소 목록
document.apples 문서 안의 자바 애플릿 객체 목록
document.links 문서 안의 링크 요소(<a href>)목록
document.forms 문서 안의 form요소 목록
document.anchors 문서 안의 앵커 요소 (a 태그 안에 name 속성이 설정되 있는거) 목록
form.elements 폼 안에 input 요소 목록
map.areas 이미지 맵 안의 area목록
table.rows 테이블 안의 tr목록
table.tBodies 테이블 안의 tbody목록
tableSection.rows 테이블 세션(thead 요소, tfoot 요소)안의 tr 요소 목록
row.cells 테이블의 행 안의 td요소와 th요소 목록