[20231226 TIL] DOM / DOM Tree / DOM Node / DOM Drilling / DOM API

Haizel·2023년 12월 26일
2
post-thumbnail

01. DOM에 대해


✴︎ DOM

DOM(Document Object Model, 문서 객체 모델) : HTML, XML 문서의 Programming-interface로, HTML과 Javascript가 상호작용할 수 있도록 하는 도구를 말한다.

DOM은 문서의 구조화된 표현(Structured representation)을 제공하고, Javascript와 같은 프로그래밍 언어가 DOM 구조에 접근할 수 있는 방법을 제공한다.

이를 돕는 것이 DOM API로, DOM 구조의 문서구조나, 스타일, 텍스트 내용 등을 변경할 수 있도록 돕는 역할을 한다.


✴︎ DOM Tree

DOM Tree는 HTML 문서의 태그(tag)를 노드의 계층 구조 트리로 표현한 것으로, 쉽게 말하면, HTML문서를 Node 구조의 tree 형태로 표시한 것을 말한다.

때문에 DOM구조는 Node Tree라고 부르기도 하며, console.dir로 DOM에 있는 노드를 탐색할 수 있다.

💡 HTML → DOM Tree Parsing


✴︎ DOM Node

Node(노드) : 노드는 추상 클래스로, 객체의 속성이다. 트리 주료구조에서는 트리를 구성하고 있는 객체 하나를 노드(Node)라고 한다.

• Document Node (문서 노드)

: DOM Tree의 최상위 계층이면서 전체 문서를 가르키는 Document 객체이다.

document로 참조할 수 있으며, DOM Tree로 웹 페이지를 접근하는 시작점이다.

• Element Node (요소, 태그 노드)

: HTML 태그에 해당 하는 노드로, 요소 노드는 속성 노드와 택스트 노트를 자식으로 가질 수 있다.

• Attribute Node (속성 노드)

: 모든 HTML 요소의 속성은 속성 노드이며, 요소 노드에 관한 정보를 가지고 있다.

• Text Node (택스트 노드)

: HTML 문서의 모든 택스트는 택스트 노드로, 개행(줄바꿈), 공백과 같이 눈에 명시적으로 보이지 않는 요소가 바로 text node이다.

※ 각 요소 노드 사이에는 /n 과 같은 텍스트 노드가 존재한다.

• Comment Node (주석 노드)

: HTML 문서의 모든 주석 노드


✴︎ DOM Tree 자료 구조

Property(프로퍼티) : object(객체)의 속성을 의미하며, 프로퍼티는 key-value의 한 쌍으로 표현된다.

• Root Node (루트 노드)

노드 트리의 가장 상위에 위치하며, 루트 노드는 트리에서 단 하나만 존재한다.

• Parent Node (부모 노드)

루트 노드를 제외한 모든 노드는 단 하나의 부모 노드만을 가지며, 부모 노드는 여러개의 자식 요소를 가질 수 있다.

• Child Node (자식 노드)

모든 요소 노드는 자식 노드를 가질 수 있으며, 자식 노드는 단 하나의 부모 노드를 가진다.

• Sibling Node (형제 노드)

같은 부모 노드를 가지는 모든 노드는 형제 노드로, 같은 트리 레벨(tree level)에 존재하는 요소를 가리킨다.

• Ancestor Node (조상 노드)

부모 노드를 포함해 계층적으로 현재 노드보다 상위에 존재하는 노드를 기리킨다.

• Descendant Node (자손 노드)

자식 노드를 포함해 계층적으로 현재 노드보다 하위에 존재하는 모든 노드를 가리킨다.


✴︎ DOM Node 객체의 Property(프로퍼티)

Node 객체의 프로퍼티를 이용해 조상, 부모, 자식, 형제 노드에 접근 할 수 있다.

• parentNode

기준 노드의 부모 노드를 참조하며, 만약 기준 노드가 Document 객체일 경우 부모 노드가 없으므로 parentNode는 null이 된다.

• childNode

기준 노드의 자식 노드의 참조가 저장된 유사 배열을 참조한다. 이때 유사 배열은 NodeList 형태이다.

• firstChild / lastChild

기준 노드의 첫 번째 자식, 마지막 자식 노드를 참조하며, 자식 노드가 없는 경우 null이 된다.

• nextSibling / previousSibling

기준 노드와 같은 부모를 가진 다음 형제 노드 또는 이전 형레 노드를 참조한다.

• nodeType

노드 유형을 뜻하는 숫자를 참조한다.
(요소 노드 : 1 / 택스트 노드 : 3 / document : 9)

• nodeValue

택스트 노드일 경우, 택스트 콘텐츠를, 요소 노드일 경우엔 null을 반환한다.


✴︎ HTML 요소의 트리

Node 객체의 프로퍼티는 택스트 노드를 포함하고 있다. 때문에 DOM 트리 안의 택스느 노드는 무시하고, HTML 요소의 계층 구조만 가져오는 프로퍼티를 활용하는 방법도 있다.

• childNodes

기준 노드의 자식 요소 참조를 저장한 유사 배열 객체(NodeList)이다.

• parentElement

기준 노드의 부모 요소 객체를 참조(택스트 노드는 제외)

• firstElementChild / lastElementChild

기준 노드의 첫 번째 자식 요소, 마지막 자식 요소 객체 참조(택스트 노드, 공백 노드 모두 제외)

• nextElementSibling / previousElementSibling

기준 노드와 같은 부모를 가진 다음 형제 노드 객체 / 이전 형제 노드 객체 밴환

• childElementCount

기준 노도의 자식 요소 개수를 반환 (= children.length)


✴︎ DOM Node의 Prototype(프로토타입)

Javascript의 거의 모든 객체는 Object의 인스턴스로, Object.prototype에서 속성과 메서드를 상속 또는 재정의할 수 있다.

따라서 DOM에서 모든 객체들은 클래스(프로토타입)을 상속받는다.

👉 img 태그의 프로토타입을 살펴보자

차례대로 Element Node(HTML Tag) HTMLelementElement HTMLElement Element Node EventTarget Object


✴︎ DOM drilling

drill에서 알 수 있듯이, 기존 HTML 요소에 접근하여 요소의 속성이나 text 등 DOM 객체의 속성(firstElementChild 등)을 통해 DOM을 탐색하는 작업을 DOM Drilling이라고 한다.

👀 DOM drilling 예제

• HTML

script 파일은 비동기적으로 로드할 수 있도록 defer 속성을 추가한다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Advanced javascript</title>
    <script src="app.js" defer></script>
  </head>
  <body>
    <h1>hi!</h1>
    <p>
      this is a
      <a href="#">link</a> // ✔️
    </p>
  </body>
</html>

• JavaSCript (DOM drilling)

✔️ 체크 된 anchor 태그의 href 속성의 주소값을 변경한다.

document.body.children[1].children[0].href = 'https://google.com';

✴︎ DOM의 문제점

동적 UI에 최적화되어 있지 않다.

JavaScript에 DOM 요소를 조작하는 코드가 많다면, 브라우저 렌더링 시, DOM Tree와 CSSOM 트리를 다시 Parsing하여 Render Tree을 재생성하고, 이를 기반으로 리플로우와 리페인팅하는 과정이 무수히 많이 일어나게 된다.

이러한 DOM의 문제점을 해결하기 위해, React에서는 virtual DOM을 이용해 DOM 업데이트를 추상화하여 브라우저 렌더링을 최소화하여 최적화하는 작업을 수행한다.


02. DOM API

Javascript에서 HTML 요소를 제어하기 위한 명령(API, Application Programming Interface)의 집합을 의미한다.

👉 Element(요소) 선택하기

  • document.queryselector(CSS 선택자, id/class 선택자)
    해당 document에서 가장 먼저 일치하는 선택자의 요소를 1개만 반환한다. 이때 해당 요소가 2개 이상이라면, 가장 먼저 찾은 요소가 리턴된다.
<!--HTML-->
<div class="this">1번 요소</div>
<div class="this">2번 요소</div>
<div class="this">3번 요소</div>
// JavaScript
document.querySelector('.this') // 1번 요소 하나만 선택된다.
  • document.queryselectorAll(CSS 선택자, id/class 선택자)
    해당 document에서 일치하는 선택자를 가진 모든 요소를 찾아 반환하며, 이때 반환데이터는 배열 형태로 정렬된다.
    배열의 요소 중 원하는 데이터를 선택하려면 [index]를 명시한다.
<!--HTML-->
<div class="this">1번 요소</div>
<div class="this">2번 요소</div>
<div class="this">3번 요소</div>
// JavaScript
document.querySelectorAll('.this') // ["1번 요소", "2번 요소", "3번 요소"] < 배열로 표시
document.querySelectorAll('.this')[1] // 2번 요소를 선택

※ 이때 반환되는 배열은 배열과 모양은 유사하나, 엄밀히 말해 배열은 아니기 때문에 이를 유사배열(array-like)라고 한다.

👉 Class 제어하기

<!--HTML-->
...
   <p>this is p</p>
...
// JavaScript
const  spanElement = document.queryselector('span');
  • .classList.add(클래스명)
    선택한 요소의 클래스로 해당 인수를 추가한다.
// JavaScript
spanElement.classList.add('warning');
  • .classList.remove(클래스명)
    선택한 요소의 클래스에서 해당 인수를 삭제한다.
// JavaScript
spanElement.classList.remove('warning');
  • .classList.contains(클래스명)
    선택한 요소의 클래스에 해당 인수가 포함되어 있는지 확인한다. 포함되어 있으면 true, 아니면 false를 반환한다.
// JavaScript
spanElement.classList.contains('warning'); // true
spanElement.classList.contains('safe'); // false;

👉 이벤트로 요소 제어하기

  • .addEventListner()
    선택한 요소에 어떤 이벤트가 발생했을 떄, 지정한 함수를 실행하는 메소드
    첫번째 인수로는 이벤트 요소를, 두번째 인수로는 이벤트 발생 시 실행할 함수를 전달한다.
<!--HTML-->
<div id="target">여기에용</div>
<button id="changeBtn">">Change!</button>
// JavaScript
let changeBtn = document.getElementById('changeBtn');
let target = document.getElementById('target');
//지정할 셀렉터를 변수로 지정하여 아래의 코드 길이 줄이기

changeBtn.addEventListener('click', function() {
    target.innerHTML = 'Text changed!';
})

그 밖에도 다양한 DOM API가 있다.



※ 참고자료

profile
한입 크기로 베어먹는 개발지식 🍰

0개의 댓글

관련 채용 정보