본문 바로가기

FE

1.2 DOM 트리

모던 JavaScript 튜토리얼 파트 2. 브라우저: 문서, 이벤트, 인터페이스를 읽고 정리, 기록

 

브라우저 환경과 다양한 명세서

 

브라우저 환경과 다양한 명세서

 

ko.javascript.info

 

 

HTML은 태그(tag)로 이루어져 있다.

모든 HTML 태그는 객체이다.

태그 안에 감싸진 ‘자식’태그는 ‘중첩 태그 (nested tag)’라고 한다.

태그 내의 문자(text) 역시 객체이다.

→ 모든 객체(태그)는 자바스크립트를 통해 접근할 수 있다.

  • ex) <body>: document.body
  • ex) innerHTML: 해당 노드의 HTML 콘텐츠
  • ex) offsetWidth: 해당 노드의 너비

DOM의 구조

<!DOCTYPE HTML>
<html>
<head>
  <title>사슴에 관하여</title>
</head>
<body>
  사슴에 관한 진실.
</body>
</html>

위 코드를 태그 트리 구조로 나타내면 다음과 같다.

  • 태그 = 요소 노드(element node)
  • <html>: 루트 노드 / <head> <body>: 루트 노드의 자식
  • 텍스트(text) 노드: 자식 노드를 가질 수 없고, 트리의 끝인 잎 노드(leaf node) 가 된다.

특수문자 (텍스트 노드)

  • 새 줄(newline): ↵ (자바스크립트에선 \\n로 표시)
  • 공백(space): ␣

텍스트 노드 생성의 예외

  1. 역사적인 이유로?, <head> 이전의 공백과 새 줄은 무시된다.
  2. HTML 명세서에서 모든 콘텐츠는 body 안쪽에 있어야한다. </body> 뒤에 내용이 있더라도 그 콘텐츠는 자동으로 body 안쪽으로 옮겨진다.

문자열 양 끝 공백과 공백만 있는 텍스트 노드는 개발자 도구에서 보이지 않는다.

자동교정

기형적인 HTML은 브라우저가 DOM 생성과정에서 자동으로 교체한다.

  • ex) 문서에 <html> 태그가 없는 경우
    • 최상위 태그는 <html> 이어야 하기 때문에 문서 최상위에서 자동으로 넣어준다.
    • <html>, <head>, <body> 도 같은 방식이 적용된다.
  • ex) 닫는 태그가 없는 경우 자동으로 넣어준다.

테이블엔 언제나 <tbody>가 있다.

DOM 명세서에서는 테이블에 반드시 <tbody>가 있어야 한다고 하지만, HTML에선 <tbody>를 생략하곤 한다.

→ 브라우저는 자동으로 DOM에 <tbody>를 만들어준다.

기타노드 (주석 노드)

트리에 주석 노드(comment node)가 존재한다.

주석이 화면 출력물에 영향을 주지 않는데 DOM에 추가되는 이유?

  • HTML에 뭔가 있다면 반드시 DOM트리에 추가되어야 한다는 규칙 때문에

노드 타입

총 열두 가지

 

interface Node

더보기
[Exposed=Window]
interface Node : EventTarget {
  const unsigned short ELEMENT_NODE = 1;
  const unsigned short ATTRIBUTE_NODE = 2;
  const unsigned short TEXT_NODE = 3;
  const unsigned short CDATA_SECTION_NODE = 4;
  const unsigned short ENTITY_REFERENCE_NODE = 5; // legacy
  const unsigned short ENTITY_NODE = 6; // legacy
  const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
  const unsigned short COMMENT_NODE = 8;
  const unsigned short DOCUMENT_NODE = 9;
  const unsigned short DOCUMENT_TYPE_NODE = 10;
  const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
  const unsigned short NOTATION_NODE = 12; // legacy
  readonly attribute unsigned short nodeType;
  readonly attribute DOMString nodeName;

  readonly attribute USVString baseURI;

  readonly attribute boolean isConnected;
  readonly attribute Document? ownerDocument;
  Node getRootNode(optional GetRootNodeOptions options = {});
  readonly attribute Node? parentNode;
  readonly attribute Element? parentElement;
  boolean hasChildNodes();
  [SameObject] readonly attribute NodeList childNodes;
  readonly attribute Node? firstChild;
  readonly attribute Node? lastChild;
  readonly attribute Node? previousSibling;
  readonly attribute Node? nextSibling;

  [CEReactions] attribute DOMString? nodeValue;
  [CEReactions] attribute DOMString? textContent;
  [CEReactions] undefined normalize();

  [CEReactions, NewObject] Node cloneNode(optional boolean deep = false);
  boolean isEqualNode(Node? otherNode);
  boolean isSameNode(Node? otherNode); // legacy alias of ===

  const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
  const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
  const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04;
  const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08;
  const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10;
  const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
  unsigned short compareDocumentPosition(Node other);
  boolean contains(Node? other);

  DOMString? lookupPrefix(DOMString? namespace);
  DOMString? lookupNamespaceURI(DOMString? prefix);
  boolean isDefaultNamespace(DOMString? namespace);

  [CEReactions] Node insertBefore(Node node, Node? child);
  [CEReactions] Node appendChild(Node node);
  [CEReactions] Node replaceChild(Node node, Node child);
  [CEReactions] Node removeChild(Node child);
};

dictionary GetRootNodeOptions {
  boolean composed = false;
};

 

주로 다루는 노드

  1. 문서(document) 노드: DOM의 진입점
  2. 요소 노드(element node): HTML 태그에서 만들어지며, DOM트리를 구성하는 블록
  3. 텍스트 노드(text node): 텍스트를 포함
  4. 주석 노드(comment node): 화면에 보이지는 않지만, 정보를 기록하고 자바스크립트를 사용해 이 정보를 DOM으로부터 읽을 수 있는 주석(comment) 노드

DOM 구조 직접 보기

https://software.hixie.ch/utilities/js/live-dom-viewer/

Live DOM Viewer에 들어가면 실시간으로 DOM 구조를 볼 수 있다.

브라우저 개발자 도구를 사용할 수도 있다.

 

개발자 도구를 이용해 DOM구조를 볼 땐, 생략된 부분이 있다.

- 텍스트 노드 → 텍스트

- 띄어쓰기만 있는 빈 텍스트 노드 → 나타나지 않음

 


크롬 개발자도구 문서

https://developers.google.com/web/tools/chrome-devtools

모든 HTML 태그는 객체이다.

태그 안에 감싸진 ‘자식’태그는 ‘중첩 태그 (nested tag)’라고 한다.

태그 내의 문자(text) 역시 객체이다.

→ 모든 객체(태그)는 자바스크립트를 통해 접근할 수 있다.

  • ex) <body>: document.body
  • ex) innerHTML: 해당 노드의 HTML 콘텐츠
  • ex) offsetWidth: 해당 노드의 너비