by-nc-sa     개발자, DBA가 함께 만들어가는 구루비 지식창고!

DOM (Document Object Model) 이란?




DOM(Document Object Model)

DOM에 대한 의미(전부 같은 의미이다.)
1. 문서를 객체로 표현하기 위한 표준으로서 HTML이나 XML등의 문서를 객체로 표혀할 때 사용 하는 API 이다.
2. 문서의 객체 모델(Document Object Model)은 HTML내에 들어 있는 요소를 구조화 객체 모델로 표현 하는 양식
3. DOM은 HTML과 XML문서에 대하여, 이들 문서의 구조적인 표현방법을 제공하며 어떻게 하면 스크립트를 이용하여 이러한 구조에 접근할 수 있는지를 정의하는 API 이다.

고로 DOM은 프로그래밍 언어에 대하여 독립 적이다.

위 3가지중 이해가 잘 되는 말을 골라 사용 하면 된다.

XML문서의 DOM의 트리 구조

아래와 같은 형태의 XML 문서를 DOM 트리 구조로 살펴 보자

 <?xml version="1.0" encoding="euc-kr" ?>

<books>
  <book>
     <title>프로젝트 생존 전략</title>
     <author>스티브 맥코넬</author>
  </book>
  <book>
     <title>JSP 2.0 프로그래밍</title>
     <author>최범균</author>
  </book>
  <book>
     <title>웹 표준</title>
     <author>댄 씨더홈</author>
  </book>
</books>

위 XML문서에서 루트 태그는 <books>이고 <books>태그는 3개의 <book> 태그를 포함 하고 있다. <book>은 <title><author>태그를 가지고 있고 이러한 포함 관계를 DOM API 에서는 부모/자식 관계라 표현 한다.
위의 관계를 트리 구조로 표현 하면 아래과 같이 된다.

이 그림은 다음과 같이 해석 할수 있다.

  • DOM트리에서 문서 전체 = document
  • document 바로 밑( ex)<books> ) = root node
  • DOM API 에서는 node 사이에 있는 문자열 ( ex) <author>최범균</author> ) = Text node

HTML문서의 DOM의 트리 구조

이번에는 HTML 문서의 DOM 트리 구조를 살펴 보자

<html>
<head>
 <title>문서구조</title>
</head>
<body>
 <h1>제목</h1>
 <form></form>
</body>
</html>

위 코드를 DOM 트리 구조로 살펴 보면 다음과 같다.

이 그림을 살펴 보면 XML문서와 동일하다는것을 알수 있다.

  • DOM트리에서 문서 전체 = document
  • document 바로 밑( ex)<html> ) = root node
  • DOM API 에서는 node 사이에 있는 문자열 ( ex) <h1>제목</h1> ) = Text node
 if(document.someForm.id.value == "") {
   alert("아이디를 넣어요");
   return false;
 }

위 코드에서 사용된 document 가 HTML을 DOM트리로 변환했을 ?의 document 와 동일한 객체가 된다.

왜 계속 XML이야기가 나올까?
  • W3C DOM 에서는 HTML 문서를 XML로 바라본다. 즉 각 문서에 있는 태그들은 node(객체)가 있는 트리 구조로 해석해낼수있다고 가정하는 것이다. 각 태그들은 element noede(요소 노드) 와 text node(텍스트 노드)가 있다고 생각하며 각각의element node에 있는 속성 값들은 attirbute node로 인식한다.

DOM API를 통한 노드(객체) 접근 방법.

현재 널리 사용 되고 있는 DOM 표준안은 Level 2 이다. Level 3명세 역시 나와 있기는 하지만 적용 될라면 아직은 먼나라 이야기 인거 같다. Level 무엇이고 각 Level별로 접근방법을 간단히 알아 보고 넘어가자.(이런게 있었다 라고만 알아두어도 될거 같다)

  • Level 0 : DOM이 만들어 지기 이전의 모든 벤더 종속적인 DOM 포함
  • Level 1 : DOM 문서에 대한 탐색과 조정에 대한 최초의 표준 명세
  • Level 2 : XML 네임스페이스(Namespace) 지원, 필터링된 뷰(View)와 이벤트
  • Level 3 : 6가지의 다른 명세로 구성 (이건 솔찍히 잘 모르겠다)

아래와 같은 문서 구조를 두고 Level0 에서의 서로 다르게 접근 하는 브라우저의 방식을 보자.

넷스케이프 에서의 문서 내 노드(객체)들은 다음과 같이 접근 한다.

 document.images['theFirst'] // name이 있는경우
 document.images[0]
 document.images[1]
 document.forms['contactform'] // form이 있는경우
 document.forms[0].elements['address']
 document.forms[0].elements[0]

이번에는 좀더 업그레이된 방법으로 접근해 보자.

 <div id = "stuff"><img name = "testimage"></div>
 document.all.['stuff'].style.left = 200; // IE 표현
 document.all.stuff.style.left = 200; // IE 표현
 document.layers['stuff'].style.left = 200; // 넷스케이프 표현
 document.stuff.style.left = 200; // 넷스케이프 표현

위와 같이 DOM Level0 에서는 구현의 차이가 존재 하므로 Level 1 표준 스펙으로 작성을 하자
아래는 Level 1의 W3C DOM의 표준 스펙을 통한 접근 방법 이다.

 document.getElementById['stuff'].style.left = 200;

IE또한 W3C 표준 스펙을 지원 하기때문에 MSDOM을 사용 하지 말고 W3C DOM 을 사용 하여 웹표준을 지키도록 하자.

자주 사용하는 node의 프로퍼티 와 메소드

일단 지금 까지 사용한 용어의 구분을 분명히 하여야 한다. OOP개발을 했던 경우라면(혹은 하고 있는 경우라면) 별로 어렵지않게 용어의 사용에 공감하고 진행 할수 있겠지만 헷갈린다 라거나 감감 하다 할경우라면 분명히 용어를 구분 하고 진행하기를 바란다.

DOM API는 DOM 트리를 구성허가 위해 몇 가지 인터페이스를 사용하는데 주요 인터페이스 간의 관계는 다음과 같다.

처음에 설명한 바와 같이 DOM API 에서 모든건 node로 표현 되며 문서의 각 구성 요소들은 모두 node 또는 하위 인터페이스로 맵핑이 된다. 인터페이스들은 다음과 같이 매핑된다.

  • Document = 전체문서 (ex : document )
  • Element = 각각의 태그 (ex : books, book, title)
  • Text = 문자열 데이터(ex: <title>웹 표준</title> 에서 '웹표준')
  • CDataSection = XML 문서의 CDATA영역의 문자열

이 외에 그림에는 없지만 Element node에 있는 속성 값들, 예를 들면

<html>
<body>
 <p align = "right" > this is a <b id="dynatext">sparta</b></p>
</body>
</html> 

위 예제에서의 <p> element node 의 alignAttribute(속성) node 라고 해서 분류에 추가 할수 있겠다.

실은 아직 이부분이 제대로 정리가 안되었다.
  • 시간이 부족한 관계로(변명 같다... 누가 알고 있다면 리플좀 달아줘...) 영어로된 W3C 사이트를 제대로
    참조 하지 못했다.(영어 싫어.. ) Attribute node 또한 하나의 Element 로 구분 되서 Element node가
    되는 건지 아니면 Attribute node가 따로 존재 하는 건지 정확히 파악이 안된다. Attribute note 의 값에 해당하는 "right" 는 text node에 저장될거 같긴 하다만...

Node 인터페이스는 "Element,Text,Document"등 주요 인터페이스가 상속받는 부모 인터페이스로 DOM API의 기본이다
Node 인터페이스의 주요 프로퍼티를 살펴 보자

프로퍼티타입(Property type) 프로퍼티 이름(Property name) 설명(description)
String nodeName 현재 노드의 이름을 반환
String nodeValue 현재 노드의 값을 반환 한다. 노드 값이 텍스트 이면 텍스트를, 속성이면 속성값을 기타는 null 을 반환 한다.
unsigned short nodeType 현재 노드의 형식을 반환 한다. 예를 들어 1번은 element node, 2번은 attribute node, 3번은 text node, 4번은 CData, 5번은 참조 엔티티(참조엔티티가 모지? )
Node parentNode 현재 node의 상위 node를 반환
NodeList childNodes element(요소)내 모든 node를 배열로반환 즉 모든 자식node를 배열로 반환 하라는 의미
Node firstChild element(요소)내 첫 번째 node를 반환. 즉 가장 첫번째 자식node를 반환
Node lastChild element(요소)내 마지막 node를 반환. 즉 가장 마지막 자식node를 반환
Node previousSibling 현재 node와 같은 부모를 가지는 자식node중에 현재 node 이전의 자식 노드를 반환. 즉 현재 node 바로전 node를 반환
Node nextSibling 현재 node와 같은 부모를 가지는 자식node중에 현재 node 다음의 자식 노드를 반환. 즉 현재 node 바로 다음 node를 반환
Document ownerDocument 현재 node를 포함하고 있는 문서 객체를 반환 = 현재 노드가 포함된 Document 객체.

위의 표에서 childNodes 속성은 NodeList 즉 배열 형태를 리턴 한다. 배열의 형태를 예측해 보자

 var bookChildNodes = xxxbook.childNodes; 
 //bookChildNodes 는 아마 title,author을 가지고 있을 것이다.
 //bookChildNodes는 배열 형태(NodeList)를 가지므로 NodeList는 childNodes로 구한 자식 node에
 //접근 할수 있게 하기 위해 2가지를 제공한다.
 // 1. length - NodeList에 저장된 node의 개수 
 // 2. item(i)- 인덱스 i에 저장된 node를 구한다.(i=0 부터 시작) 
 //
 // 예를 들어 자식node에 차례 대로 접근 하는 코드를 작성해 본다면 다음과 같지 않을까?

 for( int i = 0; i < bookChildNodes.length; i++) {
   var childNode = bookChildNodes.item(i);
 }

Node 인터페이스의 주요 프로퍼티와 샘플을 간단히 보았으니 이번에는 Document 인터페이스의 주요 프로퍼티와 Method를보도록 하자.Document 는 Node 인터페이스를 상속하니 Node 인터페이스가 제공하는 프로퍼티와 Method를 제공하며
추가적으로 다음 프로퍼티 와 메소드를 제공한다.

프로퍼티/Method 타입 이름 설명(description)
Element documentElement 문서의 최상위 node를 반환 한다.
NodeList getElementByTagName(String tagname) 지정한 태그에 해당하는 모든 element node 배열을 반환 한다.
Element getElementById(String elementId) id 속성의 값이 elementId인 태그를 구하여 노드를 반환 한다.

각 프로퍼티와 메소드의 샘플 구현

<html>
<body>
<div id='a'>a</div>
<div id='b'>b</div>
<div id='c'>c</div>
</body>
</html>

에서 <div id='c'> 가 가진 텍스트 값을 읽어와 보자

//프로퍼티 많을 이용한 처리 

var htmlNode = document.documentElement;
var bodyNode = htmlNode.firstChild;
var lastDivNode = bodyNode.lastChild;
var textNode = lastDivNode.firstChild;
var strValue = textNode.nodeValue;

//위와 같이 하던지 아래와 같이 처리 

var textNode = document.documentElement.firstChild.lastChild.firstChild;
var strValue = textNode.nodeValue;
// 일정한 규칙을 가진 태그들을 한꺼번에 처리해야 할경우

 var spanList = document.getElementByTagName("span");

 for( var i = 0; i< spanList.length; i++) {
   var span = spanList.item(i);
   ...
 }

이번에는 Element 인터페이스의 주요 프로퍼티 와 Method를 보자

프로퍼티/Method 타입 이름 설명(description)
String tagName 태그의 이름 반환
String getAttribute(String name) name에 해 해당하는 속성 값을 반환, 오페라에서 버그
  setAttribute(String name, String value) name인 속성의 값을 value로 지정, IE 버그
  removeAttribite(String name) name인 속성의 값을 제거
 <book id="book1" isbn="88910010" category="jsp">
  ...
 </book>

book 태그의 속성을 읽어 오기

  var bookNode = document.getElementById("book1");
  bookNode.getAttribute("isbn");
  bookNode.setAttribute("categoru","jsp.web");  //attribute node 가 존재 하니까 업데이트가 일어난다.
  bookNode.setAttribute("productId","8890192"); //attribute node 가 없어서 새로운 속성이 추가 된다.

참고로 Element 인터페이스 또한 Document 인터페이스에 정의된 getElementByTagName() 함수가 제공된다. 차이가 있다면 Element의 경우에는 해당 하위 노드 들에 대해서만 검색 한다.

HTML 과 XML에서의 차이
  • node 타입이 Element 인 경우 nodeName의 값은 태그의 이름과 같이 동일하다. XML문서를 DOM트리로 변경 할 경우에는 태그의 이름이 그대로 오지만 HTML 문서를 DOM 트리로 표현한 경우에는 차이가 있다. 보통 웹 브라우저들은 HTML 문서를 DOM트리로 변환할? 태그의 이름을 *대문자*로 변경 한다. 즉 태그의 이름을 '<div>...</div>' 와 같이 태그를 소문자로 표시했어도 웹 브라우저는 DOM트리로 생성할 ? 태그의 이름을 'div'로 저장하며 따라서 nodeName에 저장되는 값은 'DIV'가 된다.

다음은 참고자료로 사용한다. Node에 정의된 nodeType별 상수 값이다.(nodeType은 위 표에 기술한대로 unsigned short 형의 반환 타입을 가지고 있다)

상수명 의 미
ELEMENR_NODE 1 Element node를 의미
ATTRIBUTE_NODE 2 안써도 알듯..
TEXT_NODE 3 안써도 알듯..
CDATA_SECTION_NODE 4 안써도 알듯..
ENTITY_REPERENCE_NODE 5 안써도 알듯..
ENTITY_NODE 6 안써도 알듯..
PROCESSING_INSTRUCTION_NODE 7 안써도 알듯..
COMMENT_NODE 8 안써도 알듯..
DOCUMENT_NODE 9 안써도 알듯..
DOCUMENT_TYPE_NODE 10 안써도 알듯..
DOCUMENT_FRAGMENT_NODE 11 안써도 알듯..
NOTATION_NODE 12 안써도 알듯..

위의 코드를 기초로한 샘플 코드를 살펴 보자

 var childNodeList = xxxx.childNodes; // xxxx는 node를 의미 한다. :D
 for(var i = 0; i < childNodeList.length; i ++) {
   var child = childNodeList.item(i);
   if(child.nodeType == 2) {
     // child 가 attribute 인경우 에만 처리 
      ...
   }
 }

이제는 우리가 자주 사용하는 innerHtml의 기능을 대신해서 쓸 DOMAPI를 보자. 이것을 이용하여 HTML이나 XML의 문서구조를 변경하여 보자. (알고 있겠지만 innerHtml은 표준이 아니다...하지만 가장 빠르다. 스크립트야 어차피 사용자 PC의 처리능력으로 감당 하는 거니 상관 이야 업지만.. 분명히 말하건데 W3CDOM과 innerHTML의 성능 차이는 어떤 브라우저를 사용하건 간에 최소 3배 이상 차이가 난다. 게다가 DOM API는 귀찮어..(한국소프트웨어 진흥원 참조))

프로퍼티/Method 타입 이름 설명(description)
Element createElement(String tagName) 매개변수로 넘겨주 태그이름을 가진 Element node를 생성
Text createTextNode(String text) 매개변수로 넘겨준 text값을 가진 Text node를 생성한다.
Node insertBefore(Node newChild, Node refChild) 현재 node의 자식 node인 refChild node의 previous Sibling 자리에 newChild 노드를 삽입한다.
Node replaceChild(Node newChild, Node oldChild) 현재 node의 자식 node인 oldChild node를 새로운newChild로 교체한다.
Node removedChild(Node oldChild) 현재 node의 자식 node인 oldChild를 현재 node에서 제거 한다.
Node appendChild(Node newChild) newChild 노드를 현제 노드의 작식 node로추가한다.

샘플 코드는 각자 만들어 보기 바란다.
-DOM Level 1, 2- DOM Level 2(CSS는 DOM Level2에서 발표 하였다고 한다.)에서는 거의 모든 HTML/CSS 객체의 속성을 이용할수 있다. x를 객체라고 한다면 x.className이나 x.id x.title x.style(스타일 설정등) 등오로 속성을 읽고 쓸수 있다.

이제 DOM의 큰 특징중 하나인 Event 처리에 대한 부분이 남았는데 이부분은 조금씩 알아가 보도록 합시당.

문서에 대하여

  • 문서참고
    • 1. 한국소프트웨어진흥원에서 만든 실전 웹 표준 가이드
    • 2. Foundations of AJAX
    • 3. 최범균의 AJAX 프로그래밍
    • 4. AJAX in 액션
    • 5. AJAX in 프랙틱스
  • 최초작성자 : [허용운]
  • 최초작성일 : 2007년 12월 19일

문서정보

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.