js

Dom

mallang_col 2023. 2. 21. 21:02

DOM

Document Object Model

 

DOM은 HTML 문서의 계층적 구조와 정보를 표현하여 이를 제어할 수 있는 API

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

 

39.1 노드

 

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

요소는 렌더링 엔진에 의해 파싱되어노드 객체로 변환된다. 이때 요소의 어트리뷰트는 어트리뷰트

노드로 HTML요소의 텍스트 콘텐츠는 텍스트노드로 변환된다.

 

HTML요소 간에는 중첩관계에 의해 계층적인 부자 관계가 형성된다. 이러한 관계 요소를 객체화한

모든 노드 객체들은 트리자료 구조로 구성하게 된다.

 

트리 자료 구조 

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

노드 객체의 트리로 구조화 되어 있기 때문에 DOM을 DOM트리라 부르기도 한다.

 

39.1.2 노드 객체의 타입

 

HTML문서를 엔진이 파싱한다고 ㅅ가정.

 

<!DOCTYPE html>
<html>
<head>

<meta charset=“UTF-8”>

<link rel=“stylesheet” href=“style.css”>

</head>

<body>

<ul>

<li id=“apple”>Apple</li>

</ul>

<script src=“app.js”></script>

</body>

</html>

 

Document -> html -> head -> meta - charst=“UTF-8”

 

-> link - rel=“stylesheet”

href=“style.css”

-> body  -> ul -> li

| “Apple”

 

->script  -src=“app.js”

 

 

문서 노드 

 

문서 노드는 DOM 트리의 최상위에 존재하는 루트 노드로서 document 객체를 가르킨다.

브라우저가 렌더링한 문서 전체를 가르키는 객체로서 전역 객체의 프로퍼티에 바인딩 되어 있다.

따라서 문서노드의 경우 window.document 또는 document를 이용하여 참조 가능하다.

브라우저 환경의 모든 자바스크립트 코드의 경우 script가 분리되어 있어도 하나의 전역 객체 window를 공유한다, 문서당 document객체는 유일함.

 

요소 노드 

 

요소 노드는 HTML요소를 가르키는 객체다. 요소 노드는HTML요소간의 중첩에 부자 관계를 나타낸다.

 

어트리뷰트 노드 

 

어트리뷰트 노드는 HTML요소의 어트리뷰트를 가르키는 객체다 부모 노드와 연결되어 있지 않고 각각의 요소 노드에 연결되어 있는것이 차이점.

 

텍스트 노드 

 

텍스트 노드는 HTML요소의 텍스트를 가르키는 객체다 문서의 정보를 표현하는 녀석으로 

태그 안의 내용들이 가지고 있는 정보를 뜻하며 트리의 최종단으로 자식을 더이상 가지지 못하는 노드이다.

 

39.1.3 노드 객체의 상속 구조

 

DOM은 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API를 트리 자료구조라고 한다.

DOM을 구성하는 노드 객체는 자신의 구조와 정보를 제어할 수 있는 DOM api를 사용 할 수 있다.

 

DOM을 구성하는 노드 객체는 ECMA사양에 정의된 표준 빌트인 객체가 아니라 브라우저 환경에서 추가적으로 제공하는 호스트 객체다. 노드 객체도 자바스크립트 객체 이므로 프로토타입상속구조를 따르게 된다.

 

노드 객체는 Object, EventTarget, Node 인터페이스를 상속받는다. 추가적으로 문서노드는 Document 와 HTMLDocument를 상속 받고 어트리뷰트 노드는 Attr 텍스트 노드는 characterData 인터페이스를 상속받는다

 

노드의 특성을 나타내는 기능을 상속을 통해 제공받는다.

 

노드 객체는 트리 자료구조의 노드로서 공통적으로 트리 탐색 기능이나 노드 정보 제공이 필요하다 이와 같은 기능은 Node인터페이스가 제공한다.

 

HTML요소가 객체화된 요소 노드 객체는 공통적인 기능이 있따. Style 프로퍼티와, 요소 객체같은 특수한 노드를 뜻함. 

 

DOM 은 HTML 문서의 계층적 구조와 정보를 표현하는 것은 물론 노드 객체의 종류 즉 노드 타입에 따라 필요한 기능을 프로퍼티와 메서드의 집합인 DOM API로 제공한다. 이를 통해 구조나 내용 또는 스타일등을 동적으로 조작할 수 있다.

 

39.2 요소 노드 취득 

 

 HTML 문서 내의 스타일 등을 동적으로 조작하려면 요소 노드를 취득해야 한다 

위처럼 사용 하는것에 대한 이유를 가지고 리액트가 나왔고 가상돔이라는 친구로 사용한다.

 

39.2.1 id를 이용한 요소 노드를 취득

 

getElementById 메서드는 인수로 전달한 id어트리뷰트값을 갖는 하나의 요소 노드를 탐색하여 반환한다. getElementById 메서드가 없으면 null을 반환한다.

 

요소에 id어트리뷰트를 부여하면 id값과 동일한 전역 변수가 암묵적으로 선언되고 노드객체가 할당되는 부수 효과가 있다. 

 

39.2.2 태그 이름을 이용한 요소 노드 취득

 

getElementsByTagName메서드는 인수로 전달한 태그 이름을 갖는 모든 요소 노드를 탐색하여 반환한다. 메서드 이름에 맞는 여러개  HTMLCollection 객체를 반환한다.

 HTMLCollection 객체는 유사 배열 객체 이면서 이터러블 이므로 

forEach 와 같은 메서드를 이용하여 처리 가능하다 .

 

요소가 존재하지 않으면 빈 HTMLCollection 객체를 반환한다.

 

39.2.3 class를 이용한 요소 노드 취득

 

getElementsByClassName메서드는 인수로 전달한 class 어트리뷰트 값을 갖는 모든 요소 노드들을 탐색하여 

반환한다. 인수로 전달한 class 값은 공백으로 구분하여 여러 값을 지정할 수 있다.

 

39.2.4 css 선택자를 이용한 요소 노드 취득

 

Css 선택자는 스타일을 적용하고자 하는 HTML요소를 특정할 때 사용하는 문법이다.

 

Document.querySelectorAll 메서드는 인수로 전달한 css선택자를 만족시키는 모든 요소 노드를 탐색하여반환한다.

값이 존재하지 않으면 빈 NodeList객체를 반환한다. HTMLCollection과 같이 유사 배열 객체이면서 이터러블이다.

 

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

 

Element.prototype.matches 메서드 인수로 전달한 css 선택자를 통해 특정 요소 노드를 취득 할 수 있는지 확인한다.

 

39.2.6 HTMLCollection 과 NodeList

 

DOM 컬렉션 객체인 두가지는 DOM API 가 여러 개의 결과값을 반환하기 위한 DOM 컬렉션 객체다.

HTMLCollection 

getElementsByTagName, getElementsByClassName 메서드가 반환하는 HTMLCollection 객체는 노드 객체의 상태를 실시간으로 반영하는 객체다. 따라서 살아있는 객 체라고 부르기도 한다.

 

HTMLCollection의 경우 살아있는 객체이기 때문에 역방향 순회와 같은 방식을통해 검사한다.

또는 와일을 통해서 다 없어질때까지 하는 방식도 존재하나 제일 좋은 방법은 사용하지 않는것이다.

 

NodeList

 HTMLCollection객체의 부작용을 해결하기 위해 querySelectorAll 메서드를 사용하는 방법도 있따. NodeList의 경우 살아있는 객체가 아니기 때문에 찾고나서의 결과값이 변경 되지않는다.

childNodes프로퍼티가 반환하는 NodList 객체는 HTMLCollection 객체와 같이 실시간으로 노드 객체의 상태 변경을 반영하는 live 객체로 동작하는 주의가 필요하다.

 

39.3 노드 탐색

 

요소 노드를 취득한 다음 취득한 요소 노드를 거점으로 노드를 옮겨다니며 탐색을 해야할 때가 있다 .

트리 탐색 프로퍼티를 제공한다.

 

39.3.1 공백 텍스트 노드 

 

 HTML 요소 사이의 스페이스 탭 줄바꿈 등의 공백 문자는 텍스트 노드를 생성한다. 

 

 

39.3.2 자식 노드 탐색

자식 노드를 탐색하기 위해서는 다음과 같은 노드 탐색 프로퍼티를 사용한다 .

 

39.3.3 자식 노드 존재 확인

 

자식 노드가 존재하는지 확인 하기 위해 hasChildNodes메서드를 사용한다 자식이 존재하면 True 자식이 없으면 false를 반환한다.

 

39.3.4 요소 노드의 텍스트 노드 탐색

 

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

 

39.3.5 부모 노드 탐색

 

부모 노드를 텍스트 노드는 DOM 트리의 최종단 노드인 리프 노드이므로 부모 노드가 텍스트 노드인 경우는 없다.

 

39.3.6 형제 노드 탐색 

 

어트리뷰트노드는 요소노드와 연결되어 있지만 형제 노드가 아니기 때문에 반환되지 않는다 

 

Node.prototype.previousSibling |부모 노드가 같은 형제 노드 중에서 자신의 이전 형제 노드를 탐색하여 반환

 

Node.prototype.nextSiblilng | 부모 노드가 같은 형제 노드 중에서 자신의 다음 형제 노드를 탐색하여 반환한다. 

요소 노드 뿐만 아니라 텍스트 노드 일 수 있다.

 

Element.prototype.previousElementSibling 부모 노드가 같은 형제 요소 노드 중에서 자신의 이전 형제를 반환

 

Element.prototype.nextElementSibling 부모 노드가 같은 형제 요소 노드 중에서 nextElementSibling 프로퍼티 요소 노드만 반환한다,

 

39.4 노드 정보 취득

 

노드 객체에 대한 정보를 취득하려면 다음과 같은 노드 정보 프로퍼티를 사용한다 

 

Node.prototype.nodeType  | 노드 객체의 종류 즉 노드 타입 상수는 node에 정의되어 있다.

 

Node.prototype.nodeName| 노드의 이름을 문자열로 반환한다.

 

 

39.5 요소 노드의 텍스트 조작

 

39.5.1 nodeValue

 

nodeValue 프로퍼티를 참조하면 노드 객체의 값을 반환한다. 노드 객체의 값이란 텍스트 노드의 텍스트다 

 

39.5.2 textContent

 

Node.prototype.textContent 프로퍼티는 setter와 getter 모두 존재하는 접근자 프로퍼티로서 요소 노드의 텍스트와 

모든 자손 노드의 텍스트를 모두 취득 하거나 변경한다.

 

요소 노드의 textContent 프로퍼티에 문자열을 할당하면 요소 노드의 모든 자식노드가 제거되고 할당한 문자열이 텍스트로 추가된다. 마크업이 파싱되지 않는다

 

39.6 DOM 조작

 

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

추가되거나 삭제되면 리플로우와 리페인트가 발생하는 원인이 되므로 성능 최적화를 위해 주의해서 다루어야 한다.

 

39.6.1 innerHTML 

Element.prototype.innerHTML 프로퍼티는 setter 와 getter 모두 존재하는 접근자 프로퍼티로 마크업을 취득하거나 변경한다

 

HTML 새니티제이션 

 

HTML 새니티제이션은 사용자로부터 입력받은 데이터에 의해 발생할 수 있는 크로스 사이트 스크립팅 공격을 예방하기 위해 잠재적 위험을 제거하는 것을 말한다.

 

39.6.2 insertAdjacentHTML 메서드 

 

element.prototype.insertAdjacentHTML (position, DOMString) 메서드 포지션에 삽입하여 DOM 에 반영한다.

 

39.6.3 노드 생성과 추가 

 

innerHTML 프로퍼티와 insertAdjacentHTML 메서드를 이용해서 마크업 문자열을 파싱하여 노드를 생성하고 DOM에 반영한다.  DOM은 노드를 직접 생성/삽입/삭제/치환하는 메서드를 제공한다.

 

요소 노드 생성

 

Document.prototype.createElement(tagName) 메서드의 매개변수에는 태그 이름을 나타내는 문자열을 인수로 전달한다.

 

텍스트 노드 생성

 

Document.prototype.createTextNode(text) 메서드는 텍스트 노드를 생성하여 반환한다. 

 

텍스트 노드는 요소 노드의 자식 노드다 하지만 createTextNode메서드로 생성한 텍스트 노드는 요소의 자식노드로 추가되는것이 아니라 홀로 존재한다. 따라서 특정 요소에 추가하는 작업이 별도로 필요하고 

그래서 appendChild() 와 같은 프로퍼티를 사용한다.

 

최종적으로 연결된 상태에 변화를 감지하여 DOM이 재렌더링 됨으로 이 과정을 최소화 하는 과정이 필요하다 

 

예를들어Todo앱이라고 한다면

```

Const Container = document.createElement(“div”);

Const todo = document.createElement(“input”);

Const todoButton = document.createElement(“button”);

container.appendChild(todo);

Container.appendChild(button);

document.body.appendChild(container);

```

와 같이 사용하는 방식을 이용하는것이 좋다

하지만위의 경우 필요없는. Div.가 발생할 수 있고 DOM에 추가하면 자신은 제거되고 자신의 자식노드만 DOM에 추가된다.

 

39.6.5 노드 삽입

 

마지막 노드 추가 

 

Node.prototype.appendChild 메서드는 인수로 전달받은 노드를 자신을 호출한 노드의 마지막 자식 노드로 DOM에 추가한다. 이때 노드를 추가할 위치를 지정할 수 없고 마지막 자식 노드로만 추가한다.

 

지정한 위치에 노드 삽입

 

Node.prototype.insertBefore(newNode, childNode)메서드는 첫번째 인수로 전달받은노드를 인수로 전달받은 노드앞에 삽입한다.

 

39.6.6 노드 이동

DOM에 이미 존재하는 노드를 appendChild 또는 insertBefore 메서드를 사용하여 DOM에 다시 추가하면 

현재 위치에 추가한다.

 

39.6.7 노드 복사 

Node.prototype.cloneNode([deep:true | false])메서드는 사본을 반환한다.

 

39.6.8 노드 교체 

 

Node.prototype.replaceChild(newChild, oldChild)메서드는 자신을 호출한 노드의 자식 노드를 다른 노드로 교체한다.

 

39.7 어트리뷰트

 

39.7.1 어트리뷰트 노드와 attributes프로퍼티 

 

HTML 문서의 구성 요소인 HTML요소는 여러개의 어트리뷰트를 가질 수 있다. HTML 요소의 동작을 제어하기 위한

추가적인 정보를 제공하는 HTML어트리뷰트는 HTML 요소의 시작 태그에 어트리뷰트 이름= 값 형식으로 정의한다.

 

어트리뷰트 노드의 참조는 유사 배열 객체이자 이터러블인 NamedNodeMap 객체에 담겨서 요소 노드의 attributes 프로퍼티에 저장한다.

 

39.7.2 HTML어트리뷰트 조작 

Attributes 프로퍼티는 getter 만 존재하는 읽기 전용 접근자 프로퍼티이므로 HTML 어트리뷰트 값을 취득 할 수 있지만 변경 할 수 없다. 

 

39.7.3 HTML 어트리뷰트 vs DOM프로퍼티 

 

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

DOM 프로퍼티는 setter와 getter 모두 존재하는 접근자 프로퍼티다. 따라서 DOM 프로퍼티는 참조와 변경이 가능하다.

 

DOM 프로퍼티

 

사용자가 입력한 최신 상태는 HTML 어트리뷰트에 대응하는 요소 노드의 DOM 프로퍼티가 관리한다.

DOM 프로퍼티는 사용자의 입력에 의한 상태 변화에 반응하여 언제나 최신 상태를 유지한다.

 

DOM 프로퍼티에 값을 할당하는 것은 HTML 요소의 최신 상태 값을 변경하는 것을 의미한다. 사용자가 상태를 

변경하는 행위와 같다. 이때 HTML 요소에 지정한 어트리뷰트 값에는 어떠한 영향도 주지 않는다.

 

Id 어트리뷰트와 id 프로퍼티는 사용자 입력과 관계없이 항상 동일한 값을 유지한다. 어트리뷰트 값이 변하면 id 값도 변하고 반대도 마찬가지로 동작한다.

 

HTML 어트리뷰트와 DOM 프로퍼티의 대응관계

 

HTML 어트리뷰트 이름과 동일한 DOM 프로퍼티 1:1로 대응한다. 단 다음과 같이 HTML 언제나 1대1 대응하는것은 아니며 반드시 일치하는 것도 아니다.

 

Class 어트리뷰트는 className, classList프로퍼티와 대응한다.

for어트리뷰트는 htmlFor 프로퍼티와 1대1 대응한다.

Td 요소의 colspan어트리뷰트는 대응하는 프로퍼티가 존재하지 않는다.

 

DOM 프로퍼티 값의 타입

 

getAttribute 메서드로 취득한 어트리뷰트 값은 언제나 문자열이다. 하지만.DOM 프로퍼티로 취득한 최신 상태 값은 문자열이 아닐 수 있다. 예를들어 checkbox요소의 checked의 값은 문자열 이지만 프로퍼티 값은 불리언 타입이다.

 

39.7.4 data 어트리뷰트와 dataset 프로퍼티

 

Data 어트리뷰트와 dataset 프로퍼티를 사용하면 HTML 요소에 정의한 사용자 정의 어트리뷰트와 자바스크립트 간

데이터를 교환 할 수 있다. Data 어트리뷰트는 data-user-id, data-role 과 같이 data- 접두사 다음에 임의의 이름을 붙여 사용한다.

 

Data 어트리뷰트 값은 HTMLElement.dataset 프로퍼티를 이용하여 가져올 수 있다. 

Data- 뒤의 이름을 카멜케이스로 변환한 프로퍼티 값을 가지고 있다. 이를 통해 값을 취득, 변경 있다.

 

Data 어트리뷰트의 data-접두사 다음에 존재하지 않는 값을 키로 사용하여 할당하면.HTML 요소에 어트리뷰트가 추가되고 이때 추가한 카멜케이스의 프로퍼티 키는 data- 다음의 케밥케이스로 자동 변경되어 추가된다.

 

39.8 스타일 

 

39.8.1 인라인 스타일 조작

 

HTMLElement.prototype.style 프로퍼티는 getter 와 setter 모두 존재하며 ,요소 노드의 인라인 스타일을 취득, 추가, 변경 할 수 있다.

기본 객체는 카멜케이스를 통해서 따르며, 프로퍼티를 그대로 사용하기 위해서는 대괄호 표기법을 사용해야 한다.

['background-color']와 같이 사용 할 수 있음.

 

39.8.2 클래스 조작

 

const Box = document.querySelector(".box");

Box.className.replace("red", "blue");
Box.classList.append("asdf");

 

classList 의 경우 경우 DOMTokenList 객체를 반환하고 유사 배열 객체 이면서 이터러블한 객체로 유용한 메서드들을 제공한다.

 

add (name);

remove(name);

item(idx);

contains(name);

replace(target, to);

toggle(className[, ]);

 

39.8.3 요소에 적용되어 있는 CSS 스타일 참조 

 

style클래스는 인라인 스타일만 반환 함으로 클래스로 적용된 속성이나, 상속을 통해 암묵적으로 적용된 값은 가져오지 못한다.

따라서 위와 같은 경우가 필요할 때 getComputedStyle이라는 메서드를 사용한다 이때 

최종적으로 적용되어 있는 모든 스타일을 가져올 수 있음으로 요소를 지정하여 가져올 수 있다는 장점이 존재한다.

 

39.9 DOM 표준

 

HTML 과 DOM 표준은 W3C 와 WHATWG 에서 만들어 왔으나 별개의 표준이 만들어졌고 이는 이롭지 않다고 판단되어 

4개의 주류 벤더사가 주도하는 WHATWG에서 단일 표준을 내놓게 되었다.