8. DOM(Document Object Model)
기본적으로 웹문서는 HTML과 XML과 같은 마크업 언어로 작성된 문서로 익스플로러나 Firefox 같은 웹 브라우저는 이렇게 HTML이나 XML 같은 마크업 언어로 작성된 문서들을 여러분이 쉽게 이해할 수 있도록 바꾸는 작업을 수행합니다. 그래서 여러분들을 이러한 브라우저를 통해 문자열에서부터 그림, 테이블
등을 볼 수 있게 되는 것입니다.
그리고 이러한 해석 과정에서 HTML 페이지를 하나의 트리(Tree) 형태의 모델로 저장하는데 이를 DOM(Document Object
Model)이라고 합니다.
DOM은 HTML 문서를 하나의 트리(Tree) 형태로
나타낼 수 있는데 트리는 노드(node)들로 구성됩니다. 여기서
노드(node)란 DOM 트리에 존재하는 요소(Element), 속성(Attribute), 텍스트(Text), HTML 문서 전체를 나타내는 Document 등을 노드라고
합니다.
DOM이라는 개념이 접근하기에 따라서 어려울 수도 있는데 여기서 설명하는 대로 잘 따라 오시면 그리 어렵지 않게 DOM의 개념을 이해할 수 있을 것입니다. 그리고 이 개념은 XML의 DOM을 이해하는데 거의 그대로 적용되는데 이에 대한 부분은
인터넷에서 검색을 통한 자료나 제 2 번째 책 “예제로 배우는 XML & LINQ 완벽가이드”를 참고하시면 좋을 것 같습니다.
이해를 돕기 위해서 예를 들어 다음과 같은 HTML 문서가 있다고 가정합니다.
<!DOCTYPE
HTML>
<html>
<head>
<title>Node 이해하기</title>
<script type="text/javascript">
</script>
</head>
<body>
<h1>Node에 대하여</h1>
<p>Node는
HTML의 요소(Element), 속성(Attribute)
등을 나타냅니다.</p>
</body>
</html>
위의 문서를 “NodeEx.html”로 저장하고 IE9를
통해 열어보면 다음과 같이 나타납니다.
이제 이 HTML 문서를 DOM 트리(Tree)
형태로 나타내면 다음과 같습니다.
위의 그림에서
보는 것처럼 루트 노드(root node)는 html 요소가
되고 이 루트 노드의 자식 노드로 첫 번째 자식(child) 노드는
head 요소, 두 번째 자식 노드는 body 요소가
됩니다. 그리고 head 요소와 body 요소를 나타내는 노드들은 서로 형제지간(sibling)입니다.
다음으로 head 요소를 나타내는 노드의 첫 번째 자식 노드는 title 요소이고 두 번째 자식 노드는 script 요소입니다. 역시 title, script 요소를 나타내는 노드들은 서로 형제지간(sibling)입니다.
마지막으로 body 요소를 나타내는 노드의 첫 번째 자식 노드는 h1 요소이고 두번째 자식 노드는 p 요소이며 마찬가지로 h1 요소와 p 요소는 서로 형제지간(sibling)입니다.
8.1 Node의 주요 속성
JavaScript를 이용하여 HTML DOM을 다루는데 있어 노드(node)와 관련된 주요 속성들을
나타내면 다음과 같습니다.
속성 |
설명 |
nodeName |
노드의 이름 |
nodeType |
노드의 타입을 나타내며 읽기 전용입니다. |
nodeValue |
노드의 값을 나타냄. 일반적으로 해당 요소(Element) 값을 의미 |
parentNode |
현재 노드의 부모 노드를 반환 |
firstChild |
첫 번째 자식 노드 반환 |
lastChild |
마지막 자식 노드 반환 |
previousSibling |
바로 앞 형제 노드 반환 |
nextSibling |
다음 형제 노드 반환 |
childNodes |
자식 노드들을 반환 |
textContent |
노드나 자식 노드의 Text 값을 가져오거나 설정할 때 사용 |
innerText |
노드의 Text 값을 가져오거나 설정할 때 사용 |
innerHTML |
요소(Element)의 내용(content)나 Text 값을 가져오거나 설정할 때 사용 |
표에서
소개한 속성들을 이해하기 위해서 예제를 해볼까요? 이제 “NodeEx.html”에서 <script> … </script> 블록 내에 다음과 같이 코드를 작성합니다.
<script
type="text/javascript">
var documentNodes =
document.documentElement; //HTML --①
document.write(documentNodes.nodeName +"<br />");
var htmlfirstChild =
document.documentElement.firstChild; //첫
번째 자식노드 --②
document.write(htmlfirstChild.nodeName+"<br/>");
var htmlnextSibling =
document.documentElement.firstChild.nextSibling; // --③
document.write(htmlnextSibling.nodeName+"<br/>");
var htmllastChild = document.documentElement.lastChild;
//마지막 자식노드 --④
document.write(htmllastChild.nodeName+"<br/>");
var htmlchildNodes =
document.documentElement.childNodes;
//--⑤
for (var i = 0, l = htmlchildNodes.length; i < l; i++) {
document.write(htmlchildNodes[i].nodeName+"<br/>");
}</script>
①에서 document 객체는 window 객체(object)의 한 속성으로 DOM 트리(Tree)의 루트(root)를
나타내며 document 객체의 속성 중 documentElement
속성은 html 요소를 나타냅니다. 참고로
body 속성은 body 요소를 나타냅니다.
②에서는 firstChild 속성을 이용하여 루트 노드의
첫 번째 자식 노드에 접근할 수 있으며 ③에서는 첫 번째 자식 노드 다음에 오는 노드에 접근하기 위해서 nextSibling 속성을 사용했습니다. ④에서는 lastChild 속성을 이용하여
루트 노드의 마지막 자식 노드에 접근하는데 결과에서 보게 되면 알겠지만 루트 노드(html)에는 2개의 자식 노드만 존재하므로 ③, ④의 결과가 동일하게 나타나게 됩니다.
마지막으로 ⑤에서는 childNodes
속성을 이용하여 루트 노드의 모든 자식 노드들을 받아서 for문을
이용하여 자식 노드의 수(length)만큼 반복하여 노드이름을 나타내도록 합니다.
위와 같이 코드를 추가한 후 저장하고 IE9를 통해서 보면 다음과 같이 나타납니다.
8.2 Node의 주요 메서드를 이용한 추가, 수정, 삭제
여러분들은 HTML 요소들을 각각 Node의 관점에서 보고 다음과 같은 Node의 주요 메서드를 이용하여 새로운 노드, 즉 새로운 요소(Element)를 추가, 수정, 삭제할 수 있습니다.
메서드 |
설명 |
insertBefore() |
특정 자식노드
앞에 새로운 노드를 추가하거나 맨 마지막 자식 노드 |
appendChild() |
기존 자식 노드의 다음에 새로운 newNode를 추가 |
replaceChild() |
기존 oldNode를 newNode로 교체 |
removeChild() |
자식 노드를 삭제 |
hasChildNodes() |
노드가 자식 노드를 가지고 있으면 true, 없으면 false 반환 |
hasAttributes() |
요소 노드가 속성노드를 가지고 있으면 true, 없으면 false 반환 |
8.2.1 insertBefore(), appendChild() 메서드를 이용한
노드 추가
insertBefore(), appendChild() 메서드는 대한 형식은 다음과 같이 정의하여 사용하게 됩니다.
insertBefore(newNode
[, childNode])
appendChild(newNode)
먼저 insertBefore() 메서드는 위 형식에서 보는 것처럼 입력 파라미터로
newNode, childNode 모두 정의될 경우는 childNode 앞에 newNode 추가합니다만 입력 파라미터로 childNode가 입력되지
않을 경우 맨 마지막 자식 노드 다음에 newNode가 추가됩니다.
다음으로 appendChild() 메서드는 기존 자식 노드의 다음에 새로운 newNode를 추가합니다.
이제 두 메서드의 사용 방법을 예제를 통해 알아보기 위해 메모장을 열어서 다음과 같이 작성합니다.
<!DOCTYPE
HTML>
<html>
<head>
<title>insertBefore() 메서드 예제</title>
</head>
<body>
<ul id="oulFruits">
<li id="oliApple">사과</li>
<li
id="olistrawberry">딸기</li>
<li id="oliGrape">포도</li>
</ul>
<script type=”text/javascript”>
</script>
</body>
</html>
위와 같이 작성한 후 “insertBeforeMethod.html”로 저장한 후 IE9를 통해 보면 다음과 같이 리스트 항목(list item)을
나타냅니다.
이제 위 결과에서
“딸기” 항목 위에 “수박” 항목을 insertBefore() 메서드를 이용하여 추가해볼까요?
“딸기” 항목 위에 “수박” 항목을 추가하기 위해서는 부모 노드인 ul 노드에 insertBefore() 메서드를 적용하면 됩니다. 그래서 위 코드에서 <script>… </script> 코드 블록에 다음과 같이 코드를 추가합니다.
<script
type="text/javascript">
var newNode =
document.createElement("li");
newNode.innerText="수박";
//newNode.textContent=”수박”;
var retul =
document.getElementById("oulFruits");
retul.insertBefore(newNode,
olistrawberry);
</script>
위에서 새로운
노드를 생성하는데 있어서 createElement() 메서드를 이용했는데 이 createElement() 메서드는
document.createElement(“생성할 요소이름”) 형태로 새로운 요소 노드(Element Node)를 생성할 수 있습니다.
그리고 createElement() 메서드를 이용하여 생성된 li 요소 노드에 innerText 속성을 이용하여 해당 노드의 Text 값을 설정합니다. 물론 위 코드에서 주석처리된 대로 textContent 속성을 이용해서도 노드의 Text 값을 설정할
수 있습니다.
다음으로 getElementById() 메서드를 이용하여
id 속성값이 “oulFruits”인 ul 을
검색하고 검색된 ul 노드에 insertBefore() 메서드를
이용하여 생성한 li 요소 노드를 추가할 수 있습니다. 저장하고 IE9를 통해 확인하면 다음과 같이 원하는 위치에 노드가 추가되어 나타납니다.
만일 위의 insertBefore() 메서드를 “retul.insertBefore(newNode);”
형태로 사용하면 어떤 결과가 나올까요? Text값이 “수박”인 li 노드는 Text값이
“포도”인 li 노드
다음에 추가되어 나타납니다. 이는 appendChild() 메서드를
이용하여 추가하는 결과와 동일합니다.
위 코드에서 “// retul.insertBefore(newNode, olistrawberry);”와
같이 주석처리하고 그 밑에 다음과 같이 한 줄을 추가합니다.
retul.appendChild(newNode);
저장하고 IE9를 통해 확인하면 다음과 같이 “수박” 노드가 맨 마지막에 나타나게 됩니다.
- 본 저작물은 본인이 2011년 상반기부터 2012년 여름 즈음까지 도서 출판을 목적으로 약 470 페이지(A4, 폰트 10)으로 작성한 원본 중 JavaScript에 대한 부분을 그대로를 공개하는 것으로 본 저작물에 대한 모든 권리는 본인(원철연)에서 있음을 알립니다.
개인적인
학습 목적으로 사용을 허용하며 온오프라인의 베포나 펌, 상업적인 용도의 사용은 삼가해주시기
바랍니다. 끝으로 학교나 비영리 단체에서의 경우 본 저작물을 비상업적인 용도로 활용하고자 할 경우 연락처를
비밀댓글로 남겨주시면 연락드리겠습니다.
'제가 쓴 책 > HTML5, CSS3 and JavaScript' 카테고리의 다른 글
8.2.3 removeChild() 메서드를 이용한 노드의 삭제 (0) | 2013.08.06 |
---|---|
8.2.2 replaceChild() 메서드를 이용한 기존 노드의 교체 (0) | 2013.08.06 |
7.2 Event Method를 이용한 이벤트 처리 (0) | 2013.08.06 |
7.1.4 폼(Form)과 관련된 이벤트 핸들러 속성 (0) | 2013.08.06 |
7.1.3 키보드(Keyboard)와 관련된 이벤트 핸들러 속성 (0) | 2013.08.06 |