DOM

January·2022년 8월 22일
0

노드

HTML 문서의 계층적 구조와 정보를 표현
구조와 정보를 제어하는 API

즉 프로퍼티와 메서드를 제공하는 트리 자료구조

트리 자료구조

트리자료 구조는 부모노드와 자식노드로 구성되서 비선형 자료구조이다.
(하나의 자료 뒤에 여러개의 자료가 존재 가능)
최상위 노드 = 루트 노드
루트 노드는 0개 이상의 자식 노드를 갖고 자식 노드가 없으면 리프 노드라고 한다.

그래서 노드 객체들로 구성된 트리 자료구조를 DOM이라고 한다. (or DOM트리)

노드 객체는 총 12개의 종류(노드 타입)이 있고 중요한 4가지는 다음과 같다.

문서 노드

루트 노드이고 document객체를 가리킨다. document객체는 HTML 전체를 가리키고 전역 객체 window의 document 프로퍼티에 바인딩되어 있다. 자바스크립트 코드는 하나의 전역 객체 window를 공유한다. 그래서 자바스크립트 코드는 window의 document 프로퍼티에 바인딩되어 있는 document 객체를 바라본다.
문서 노드는 루트 노드이므로 DOM 트리의 토드들에 접근하기 위한 진입점 역할을 담당한다.

요소 노드

HTML 요소를 가리키는 객체다. 부자 관계를 가지고 부자 관계를 통해 정보를 구조화한다. 따라서 요소 노드는 문서의 구조를 표현한다.

어트리뷰트 노드

HTML 요소의 어트리뷰트를 가리키는 객체다. 요소 노드와 연결되어 있다. 어트리뷰트는 부모 노드와 연결되어 있지 않고 요소 노드에만 연결된다. 부모가 없어서 요소 노드의 형제 노드도 아니다. 하지만 접근하려면 먼저 요소 노드에 접근해야한다.

텍스트 노드

HTML 요소의 텍스트를 가리키는 객체다. 텍스트 모드는 문서의 정보를 표현한다. 요소 노드의 자식 노드이고 리프 노드이다. DOM 트리의 최종단이다.

노드 객체의 상속 구조

DOM은 프로퍼티와 메서드를 제공하는 트리 자료구조이다. DOM API를 사용해서 노드 객체는 자신의 부모, 형제, 자식을 탐색하고 어트리뷰트와 텍스트를 조작할 수 있다.

  1. 모든 노드 객체는 Object, EventTarget, Node 인터페이스를 상속받는다.
  2. 문서 노드는 Document, HTMLDocument 인터페이스를 상속받는다.
  3. 어트리뷰트 노드는 Attr 인터페이스를 상속받는다.
  4. 텍스트 노드는 ChatacterData 인터페이스를 상속받는다.
  5. 요소 노드는 Element 인터페이스를 상속받는다.
    • HTMLElement와 태그의 종류별로 세분화된 HTMLHtmlElement, HTMLHeadElement, HTMLBodyElement, HTMLUListElement 등 인터페이스를 상속받는다.
const $input = document.querySelector('input')

console.log(
  Object.getPrototypeOf($input) === HTMLInputElement.prototype,
  Object.getPrototypeOf(HTMLInputElement.prototype) === HTMLElement.prototype,
  Object.getPrototypeOf(HTMLElement.prototype) === Element.prototype,
  Object.getPrototypeOf(Element.prototype) === Node.prototype,
  Object.getPrototypeOf(Node.prototype) === EventTarget.prototype,
  Object.getPrototypeOf(EventTarget.prototype) === Object.prototype
)

// 모두 true

프로토타입 체인 관접에서 보면 input 요소 노드 객체는 프로토타입 체인에 있는 모든 프로토타입의 프로퍼티나 메서드를 상속받아 사용할 수 있다.

노드 타입 상관없이 모든 노드 객체가 공통으로 갖는 기능과 타입에 따라 고유한 기능이 있다.

모든 노드 객체는 공통적으로 이벤트를 발생할 수 있고 EventTarget 인터페이스가 제공한다. 또한 Node 인터페이스가 트리 탐색 기능, 노드 정보 기능을 제공한다.
요소 노드 객체에 공통적인 기능은 input 요소 노드 객체와 div 요소 노드 객체는 style 프로퍼티가 있고 HTMLElement 인터페이스가 제공한다. 고유한 기능으로는 input 요소 노드 객체는 value 프로퍼티가 필요하지만 div는 필요하지 않다. 필요한 기능을 제공하는 인터페이스가 HTML 요소의 종류에 따라 각각 다르다.

프론트엔드 개발자는 HTML을 DOM과 연관 지어 바라보아야한다. 단순히 뷰를 구성하는 것 이상의 의미를 갖기 때문이다.

요소 노드 취득

HTML을 동적으로 조작하려면 요소 노드를 취득해야 한다. 요소 노득의 취득은 HTML 요소를 조작하는 시작점이다. 요소 노드를 취득할 수 있는 다양한 메서드를 제공하고 있다.
ex) h1요소의 텍스트 변경

  1. DOM 트리 내에 존재하는 h1 요소 노드를 취득한다.
  2. 취득한 요소 노드의 자식 노드인 텍스트 노드를 변경한다.

id를 이용한 취득

Document.prototype.getElementById 메서드는 인수로 전달한 id 어트리뷰트 값을 갖는 요소 노드 하나를 탐색해서 반환한다.getElementByIdDocument.prototype의 프로퍼티이기 때문에 반드시 문서 노드 document를 통해 호출해야한다.

id 값은 문서 내에서 유일한 값이어야 하고 class 어트리뷰트처럼 공백 문자로 구분해서 여러 값을 가질 수 없다. id값이 중복되서 여러 요소가 있다면 첫 번째 요소 노드만 반환하고 에러를 발생하지 않는다.

  • 인수로 전달된 id 값을 갖는 요소가 없다면 메서드는 null을 반환한다.
  • 암묵적으로 id 값과 동일한 이름의 전역 변수 선언(이미 동일한 전역 변수가 선언되어 있다면 재할당 되지 않는다.)

태그 이름을 이용한 취득

Document.prototype/Element.prototype.getElementsByTagName 메서드는 인수로 전달한 태그 이름을 갖는 모든 요소 노드들을 탐색해서 반환한다. 여러 개의 요소 노드 객체를 갖는 DOM 컬렉션 객체인 HTMLCollection 객체를 반환한다. HTMLCollection 객체는 유사 배열 객체이면서 이터러블이다.

문서의 모든 요소를 취득 하려면 인수로 *를 전달한다.

Domcument로 정의된 메서드, Element로 정의된 메서드

Document.prototype.getElementsByTagName 메서드는 DOM의 루트 노드인 문서노드(document)를 통해 호출하고 DOM 전체에서 요소 노드를 탐색한다.

Element.prototype.getElementsByTagName 매서드는 특정 요소 노드를 통해 호출하고 특정 요소의 자손 노드 중에서 요소 노드를 탐색해서 반환한다.

class를 이용한 취득

Document.prototype/Element.prototype.getElementsByClassName 메서드는 인수로 전달한 class 어트리뷰트 값을 갖는 모든 요소 노드들을 탐색해서 반환한다. class 값은 공백으로 구분해서 여러 개의 class를 지정할 수 있다. 여러 개의 요소 노드 객체를 갖는 DOM 컬렉션 객체인 HTMLCollection 객체를 반환한다.

Domcument로 정의된 메서드, Element로 정의된 메서드
getElementsByTagName와 마찬가지로 루트 노드를 호출하거나 특정 요소 노드를 호출해서 요소 노드를 반환한다.

CSS 선택자를 이용한 취득

CSS 선택자는 스타일을 적용하고자 하는 HTML 요소를 특정할 때 사용한다.
Document.prototype/Element.prototype.querySelector 메서드는 인수로 전달한 CSS 선택자를 만족시키는 하나의 요소 노드를 반환한다.

  • 요소 노드가 여러개인 경우 첫 번째 요소 노드만 반환한다.
  • 요소 노드가 존재하지 않는 경우 null을 반환한다.
  • CSS 선택자가 문법에 맞지 않는 경우 DOMException 에러가 발생한다.

Document.prototype/Element.prototype.querySelectorAll 메서드는 인수로 전달한 CSS 선택자를 만족시키는 모든 요소 노드를 반환한다. 여러 개의 요소 노드 객체를 갖는 DOM 컬렉션인 NodeList 객체를 반환한다. 유사배열 객체이면서 이터러블이다. 문서의 모든 요소를 취득 하려면 인수로 *를 전달한다.

  • 요소가 존재하지 않을 경우 빈 NodeList 객체를 반환한다.
  • CSS 선택자가 문법에 맞지 않는 경우 DOMException 에러가 발생한다.

Domcument로 정의된 메서드, Element로 정의된 메서드
getElementsByTagName와 마찬가지로 querySelector, querySelectorAll은 루트 노드를 호출하거나 특정 요소 노드를 호출해서 요소 노드를 반환한다.

CSS 선택자 문법을 사용하는 메서드는 getElementById, getElementBy*** 메서드보다 느리지만 구체적인 조건과 일관된 방식으로 요소 노드를 취득할 수 있는 장접이 있어서 getElementById로 id 어트리뷰트가 있는 요소 노드를 검색하고 그 외에는 querySelector, querySelectorAll 메서드 사용을 권장한다.

특정 요소 노드를 취득할 수 있는지 확인

Element.prototype.matches 메서드는 인수로 전달한 CSS 선택자를 통해 특정 요소 노드를 취득할 수 있는지 확인한다. 이 메서드는 이벤트 위임을 사용할 때 유용하다.

HTMLCollection, NodeList

DOM API가 여러 개의 결과값을 반환하기 위한 DOM 컬렉션 객체이다. 모두 유사 배열 객체이면서 이터러블이다. for...of로 순회할 수 있고 스프레드 문법을 사용해서 배열로 변환 가능하다.

특징으로는 노드 객체의 상태 변화를 실시간으로 반영하는 살아 있는 객체이다. HTMLCollection은 언제라 live이지만 NodeList는 non-live 객체로 동작한다(경우에 따라서 live 객체로 동작할 때도 있다.)

live 객체의 부작용을 해결하기 위해 querySelectorAll 메서드를 사용하는 방법도 있다. NodeList 객체를 반환하기 때문에 실시간 상태 변경을 반영하지 않는다. 하지만 childNodes 프로퍼티가 반환하는 NodeListAsms live 객체이므로 주의가 필요하다.

Node.prototype.forEachArray.prototype.forEach와 사용방법이 동일하다.

0개의 댓글