[Web] DOM이 뭔가요?

초코침·2023년 3월 7일
1

Web

목록 보기
2/5

자바스크립트에서 HTML의 요소들을 조작(CRUD)하려면 그 전에 DOM이 무엇인지 알아야 한다.

DOM

DOM은 Document Object Model로 HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API를 제공하는 트리 자료구조다. 이때, API란 DOM이 제공하는 프로퍼티와 메서드를 말한다.


HTML 요소와 노드 객체

HTML 요소는 HTML 문서를 구성하는 개별적인 요소를 말한다. 즉, HTML의 divspan 등이 HTML 요소가 된다.

HTML 문서는 HTML 요소들의 집합으로 이뤄져 있으며, HTML 요소는 중첩 관계를 갖는다. 이때 요소 간에는 중첩 관계에 의해 계층적인 부모와 자식 관계가 형성된다.


HTML 요소는 렌더링 엔진에 의해 파싱되어 DOM을 구성하는 요소 노드 객체로 변환된다. 이때 요소의 태그(div, span 등)는 요소 노드, 어트리뷰트(class, id 등)는 어트리뷰트 노드로, 텍스트 콘텐츠는 텍스트 노드로 변환된다.

이때 HTML 요소 간 부모와 자식 관계를 반영하여 HTML 요소를 객체화한 모든 노드 객체들을 트리 자료 구조로 구성한다.


노드의 객체 타입

노드 객체는 종류가 있고 상속 구조를 가지며 총 12개의 노트 타입이 있다.

다음은 대표적인 노드 타입이다.

  1. 문서 노드
    • DOM 트리 최상위에 존재하는 루트 노드로서 document 객체를 가리킴
    • 브라우저가 렌더링한 HTML 문서 전체를 가리키는 객체
    • 전역 객체 windowdocument 프로퍼티에 바인딩 되어 있음
    • 브라우저 환경의 모든 자바스크립트 코드는 전역 객체 window의 document 프로퍼티에 바인딩된 하나의 document 객체를 가리킴 (문서 당 document 객체는 유일함)
    • DOM 트리의 루트 노드기 때문에 트리의 노드(하위 노드)들에 접근하기 위한 진입점 역할을 함
  2. 요소 노드
    • HTML 요소를 가리키는 객체
    • HTML 요소 간 중첩에 의해 부모-자식 관계를 가지고 이를 통해 정보를 구조화
    • 문서의 구조를 표현함
  3. 어트리뷰트 노드
    • HTML 요소의 어트리뷰트를 가리키는 객체
    • 어트리뷰트가 지정된 HTML 요소의 요소 노드와 연결되어 있음
    • 부모 노드가 없기 때문에 요소 노드의 형제 노드는 아님 (부모를 공유하지 않음)
    • 먼저 요소 노드에 접근해야 어트리뷰트 노드에 접근할 수 있다.
  4. 텍스트 노드
    • HTML 요소의 텍스트를 가리키는 객체
    • 문서의 정보를 표현하는 역할
    • 요소 노드의 자식 노드이며 자식 노드를 가질 수 없는 리프 노드
    • 먼저 부모 노드인 요소 노드에 접근해야 텍스트 노드에 접근할 수 있음

이 외에도 주석을 위한 Comment 노드, 복수의 노드를 생성하여 추가할 때 사용하는 DocumentFragment 노드 등 총 12가지 타입이 있다.


body 내부의 요소 노드, 어트리뷰트 노드, 텍스트 노드 확인해 보기

다음처럼 트리 구조를 이루는 HTML 문서를 작성한 다음, body 내부의 요소 노드/어트리뷰트 노드/텍스트 노드를 확인해 보았다.

  1. 요소 노드

예시로 HTML 문서에서 (렌더링 엔진을 거쳐 생성될) DOM에는 어떤 것들이 있을지 살펴보자.

다음과 같이 HTML 문서를 작성하고 live server로 크롬 브라우저에 열어 보았다.

<!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>Document</title>
  </head>
  <body>
    <h1 id="subject" class="title-text">노드의 객체 타입</h1>
    <div id="description" class="text">대표적인 노드의 객체 타입</div>
    <ul>
      <li>문서 노드</li>
      <li>요소 노드</li>
      <li>어트리뷰트 노드</li>
      <li>텍스트 노드</li>
    </ul>
  </body>
</html>

body 내부만 살펴봤을 때 body의 자식이 될 노드는 [h1 요소 노드, div 요소 노드, ul 요소 노드] 이렇게 3가지가 나올 것이라 예상했다.


특정 노드의 자식 노드들을 참조할 수 있는 childNodes로 자식 노드들을 출력해보았다.

실제로 출력해 봤을 땐 예상과 달리 11개의 자식 노드가 나타났다.


h1, div, ul은 예상했던 노드지만 text, comment, script는 파일에 작성하지 않았는데 자식 노드로 들어가 있어서 무엇인가 했더니, text의 경우 HTML 요소 사이의 개행이나 공백은 텍스트 노드가 되어 text가 된다고 한다.

즉, 다음과 같이 아무것도 없다고 생각한 부분이 text 노드로 변경된 것이다.

<body>
  <!-- text 노드 -->
  <h1 id="subject" class="title-text">노드의 객체 타입</h1>
	<!-- text 노드 -->
  <div id="description" class="text">대표적인 노드의 객체 타입</div>
	<!-- text 노드 -->
  <ul>
    <li>문서 노드</li>
    <li>요소 노드</li>
    <li>어트리뷰트 노드</li>
    <li>텍스트 노드</li>
  </ul>
	<!-- text 노드 -->
	<!-- comment 노드 -->
	<!-- text 노드 -->
	<!-- script 노드 -->
	<!-- text 노드 -->
</body>

공백 텍스트 노드: HTML 요소 사이의 개행이나 공백은 텍스트 노드(text)가 된다.


text 노드의 정체는 알게 됐고, 그렇다면 commentscript 노드의 정체는 무엇일까 하고 요소 창을 열어 봤더니

live server에 의해 자동적으로 생성된 주석과 자바스크립트 코드가 노드로 생성된 것이었다. 😅


  1. 어트리뷰트 노드
<!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>Document</title>
  </head>
  <body>
    <h1 id="subject" class="title-text">노드의 객체 타입</h1>
    <div id="description" class="text">대표적인 노드의 객체 타입</div>
    <ul>
      <li>문서 노드</li>
      <li>요소 노드</li>
      <li>어트리뷰트 노드</li>
      <li>텍스트 노드</li>
    </ul>
  </body>
</html>

어트리뷰트를 가지고 있는 노드는 h1과, div 뿐이다. 이 요소 노드에 연결되어 있는 어트리뷰트 노드는 attributes 프로퍼티로 확인할 수 있다. 이는 요소 노드의 모든 어트리뷰트 노드의 참조가 담긴 NamedNodeMap 객체를 반환한다.


두 요소 노드의 어트리뷰트를 조회해 봤더니, 다음과 같이 출력됐다. 두 객체의 length는 2로, 두 개의 어트리뷰트를 갖고 있음을 의미한다.


또한, 어트리뷰트 노드는 부모 노드가 없기 때문에 요소 노드와 연결은 되어 있지만 형제 노드가 아니라고 했다. 이를 확인하기 위해 어트리뷰트 노드의 부모 노드와 형제 노드를 확인해 보았다.

어트리뷰트 노드는 parentNode도 없고(null) sibling 노드도 없어(null) 요소 노드와 형제 관계가 아님을 알 수 있었다.


  1. 텍스트 노드

ul 내부의 li 텍스트 요소를 출력해 보자.

<!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>Document</title>
  </head>
  <body>
    <h1 id="subject" class="title-text">노드의 객체 타입</h1>
    <div id="description" class="text">대표적인 노드의 객체 타입</div>
    <ul>
      <li>문서 노드</li>
      <li>요소 노드</li>
      <li>어트리뷰트 노드</li>
      <li>텍스트 노드</li>
    </ul>
  </body>
</html>

document(문서 노드)에서 li 요소의 요소 노드를 모두 가져와 순차적으로 접근하면서 li의 첫 번째 자식인 text 노드nodeValue를 참조해 출력하였다.

firstChild: 노드의 첫 번째 자식 노드 참조
nodeValue: text 노드의 값 참조 (문서 또는 요소 노드에서 참조 시 null 리턴)


이제 DOM이 무엇인지 감을 잡았으니! 다음 글은 CRUD에 대해 작성해봐야 겠다.

profile
블로그 이사중 🚚 (https://sungjihyun.vercel.app)

0개의 댓글