JS DOM( Document Object Model ): 문서 객체 모델

DOM: 문서 객체 모델

출처 - https://www.w3schools.com/js/js_htmldom_navigation.asp

문서 객체 모델(DOM)은 HTML 문서 구조를 말합니다.

HTML 문서의 구조에서 최상위 객체로는 <html>이 있으며, 그 하위 객체로는 <head>와 <body>가 있습니다.

 

모든 HTML 태그는 객체 또는 노드라 합니다. Document는 document 노드라 하고 태그들도 모두 노드입니다. HTML 태그 내의 텍스트 역시 텍스트 노드라 하고 주석도 주석 노드라 합니다. 위 그림 처럼 노드들은 트리 구조를 구성기 때문에 <html> 태그를 루트 노드가 되고, <head>태그와 <body>태그는 루트 노드의 자식 노드가 됩니다.

 

이 같은 노드들은 모두 JS를 통해 접근할 수 있고 조작할 수 있습니다. 예를 들어 <body> 태그는  document.body로 접근할 수 있고 텍스트 노드는 innerHTML속성으로 접근할 수 있습니다.

 


DOM 노드 탐색하기

노드에 접근하기 위해서는 무조건 document 객체에서 시작합니다. 위 그림으로 바로 이해할 수 있듯이 document 노드는 DOM에 접근하기 위한 진입점이기 때문입니다. 

 

 

트리 상단 노드 탐색

트리 상단의 , , 는 다음과 같이 접근할 수 있습니다.

  • <html> - document.documentElement
  • <head> - document.head
  • <body> - document.body

 

 

노드 간 탐색

자식 노드: 바로 아래의 자식 노드 입니다.

후손 노드: 자식노드와 자식 노드의 모든 자식 노드들 입니다.

  • parentNode - 부모 요소 노드
  • childNodes[nodenumber] - 모든 자식 노드를 담고 있습니다.
  • firstChild - 첫 번째 자식 요소 노드, childNodes[0]과 같습니다.
  • lastChild - 마지막 자식 요소 노드, childNodes[element.childNodes.length - 1]과 같습니다.
  • nextSibling - 다음 형제 노드
  • previousSibling - 이전 형제 노드

 

childNodes은 Iterable한 컬렉션입니다. 때문에 다음과 같은 특징을 가집니다.

컬렉션이지 배열이 아님은 주의!!

     
      // Iterable하기 때문에 for..of 사용 가능
      for (let node of document.body.childNodes) {
        console.log(node);
      }

      // 컬렉션이기 때문에 배열로 변환 가능
      Array.from(document.body.childNodes);
 

 

 

아래 세 개는 같은 노드에 접근합니다.


      <title id="demo">TEXT NODE</title>;

      document.getElementById("demo").innerHTML;

      document.getElementById("demo").firstChild.nodeValue;

      document.getElementById("demo").childNodes[0].nodeValue;
 

 

 

HTML 요소

HTML 요소 찾기

document.getElementById() id를 통해 요소 찾기
document.getElementsByTagName() 태그 이름 통해 요소 찾기
document.getElementsByClassName() 클래스 이름 통해 요소 찾기
document.querySelector() 파라미터로 입력받는 CCS 선택자로 찾은 요소들 중 첫 번째 요소 반환
document.querySelectorAll() 파라미터로 입력받은 요소들을 찾아 NodeList로 반환

 

HTML 요소 변경

element.innerHTML = content   inner HTML content 변경
element.attribute = value HTML 요소의 value 변경
element.style.property = style HTML 요소의 style 변경

 

요소 추가 및 삭제

document.createElement(element) HTML 요소 생성
document.removeChild(element) HTML 요소 삭제

child.parentNode.removeChild(child) 형식으로 노드를 삭제해주어야 합니다. 
document.appendChild(element) HTML 요소 추가 
document.replaceChild(new, old) HTML 요소 old에서 new로 대체
document.write(text) Write into the HTML output stream

예시

  1. document.createElement()를  통해 HTML 요소를 생성(예. <h1>, <button> 등)
  2. element.innerHTML 또는 document.createTextNode()를 통해 텍스트 입력
  3. document.appendChild()를 통해 생성하고 텍스트를 작성한 HTML 요소를 추가

appendChild()로 새 요소를 추가하면 마지막 노드에 추가됩니다. 만약 노드의 위치를 바꿔 삽입하고 싶으면 다음 방법을 사용하면 됩니다.

id가 div1인 요소의 자식 노드 중 id가 p1인 자식 노드 전에 삽입하는 예제입니다.


      const element = document.getElementById("div1");
      const child = document.getElementById("p1");
      element.insertBefore(para, child);
     

 

 

노드 속성 접근

노드의 이름: nodeName

  • 요소 노드인 경우: 태그 이름
  • 속성 노드인 경우: 속성 이름
  • 텍스트 노드인 경우: #text
  • 문서 노드인 경우: #document
  • 읽기 전용이기 때문에 수정이 불가능합니다.

 

노드의 값: nodeValue

  • 요소 노드인 경우: null
  • 텍스트 노드인 경우: 텍스트 값
  • 속성 노드인 경우: 속성 값 

 

노드 유형: nodeType

노드의 유형을 반환합니다. 읽기 전용입니다.

  • 요소노드: 1
  • 속성노드: 2
  • 텍스트노드: 3
  • 주석노드: 8
  • 문서노드: 9
  • 문서타입노드: 10 (ex:<!Doctype html>)

 


DOM Collections

getElementsByTagName()은 HTML Collection을 반환합니다.

     
      const myCollection = document.getElementsByTagName("div");
 
      myCollection[1];

 

DOM NodeList

  • 문서에서 추출된 노드의 리스트입니다.
  • HTMLCollection과 거의 유사합니다.
  • childNodes과 querySelectorAll()는 NodeList를 반환합니다.
  • 인덱스로 배열처럼 접근할 수도 있고, myNodeList.length를 통해 길이도 구할 수 있습니다. 하지만 이 역시 배열은 아님을 주의!!

 

 

HTMLCollection VS NodeList

공통점

HTMLCollections과 NodeList는 거의 같다고봐도 됩니다. 둘 다 문서에서 추출한 노드(요소) 컬렉션이고, 배열은 아니지만 배열처럼 인덱스 접근이 가능하고 length를 통해 길이를 구할 수 있습니다.

 

차이점

  • HTMLCollection
    • 동적이기 때문에 DOM에 새로운 요소가 추가되면 HTMLCollection은 바로 새로운 요소를 가져온다
    • HTMLCollection 객체는 <div>, <p> 등과 같은 요소 노드만 포함합니다.
    • 자식노드에 접근할 때 id, name, 인덱스를 통해 자식 노드에 접근합니다.
    • 반복문을 돌때 유사 배열 객체이기 때문에 for..of 문을 사용하여 접근합니다.
    • getElementByTagName(), getElementByClassName()
  • NodeList
    • 정적이기 때문에 DOM에 새로운 요소가 추가되면 요소를 가져오지 못합니다.
    • NodeList 객체는 요소 노드, 속성 노드, 텍스트 노드 등을 포함합니다.
    • 자식노드에 접근할 때 id, name으로 자식 노드에 접근할 수 없고 인덱스로만 접근 가능합니다.
      namedItem() 메서드를 갖고 있지 않기 때문입니다.
    • 반복문을 돌때 forEach() 메서드를 사용하여 접근합니다.
    • getElementByName(), querySelectorAll()