DOM은 HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API 즉 프로퍼티와 메서드를 제공하는 트리 자료구조입니다.
39.1 노드
39.1.1 HTML 요소와 노드 객체
HTML 요소는 HTML 문서를 구성하는 개별적인 요소를 의미합니다.
이는 렌더링 엔진에 의해 파싱되는데 HTML Attr은 Attr node로, HTML text contents는 Text Node로 변환됩니다.
HTML 문서는 HTML 요소들의 집합으로 이뤄지며, HTML 요소는 중첩 관계를 갖습니다. 즉 HTML 요소의 콘텐츠 영역에는 텍스트와 다른 HTML 요소도 포함될 수 있습니다. 이때 모든 노드 객체들은 트리 자료 구조로 구성됩니다.
트리 자료구조
Tree data structore는 노드들의 계층 구조로 이뤄집니다. 즉, 트리 자료구조는 부모 노드와 자식 노드로 구성되어 노드간의 계층적 구조를 표현하는 비선형 자료구조를 말합니다. 트리 자료구조는 하나의 최상위 노드에서 시작합니다.
노드 객체들로 구성된 트리 자료구조를 DOM이라 합니다.
39.1.2 노드 객체의 타입
노드의 예시인데 여기서 중요한 몇가지 노드들이 있습니다.
문서 노드 document node
document객체는 브라우저가 렌더링한 HTML 문서 전체를 가리키는 객체로써 전역 객체 window의 document 프로퍼티에 바인딩되어 있습니다. 그리고 브라우저의 모든 JS 코드는 전역 객체 window를 공유하는데 document 또한 바라보는 것이 하나이기 때문에 1개만 존재합니다.
요소 노드 element node
HTML 요소를 개리키는 객체입니다. 중첩에 의해 부자 관계를 가지며, 이를 통해 정보를 구조화합니다.
어트리뷰트 노드 attribute node
HTML 요소의 Attr을 가리키는 객체로, 지정된 HTML 요소의 요소 노드와 연결되어있습니다. 이를 접근하기 위해서는 요소 노드에 먼저 접근해야 합니다.
텍스트 노드 text node
텍스트 노드는 요소 노드의 자식 노드로 리프 노드입니다.
39.1.3 노드 객체의 상속 구조
노드 객체는 구조와 정보를 제어할 수 있는 DOM API를 사용할 수 있는데, 이를 통해 노드 객체는 자신의 부모, 형제, 자식을 탐색할 수 있고 속성과 텍스트를 조작할 수 있습니다. 노드 객체는 브라우저 환경에서 추가적으로 제공하는 호스트 객체로, 프로토 타입에 의한 상속 구조를 갖습니다.
즉 모든 노드 객체는 Object, EventTarget, Node 인터페이스 상속을 받습니다. 그리고 모든 요소 노드는 Element 인터페이스를 상속 받는데 세분화된 인터페이스를 상속받습니다.
노드의 정보 제공 기능(Node.parentNode … )등은 Node 인터페이스가 제공합니다. 그리고 이벤트에 관련된 기능(EventTarget.addEventListner … )은 EventTarget 인터페이스가 제공합니다.
HTML 요소가 객체화된 요소 노드 객체는 HTML 요소가 갖는 공통적인 기능이 있는데 input 노드 객체와 div 요소 노드 객체는 모두 HTML 요소의 스타일을 나타내는 style 프로퍼티가 있습니다. 이처럼 HTML 요소가 갖는 공통적인 기능은 HTMLElement 인터페이스가 제공합니다.
39.2 요소 노드 취득
39.2.1 id를 이용한 요소 노드 취득
Document.prototype.getElementById 메서드는 id 어트리뷰트 값을 갖는 하나의 요소 노드를 탐색하여 반환합니다. id의 경우 하나만 존재하며, 여러 개 존재할 시 첫 번째 요소 노드반 반환합니다. 만약 없을 시 null을 반환합니다.
HTML 요소에 id 부여 시 동일한 이름의 전역 변수가 암묵적으로 선언되고 해당 노드 객체가 할당되는 부수효과가 있습니다.
만약 이를 삭제할 시 전역 프로퍼티는 삭제되지만 전역 변수는 삭제되지 않습니다.
단, 동일한 이름의 전역 변수가 이미 선언되어있다면 재할당되진 않습니다.
39.2.2 태그 이름을 이용한 요소 노드 취득
Document.prototype/Element.prototype.getElementsByTagName은 인수로 전달한 태그이름을 갖는 모든 노드 요소들을 반환합니다. 이때 반환하는 DOM 컬렉션 객체인 HTMLCollection 객체는 유사 배열 객체이면서 이터러블입니다. 여기서 Document.prototype을 사용할 시 루트노드에서부터 탐색하지만, Element.prototype의 경우 해당 노드에서부터 탐색합니다.
39.2.3 class를 이용한 요소 노드 취득
Document.prototype/Element.prototype.getElementsByClassName은 class 속성값을 갖는 모든 노드를 찾고 반환합니다. 나머진 getElementsByTagName과 동일합니다.
39.2.4 CSS 선택자를 이용한 요소 노드 취득
Document.prototype/Element.prototype.querySelector는 CSS 선택자를 만족시키는 하나의 요소 노드를 탐색하여 반환합니다.
•
결과가 여러개일 시 첫번 째 요소 노드만 반환합니다.
•
없으면 null을 반환합니다.
•
인자가 문법에 맞지 않을 경우 DOMException 에러가 발생합니다.
만약 한 개가 아닌 다수를 반환받고 싶은 경우
Document.prototype/Element.prototype.querySelectorAll을 사용해야합니다. 그리고 NodeList 객체는 유사 배열 객체이면서 이터러블입니다.
단 이 방법의 경우 다른 getElementBy*** 느린 것으로 알려져 있습니다.
39.2.5 특정 요소 노드를 취득할 수 있는지 확인
Element.prototype.matches는 인수로 전달한 CSS 선택자를 통해 특정 요소 노드를 취득할 수 있는지 확인합니다. 이는 이벤트 위임 때 유용합니다.
39.2.6 HTMLCollection과 NodeList
DOM API가 여러 개의 결과값을 반환하기 위한 DOM 컬렉션 객체이며 for…of문으로 순회할 수 있고, 스프레드 문법을 사용해 배열로 변환할 수 있습니다.
HTMLCollection
노드 객체의 상태 변화를 실시간으로 반영하는 살아있는 DOM 컬렉션 객체입니다. 실시간으로 값이 변하기 때문에 반복문을 통한 순회시에 노드 객체 상태 변경시 주의해야합니다. 따라서 이를 바로 사용하지말고 변환후 사용하는 것을 추천합니다.
[...$elems].forEach(elem => elem.className = 'blue');
JavaScript
복사
NodeList
NodeList 객체는 실시간으로 노드 객체의 상태 변경을 반영하지 않습니다. 하지만 childNode 프로퍼티가 반환하는 NodeList 객체는 실시간 반영이므로 주의할 필요가 있습니다.
39.3 노드 탐색
Node.prototype은
•
parentNode
•
previousSibling
•
firstChild
•
childNodes
를 제공합니다.
Element.prototype은
•
previousElemtSibling
•
nextElementSibling
•
child
을 제공합니다.
이들은 모두 접근자 프로퍼티로, setter 없이 getter만 존재합니다.
39.3.1 공백 텍스트 노드
HTML 요소 사이의 공백은 텍스트 노드를 생성하는데 이를 공백 텍스트 노드라고 합니다. 이는 의도치 않은 공백을 생성할 수 있습니다.
39.3.2 자식 노드 탐색
•
Node.prototype.childNodes : 자식 노드 모두를 탐색해 NodeList에 담아 반환하며, 노드와 텍스트 노드 모두를 포함합니다.
•
Element.prototype.children : HTMLCollection에 담아 반환하는데 텍스트 노드가 포함되지 않습니다.
•
Node.prototype.firstChild : 첫 번째 자식 노드를 반환하는데 텍스트 노드이거나 요소 노드입니다.
•
Node.prototype.lastChild : 마지막 자식 노드를 반환하는데 텍스트 노드이거나 요소 노드입니다.
•
Element.prototype.firstElementChild : 첫 번째 요소 노드만 반환합니다.
•
Element.prototype.lastElementChild : 마지막 요소 노드만 반환합니다.
39.3.3 자식 노드 존재 확인
존재확인 시 Node.prototype.hasChildNodes 메서드를 사용합니다. 자식 노드가 존재시 true, 없을 시 false를 반환합니다. 만약 자식 노드 중에 텍스트 노드가 아닌 요소 노드가 존재하는지 확인하려면 children.length나 Element인터페이스의 childElementCount 프로퍼티를 사용합니다.
39.3.4 요소 노드의 텍스트 노드 탐색
요소 노드의 텍스트 노드는 firstChild 프로퍼티로 접근할 수 있습니다. 이 노드는 텍스트 노드이거나 요소 노드입니다.
39.3.5 부모 노드 탐색
Node.prototype.parentNode 프로퍼티를 사용합니다.
39.3.6 형제 노드 탐색
•
Node.prototype.previousSibling : 자신의 이전 형제 노드를 탐색하여 반환합니다. 요소 노드와 텍스트 노드 둘 다 가능합니다
•
Node.prototype.nextSibling : 부모 노드가 같은 형제 노드 중에서 자신의 다음 형제 노드를 탐색하여 반환하는데, 요소 노드와 텍스트 노드 둘 다 가능합니다.
•
Element.prototype.previousElementSibling : 자신의 이전 형제 요소 노드를 탐색하며, 요소 노드만 반환합니다.
•
Element.prototype.nextElmentSibling : 자신의 다음 형제 요소 노드를 탐색하며, 요소 노드만 반환합니다.