문서 객체 모델(DOM, Document Object Model)은 XML이나 HTML 문서에 접근하기 위한 일종의 인터페이스이다.
이 객체 모델은 문서 내의 모든 요소를 정의하고, 각각의 요소에 접근하는 방법을 제공한다.
웹페이지를 자바스크립트로 제어하기 위한 객체 모델을 의미하며, window 객체의 document 프로퍼티를 통해서 사용할 수 있다.
Window 객체가 창을 의미한다면 Document 객체는 윈도우에 로드된 문서를 의미한다고 할 수 있다.
브라우저가 읽거나 어떤 작업을 할 수 있는 언어가 JavaScript 라고 한다면, DOM은 바로 이 작업이 이루어지는 장소이다. (DOM은 브라우저에 의해 기록되는 모든 것이고, JavaScript는 이를 조작할 수 있는 문법언어일 뿐이다. )
DOM은 W3C의 표준 객체 모델이며, 다음과 같이 계층 구조로 표현된다 ▼
Document 객체는 웹 페이지 그 자체를 의미하며, 웹 페이지에 존재하는 HTML 요소에 접근하고자 할 때는 반드시 Document 객체부터 시작해야 한다.
Document 객체는 HTML 요소와 관련된 작업을 도와주는 다양한 메소드를 제공한다.
Document 메소드
document.getElementsByTagName
문법 )
const elements = document.getElementsByTagName(name);
document.getElementsByClassName
문법)
const elements = document.getElementsByClassName(names);
class의 이름을 이용해서 HTML 요소(element)들을 가져오는 메서드이다.
Document 인터페이스 의 getElementsByClassName메서드는 주어진 클래스 이름을 모두 가진 모든 자식 요소의 배열과 유사한 객체를 반환한다.
복수형태로 가져 온다.
Element.getElementsByClassName()
: 주어진 클래스를 가진 모든 자식 엘리먼트의 실시간 HTMLCollection 을 반환한다.
document.getElementsByClassName()
: 도큐먼트 루트로부터 도큐먼트 전체를 탐색한다는 점을 제외하고는 위와 동일하게 작동한다.
document.getElementById
문법)
document.getElementById(id);
document.querySelector
문법)
document.querySelector(selectors);
CSS 선택자로 요소를 선택하게 해준다. 주의할 점은 선택자에 해당하는 첫번째 요소만 선택한다는 것이다.
ex) document.querySelector('.abc')
: 클래스 값이 abc인 첫번째 요소에 접근
document.querySelectorAll
문법)
elementList = parentNode.querySelectorAll(selectors);
선택자를 만족하는 모든 요소의 목록이 필요하다면 querySelectorAll()을 사용한다.
<form id="userForm">
<input id="username" type="text" value="Kim" />
</form>
위의 코드에서, username
요소를 username
변수에 할당한다고 가정해보자.
1) getElementById
를 사용할 경우 ▼
var username = document.getElementById("username");
2) querySelector
를 사용할 경우 ▼
var username = document.querySelector("#userForm #username");;
추가) querySelector가 getElementById등 보다 더 유연하게 쓰일 수 있는 이유
: 어떤요소를 가져오는지에 따라 상관없이 항상 동일한 API를 쓸 수 있다는점, 구체적으로 요소를 선택할 수 있다는점(CSS문법처럼)
<form id="productForm">
<input id="productOne" class="product" type="text" value="Product 1" />
<input id="productTwo" class="product" type="text" value="Product 2" />
<input id="productThree" class="product" type="text" value="Product 3" />
</form>
위의 코드에서, 모든 product
요소를 products
변수에 할당한다고 가정해보자.
1) getElementsByClassName
을 사용할 경우 ▼
var products = document.getElementsByClassName("product");
2) querySelectorAll
을 사용할 경우 ▼
var products = document.querySelectorAll("#productForm .product");
getElementsByClassName
은 HTMLCollection에 리턴이 되고, querySelectorAll
은 NodeList에 리턴이 된다.HTMLCollection과 Nodelist는 문서 내의 노드들을 가지고 있는 컬렉션이며, 유사배열이다.
length
프로퍼티를 가지기 때문에 객체를 배열처럼 접근할 수 있고(인덱스 접근) 반복문을 돌 수 있다. : getElementsByTagName
, getElementsByClassName
메서드가 반환하는 HTMLCollection 객체는 노드 객체의 상태 변화를 실시간으로 반영하는 살아있는 live DOM 컬렉션 객체이다. 이것은 객체가 스스로 실시간 노드 객체의 상태 변경을 반영함을 의미한다.
: querySelectorAll
등의 메서드가 반환하는 NodeList 객체는 노드 객체의 상태 변화를 반영하지 않는 non-live DOM 컬렉션 객체이다. NodeList는 앞의 HTMLCollection과 다르게 노드가 변경되도 그 상태를 반영하지 않는다.
📌 추가)
: 대개의 경우 NodeList는 라이브(Live) 콜렉션으로 DOM의 변경 사항을 실시간으로 반영한다. 그러나 document.querySelectorAll() 메소드에 의해 반환되는 NodeList는 정적(Static) 콜렉션으로 DOM의 변경 사항이 실시간으로 반영되지 않는다.
Array.map
을 사용하기 위해서는 배열의 메서드인 from
을 활용한다. 따라서 HTMLCollection
과 NodeList
을 편리하게 사용하기 위해서는 배열로 만들어 주는 것이 좋다. 특히 HTMLCollection과 같은 live 객체는 반복문을 순회하면서 노드가 변경되는 경우, 개발자의 의도와는 다른 결과가 발생할 수 있으므로 배열로 바꾸어 사용하는 것이 바람직하다.
❓ 객체를 배열로 만드는 방법
✍️ JS로 그림판을 만들 때 사용했던 Array.from
을 예로 들어보자.
유사배열객체(array-like object)나 반복가능객체(iterable object)를 얕게 복사(shallow copy)하여 새로운 배열(Array) 객체를 만들어 리턴해 준다.
console.log(Array.from('seul'));
// Array ['s', 'e', 'u', 'l']
console.log(Array.from([ 1, 2, 3], x => x + x));
// Array [2, 4, 6]
✍️ 강의에서 HTMLCollection이 왜 나왔는지 궁금해 하셨던 부분이 getElementsByClassName 메서드가 반환하는 HTMLCollection 객체와 관련이 있다는 것을 알았다.
때문에 Array.from 그리고 forEach를 사용해서 컬러배열을 생성하고 원하는 함수를 배열 요소 각각에 실행시키는 것에 대해서 조금이나마 이해가 되었고, 뒤로 갈수록 코드 한줄에 많은 연결고리가 있다는 것을 느꼈다.
DOM내용 중에서도 DOM요소를 선택하는 것과 관련해서 정리를 해보았는데, (사실 그림판을 만들다가 제어대상을 찾는 API, 그리고 Array.from 가 궁금해서 여기까지 온 것이다 😅) DOM을 주제로도 따로 공부해야겠다.
✍️ 어느 자료에서는 getElementsByTagName(name) 이 HTMLCollection 이라고 하고, 또 다른 자료에서는 "인자로 전달된 태그명에 해당하는 객체들을 찾아서 그 리스트를 NodeList라는 유사 배열에 담아서 반환하는 메서드" 라고 하기에 알아봤더니, 최신 W3C 명세에서는 elements 가 HTMLCollection 라고 하지만, WebKit 브라우저에서는 NodeList 를 반환한다고 한다.🧐 MDN
reference
gogori-DOM
JS-document
MDN
chloeee-querySelector
young-HTMLCollection
hianna
basemenks-NodeList
TCPschool-dom