코딩을 쉽게 해보자

[Deep Dive] 39장 - DOM 본문

JavaScript

[Deep Dive] 39장 - DOM

꿀단지코딩 2023. 1. 3. 17:52

브라우저의 렌더링 엔진은

HTMl 문서를 파싱하여 브라우저가 이해할 수 있는 자료구조인 DOM을 생성한다.

DOM은 HTML 문서의 계층적 구조와 정보를 표현하며

이를 제어할 수 있는 API,

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

 

1. 노드

1-1. HTML 요소와 노드 객체

HTML 요소는 HTML 문서를 구성하는 개별적인 요소를 의미한다.

 

HTML 요소 간에는 중첩 관계에 의해 계층적인 부자관계가 형성된다.

이러한 HTML 요소간의 부자 관계를 반영하여 HTML 문서의 구성 요소인 HTML 요소를 객체화한

모든 노드 객체들을 트리 자료 구조로 구성한다.

 

트리 자료구조

트리 자료구조는 노드들의 계층 구조로 이뤄진다.

노드 객체들로 구성된 트리 자료구조를 DOM이라 한다.

 

1-2. 노드 객체의 타입

노드 객체는 종류가 있고 상속 구조를 갖는다.

노드 객체는 총 12개의 종류(노드 타입)가 있다.

중요한 노드타입은

  • 문서 노드
    DOM 트리의 최상위에 존재하는 루트 노드로서
    document 객체를 가리킨다.
    브라우저가 렌더링한 HTML 문서 전체를 가리키는 객체다.
  • 요소 노드
    HTML 요소를 가리키는 객체
  • 어트리뷰트
    HTML 요소의 어트리뷰트를 가리키는 객체
  • 텍스트 노드
    HTML 요소의 텍스트를 가리키는 객체

 

1-3. 노드 객체의 상속 구조

노드 객체도 JS 객체이므로

프로토타입에 의한 상속 구조를 갖는다.

 

DOM은 HTML 문서의 계층적 구조와 정보를 표현하는 것은 물론

노드 객체의 종류, 즉  노드 타입에 따라 필요한 기능을

프로퍼티와 메서드의 집합인 DOM API로 제공한다.

이 DOM API를 통해 HTML의 구조나 내용 또는 스타일 등을 동적으로 조작할 수 있다.

 

2. 요소 노드 취득

HTML의 구조나 내용 또는 스타일 등을 동적으로 조작하려면

먼저 요소 노드를 취득해야 한다.

 

DOM은 요소 노드를 취득할 수 있는 다양한 메서드를 제공한다.

 

2-1. id를 이용한 요소 노드 취득

Document.prototype.getElementById

 

2-2. 태그 이름을 이용한 요소 노드 취득

Document/Element.prototype.getElementsByTagName

 

2-3. 클래스를 이용한 요소 노드 취득

getElementsByClassName

 

2-4. CSS 선택자를 이용한 요소 노드 취득

querySelector

 

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

Element.prototype.matches

 

2-6. HTMLCollection과 NodeList

DOM 컬렉션 객체인 이들은 DOM API가 여러 개의 결과값을 반환하기 위한

DOM 컬렉션 객체다.

모두 유사 배열 객체이면서 이터러블이다.

for ... of문으로 순회할 수 있으며

스프레드 문법을 사용하여 간단히 배열로 변환할 수 있다.

 

중요한 특징은

노드 객체의 상태 변화를 실시간으로 반영하는

살아 있는 객체라는 것이다.

 

HTML Collections이나 NodeList 객체는

예상과 다르게 동작할 때가 있어 다루기 까다롭고 실수하기 쉽다.

노드 객체의 상태 변경과 상관없이 안전하게 DOM 컬렉션을 사용하려면

HTMLCollection이나 NodeList 객체를 배열로 변환하여

사용하는 것을 권장한다.

 

객체를 배열로 변환하면 고차함수를 사용할 수 있다는 장점이 있다.

 

3. 노드 탐색

3-1. 공백 텍스트 노드

HTML 문서에 스페이스 키, 탭 키, 엔터 키 등을 입력하면 공백 문자가 추가된다.

 

3-2. 자식 노드 탐색

Node.prototype.childNodes

Element.prototype.children

Node.prototype.firstChild

Node.prototype.lastChild

Element.prototype.firstElementChild

Element.prototype.lastElementChild

 

3-3. 자식 노드 존재 확인

Node.prototype.hasChildNodes

 

3-4. 요소 노드의 텍스트 노드 탐색

요소 노드의 텍스트 노드는

요소 노드의 자식 노드

따라서 요소 노드의 텍스트 노드는 firstChild 프로퍼티로 접근할 수 있다.

 

3-5. 부모 노드 탐색

Node.prototype.parentNode

 

3-6. 형제 노드 탐색

Node.prototype.previousSibling

Node.prototype.nextSibling

Element.prototype.previousElementSibling

Element.prototype.nextElementSibling

 

4. 노드 정보 취득

Node.prototype.nodeType

노드 타입을 나타내는 상수 반환

 

Node.prototype.nodeName

노드의 이름을 문자열로 반환

 

5. 요소 노드의 텍스트 조작

5-1. nodeValue

5-2. textContent

 

6. DOM 조작

DOM 조작은

새로운 노드를 생성해 DOM에 추가하거나 기존 노드를 삭제 또는 교체하는 것을 말한다.


DOM 조작에 의해

DOM에 새로운 노드가 추가되거나 삭제되면

리플로우와 리페인트가 발생하는 원인이 되므로

성능에 영향을 준다.

 

6-1. innerHTML

사용자로부터 입력받은 데이터를

그대로 innerHTML 프로퍼티에 할당하는 것은

크로스 사이트 스크립팅 공격(XSS: Cross-site Scripting Attacks)에 취약하므로 위험하다.

 

6-2. insertAdjacentHTML

기존 요소를 제거하지 않으면서

위치를 지정해 새로운 요소를 삽입한다.

 

인수로 전달할 수 있는 문자열은

beforebegin, afterbegin, beforeend, afterend의 4가지다.

 

6-3. 노드 생성과 추가

요소 노드 생성

Document.prototype.createElement(tagName)

 

텍스트 노드 생성

Document.prototype.createTextNode(text)

 

텍스트 노드를 요소 노드의 자식 노드로 추가

Node.prototype.appendChild(childNode)

 

요소 노드를 DOM에 추가

Node.prototype.appendChild

 

6-4. 복수의 노드 생성과 추가

컨테이너 요소를 사용하면 DOM은 한 번만 변경된다.

불필요한 컨테이너 요소는 DoucmentFragment 노드를 통해 해결할 수 있다.

 

6-5. 노드 삽입

마지막 노드로 추가

Node.prototype.appendChild

 

지정한 위치에 노드 삽입

Node.prototype.insertBefore(newNode, childNode)

 

6-6. 노드 이동

DOM에 이미 존재하는 노드를

appendChild 또는 insertBefore 메서드를 사용하여 DOM에 다시 추가하면

현재 위치에서 노드를 제거하고 새로운 위치에 노드를 추가한다.

즉, 노드가 이동한다.

 

6-7. 노드 복사

Node.prototype.cloneNode

 

6-8. 노드 교체

Node.prototype.replaceChild(newChild, oldChild)

 

6-9. 노드 삭제

Node.prototype.removeChild(child)

 

7. 어트리뷰트

7-1. 어트리뷰트 노드와 attributes 프로퍼티

HTML 문서의 구성 요소인 HTML 요소는 여러 개의 어트리뷰트를 가질 수 있다.

 

7-2. HTML 어트리뷰트 조작

7-3. HTML 어트리뷰트 vs DOM 프로퍼티

DOM 프로퍼티들은 HTML 어트리뷰트 값을 초기값으로 가지고 있다.


HTML 어트리뷰트의 역할은 HTML 요소의 초기 상태를 지정하는 것이다.

즉, HTML 어트리뷰트 값은 HTML 요소의 초기 상태를 의미하며 이는 변하지 않는다.

 

요소 노드는 상태(state)를 가지고 있는다.

 

요소 노드는 2개의 상태, 즉 초기 상태와 최신 상태를 관리해야 한다.

요소 노드의 초기 상태는 어트리뷰트 노드가 관리하며,

요소 노드의 최신 상태는 DOM 프로퍼티가 관리한다.

 

어트리뷰트 노드

HTML 어트리뷰트로 지정한 HTML 요소의 초기 상태는 어트리뷰트 노드에서 관리한다.

 

DOM 프로퍼티

사용자가 입력한 최신 상태는

HTML 어트리뷰트에 대응하는 요소 노드의 DOM 프로퍼티가 관리한다.

DOM 프로퍼티는 사용자의 입력에 의한

상태 변화에 반응하여 언제나 최신 상태를 유지한다.

 

7-4 data 어트리뷰트와 dataset 프로퍼티

 

8. 스타일

8-1. 인라인 스타일 조작

HTMLElement.prototype.style

 

8-2. 클래스 조작

className

classList

 

8-3. 요소에 적용되어 있는 CSS 스타일 참조

style 프로퍼티는 인라인 스타일만 반환하기에

HTML 요소에 적용되어 있는 모든 CSS 스타일을 참조해야 할 경우 getComputedStyle 메서드를 사용한다.

 

9. DOM 표준

HTML과 DOM 표준은

W3C와 WHATWG이라는 두 단체가 나름 협력하며 공통된 표준을 만들어 왔다.

 

약 1년 전부터 두 단체가 서로 다른 결과물을 내놓기 시작했다.

2018년 4월부터 구글, 애플, 마소, 모질라로 구성된 4개의 주류 브라우저 벤더사가 주도하는

WHATWG이 단일 표준을 내놓기로 두 단체가 합의했다.