LHJ

I'm a FE developer.

18.2. 문서 객체 모델

01 Jun 2020 » js_lj

18.2. 문서 객체 모델

DOM, 즉 문서 객체 모델은 HTML 문서의 구조를 나타내는 표기법인 동시에 브라우저가 HTML 문서를 조작하는 핵심이기도 합니다.

DOM은 트리 구조로 표현합니다.
DOM 트리는 노드(node)로 구성됩니다.
루트 노드를 제외하면 모든 노드에 부모가 있으며, 자식 노드는 있어도 되고 없어도 됩니다.
루트 노드는 문서(document)이며 자식 노드는 <html> 요소 하나뿐입니다.
<html> 요소에는 자식으로 <head> 요소와 <body> 요소가 있습니다.
[그림 18-1]은 DOM 예제입니다.

DOM 트리의 모든 노드는 Node 클래스의 인스턴스입니다(다음 장의 주제인 노드.js와 헷갈리지 마십시오).
Node 객체에는 트리 구조를 나타내는 parentNodechildNodes 프로퍼티, 자신에 대한 프로퍼티인 nodeNamenodeType 프로퍼티가 있습니다.

NOTE_
DOM은 노드로만 구성됩니다.
하지만 모든 노드가 HTML 요소는 아닙니다.
예를 들어 문단 태그(<p>)는 HTML 요소지만, 그 문단에 포함된 텍스트는 텍스트 노드입니다.
노드와 요소 용어를 섞어 써서 문제가 되는 경우는 거의 없지만, 정확히 말하면 다른 개념입니다.
이 장에서 말하는 노드는 거의 HTML 요소이고, ‘요소’라고 하면 그건 ‘요소 노드’를 가리키는 겁니다.

예제에 사용할 단순 HTML 파일을 하나 만듭시다.
다음과 같이 simple.html 파일을 만드십시오.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Simple HTML</title>
<style>
.callout {
    border: 1px solid #ff0080;
    margin: 2px 4px;
    padding: 2px 6px;
}
.code {
    background: #ccc;
    margin: 1px 2px;
    padding: 1px 4px;
    font-family: monospace;
}
</style>
</head>
<body>
<header>
    <h1>Simple HTML</h1>
</header>
<div id="content">
<p>This is a <i>simple</i> HTML file.</p>
<div class="callout">
    <p>This is as fancy as we'll get!</p>
</div>
<p>IDs (such as <span class="code">#content</span>) are unique (there can only be one per page).</p>
<p>Classes (such as <span class="code">.callout</span>) can be used on many elements.</p>
<div id="callout2" class="collout fancy">
    <p>A single HTML element can have multiple classes.</p>
</div>
</div>
</body>
</html>

모든 노드에는 nodeType, nodeName 프로퍼티가 있습니다.
nodeType은 그 노드가 어떤 타입인지 나타내는 정수입니다.
이 장에서는 HTML 요소인 Node.ELEMENT_NODE(node Type 1)과 보통 HTML 요소의 텍스트 콘텐츠로 쓰이는 Node.TEXT_NODE(nodeType 3)을 주로 설명합니다.
더 많은 정보가 궁금하다면 nodeType에 대한 MDN 문서를 보십시오.

document에서 시작해 DOM 전체를 순회(traverse)하면서 콘솔에 출력하는 함수를 만들어 봅시다.

function printDOM(node, prefix) {
    console.log(prefix + node.nodeName);
    for (let i=0; i<node.childNodes.length; i++) {
        printDOM(node.childNodes[i], prefix + '\t');
    }
}
printDOM(document, '');

재귀 함수깊이 우선, 전위 순회(depth-first, pre-order traversal)라고 부르는 방법을 사용해 트리를 순회합니다.
어렵게 들리지만, 쉽게 말해 다음 가지로 넘어가기 전에 이 가지를 다 순회한다는 뜻입니다.
브라우저에서 웹 페이지를 불러온 상태에서 이 함수를 실행하면 전체 페이지 구조가 콘솔에 출력됩니다.

연습 삼아 순회 함수를 만들어 봤지만, HTML을 조작하려 할 때마다 이런 함수를 써서 DOM을 이동해야 한다면 너무 지루하고 비효율적일 겁니다.
다행히 DOM에는 원하는 HTML 요소를 바로 찾는 메서드가 있습니다.

TIP_
연습삼아 순회 함수를 직접 만들어 보는 것도 좋겠지만, DOM API에서 제공하는 TreeWalker 객체를 활용하는 것이 좋습니다.
이 객체를 사용해 DOM 요소 전체를 순회할 수 있고, 원하는 타입의 요소만 필터링할 수도 있습니다.
더 자세한 내용은 document.createTreeWalker에 관한 MDN 문서를 보십시오.

https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker