DOM API와 DOM에 접근하기
1. DOM API란?

DOM은 Document Object Model의 약자로, 웹 페이지의 구조를 표현하는 객체 모델 입니다. DOM은 HTML 문서의 내용을 트리 형태로 구조화하여 웹페이지와 프로그래밍 언어인 자바스크립트를 연결시켜주는 역할을 합니다. 따라서 자바스크립트를 이용하여 웹 페이지의 요소를 조작할 수 있습니다.
DOM트리를 구성하는 기본 단위를 노드(node) 라고 합니다. 모든 HTML 문서는 이러한 노드들을 계층이 있는 트리 구조로 표현합니다.
CODE | DOM TREE |
---|---|
![]() | ![]() |
DOM API는 이러한 DOM을 조작하기 위한 메서드와 속성들을 제공하는 인터페이스입니다. 자바스크립트는 DOM API를 통해 HTML 문서의 요소에 접근하고 조작할 수 있습니다. DOM에 새로운 요소를 추가하거나, 기존 요소를 삭제할 수 있고 노드에 접근하여 속성이나 스타일을 변경할 수 있습니다. 예를 들어, 자바스크립트를 사용하여 DOM 트리의 특정 노드에 접근하고, 해당 노드의 텍스트를 변경하거나, 새로운 HTML 요소를 추가하는 등의 작업을 수행할 수 있습니다.
API란 무엇인가요?
API는 Application Programming Interface의 약자로, 프로그램 간에 상호작용할 수 있도록 도와주는 인터페이스입니다. 서로 다른 프로그램이 소통할 수 있도록 규칙을 정해놓은 것입니다. 예를 들어, 우리가 웹 페이지를 만들 때 자바스크립트를 사용하여 HTML 요소를 조작하는데, 이때 자바스크립트와 HTML 문서 간의 상호작용을 가능하게 해주는 것이 DOM API입니다.
API는 '키오스크'의 역할을 합니다. 고객은 키오스크를 통해서 원하는 메뉴를 요청하고, 주방은 그에 맞는 요리를 만들어 제공합니다. 이런 방식으로 고객은 주방의 복잡한 작업 과정을 알 필요 없이 원하는 결과물을 얻을 수 있습니다.
2. 요소에 접근하기
현재 웹 페이지의 HTML 문서를 나타내는 document
객체를 통해 DOM API에 접근할 수 있습니다. document
객체는 DOM API의 진입점 역할을 하며, HTML 문서의 구조를 표현하는 트리 형태로 구성되어 있습니다. 이 트리 구조를 통해 HTML 요소에 접근하고 조작할 수 있습니다.
<!DOCTYPE html>
<html>
<head>
<title>My Document</title>
</head>
<body>
<h1>Hello, World!</h1>
<p>This is a paragraph.</p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>My Document</title>
</head>
<body>
<h1>Hello, World!</h1>
<p>This is a paragraph.</p>
</body>
</html>
2.1 단일 요소 선택하기
getElementById
해당하는 ID로 요소를 선택합니다.
const element = document.getElementById('myId');
console.log(element); // <div id="myId">...</div>
const element = document.getElementById('myId');
console.log(element); // <div id="myId">...</div>
querySelector
CSS 선택자를 사용하여 단일 요소에 접근합니다. 선택자에 일치하는 첫 번째 요소를 반환합니다.
const element = document.querySelector('button.myClass');
console.log(element); // <button class="myClass">...</button>
const element = document.querySelector('button.myClass');
console.log(element); // <button class="myClass">...</button>
2.2 다중 요소 선택하기
getElementsByClassName
해당하는 클래스를 가진 모든 요소에 접근합니다.
const elements = document.getElementsByClassName('myClass');
console.log(elements); // HTMLCollection(2) [div.myClass, div.myClass]
const elements = document.getElementsByClassName('myClass');
console.log(elements); // HTMLCollection(2) [div.myClass, div.myClass]
getElementsByTagName
해당하는 태그 이름을 가진 모든 요소에 접근합니다.
const elements = document.getElementsByTagName('p');
console.log(elements); // HTMLCollection(2) [p, p]
const elements = document.getElementsByTagName('p');
console.log(elements); // HTMLCollection(2) [p, p]
querySelectorAll
CSS 선택자를 사용하여 여러 요소에 접근합니다.
const elements = document.querySelectorAll('.myClass');
console.log(elements); // NodeList(2) [div.myClass, div.myClass]
const elements = document.querySelectorAll('.myClass');
console.log(elements); // NodeList(2) [div.myClass, div.myClass]
HTMLCollection과 NodeList
getElementsBy-
메소드와 querySelectorAll
메소드는 조건에 일치하는 모든 요소를 찾는다는 공통적인 기능을 수행합니다. 하지만 결과를 콘솔창에서 확인하면 조금 다르다는것을 알게 됩니다.
<ul id="member-list">
<li>라이캣</li>
<li>빙키</li>
<li>개리</li>
<li>뮤라</li>
</ul>
<script>
const getItems = document.getElementsByTagName('li');
const queryItems = document.querySelectorAll('li');
console.log(getItems);
console.log(queryItems);
</script>
<ul id="member-list">
<li>라이캣</li>
<li>빙키</li>
<li>개리</li>
<li>뮤라</li>
</ul>
<script>
const getItems = document.getElementsByTagName('li');
const queryItems = document.querySelectorAll('li');
console.log(getItems);
console.log(queryItems);
</script>
getElementsBy-
의 결과는 HTMLCollection
이고, querySelectorAll
의 결과는 NodeList
입니다.

HTMLCollection
과 NodeList
는 모두 배열과 비슷한 객체(array-like object) 형태를 가집니다. 요소에 접근하기 위해서 배열처럼 인덱스를 사용한다는 공통점이 있지만, 몇 가지 차이점이 있습니다.
- 해당 객체에 포함될 수 있는 요소의 유형
- HTMLCollection : HTML 요소만 포함
- NodeList : 모든 종류의 노드 포함 - HTML 요소, 텍스트 노드, 주석 노드
<div id="container">
<!-- 여기는 주석입니다 -->
텍스트 노드입니다
<p>첫 번째 문단</p>
<p>두 번째 문단</p>
</div>
<div id="container">
<!-- 여기는 주석입니다 -->
텍스트 노드입니다
<p>첫 번째 문단</p>
<p>두 번째 문단</p>
</div>
const container = document.getElementById('container');
const htmlCollection = container.getElementsByTagName('*');
const nodeList = container.childNodes;
console.log(htmlCollection); // HTMLCollection(3) [p, p]
console.log(nodeList); // NodeList(5) [#text, #comment, p, #text, p]
const container = document.getElementById('container');
const htmlCollection = container.getElementsByTagName('*');
const nodeList = container.childNodes;
console.log(htmlCollection); // HTMLCollection(3) [p, p]
console.log(nodeList); // NodeList(5) [#text, #comment, p, #text, p]
- 정적 vs 동적
- HTMLCollection : 동적 - DOM이 변경되면 자동으로 업데이트
- NodeList : 정적 - DOM이 변경되어도 업데이트되지 않음
const container = document.getElementById('container');
const htmlCollection = container.getElementsByTagName('p');
const nodeList = container.querySelectorAll('p');
console.log(htmlCollection); // HTMLCollection(2) [p, p]
console.log(nodeList); // NodeList(2) [p, p]
// 새로운 요소 추가
const newElement = document.createElement('p');
newElement.textContent = '세 번째 문단';
container.appendChild(newElement);
console.log(htmlCollection); // HTMLCollection(3) [p, p, p]
console.log(nodeList); // NodeList(2) [p, p]
const container = document.getElementById('container');
const htmlCollection = container.getElementsByTagName('p');
const nodeList = container.querySelectorAll('p');
console.log(htmlCollection); // HTMLCollection(2) [p, p]
console.log(nodeList); // NodeList(2) [p, p]
// 새로운 요소 추가
const newElement = document.createElement('p');
newElement.textContent = '세 번째 문단';
container.appendChild(newElement);
console.log(htmlCollection); // HTMLCollection(3) [p, p, p]
console.log(nodeList); // NodeList(2) [p, p]
-
메소드 사용 가능 여부
- HTMLCollection : forEach, map, filter 등의 배열 메소드 사용 불가
- NodeList : forEach, map, filter 등의 배열 메소드 사용 가능
const nodeList = document.querySelectorAll('li'); nodeList.forEach((item) => { console.log(item.textContent); });
const nodeList = document.querySelectorAll('li'); nodeList.forEach((item) => { console.log(item.textContent); });
HTMLCollection에서
forEach
를 사용하려면 배열로 변환해야 합니다.const htmlCollection = document.getElementsByTagName('li'); const itemsArray = Array.from(htmlCollection); itemsArray.forEach((item) => { console.log(item.textContent); });
const htmlCollection = document.getElementsByTagName('li'); const itemsArray = Array.from(htmlCollection); itemsArray.forEach((item) => { console.log(item.textContent); });
이렇게 선택한 DOM 요소를 통해 HTML 문서의 내용을 조작할 수 있습니다. 다음 챕터에서 DOM 요소를 조작하는 방법에 대해 알아보겠습니다.
3. 요소 탐색
DOM 트리에서 특정 요소를 선택한 후, 해당 요소의 자식, 부모, 형제 요소에 접근할 수 있는 메서드들이 있습니다. 이러한 메서드를 사용하여 DOM 트리를 탐색할 수 있습니다.
3.1 부모 요소 탐색하기
parentElement
를 사용하여 부모 요소에 접근할 수 있습니다. parentElement
는 선택한 요소의 부모 요소를 반환합니다. 만약 선택한 요소가 최상위 요소라면 null을 반환합니다.
<div id="parent">
<!-- 주석입니다. -->
텍스트입니다.
<div class="child">Hello</div>
<div class="child">World</div>
</div>
<div id="parent">
<!-- 주석입니다. -->
텍스트입니다.
<div class="child">Hello</div>
<div class="child">World</div>
</div>
const childElement = document.querySelector('.child');
const parentElement = childElement.parentElement;
console.log(parentElement); // <div class="parent">...</div>
const childElement = document.querySelector('.child');
const parentElement = childElement.parentElement;
console.log(parentElement); // <div class="parent">...</div>
3.2 자식 요소 탐색하기
children
children
을 사용하여 자식 요소에 접근할 수 있습니다. children
은 선택한 요소의 자식 요소를 HTMLCollection 형태로 반환합니다.
const parentElement = document.querySelector('.parent');
const childElements = parentElement.children;
console.log(childElements); // HTMLCollection(2) [div.child, div.child]
const parentElement = document.querySelector('.parent');
const childElements = parentElement.children;
console.log(childElements); // HTMLCollection(2) [div.child, div.child]
firstElementChild와 lastElementChild
firstElementChild
와 lastElementChild
를 사용하여 첫 번째 자식 요소와 마지막 자식 요소에 접근할 수 있습니다. 이 메서드는 선택한 요소의 첫 번째 또는 마지막 자식 요소를 반환합니다.
const parentElement = document.querySelector('.parent');
const firstChild = parentElement.firstElementChild;
const lastChild = parentElement.lastElementChild;
console.log(firstChild); // <div class="child">Hello</div>
console.log(lastChild); // <div class="child">World</div>
const parentElement = document.querySelector('.parent');
const firstChild = parentElement.firstElementChild;
const lastChild = parentElement.lastElementChild;
console.log(firstChild); // <div class="child">Hello</div>
console.log(lastChild); // <div class="child">World</div>
childNodes
childNodes
를 사용하면 모든 자식 노드를 NodeList로 반환합니다. 이 때, NodeList는 동적으로 변경됩니다. 즉, 자식 노드가 추가되거나 삭제되면 NodeList도 자동으로 업데이트됩니다.
const parentElement = document.querySelector('.parent');
const childNodes = parentElement.childNodes;
console.log(childNodes); // NodeList(7) [#text, #comment, #text, div.child, #text, div.child, #text]
const parentElement = document.querySelector('.parent');
const childNodes = parentElement.childNodes;
console.log(childNodes); // NodeList(7) [#text, #comment, #text, div.child, #text, div.child, #text]
3.3 형제 요소 탐색하기
nextElementSibling
과 previousElementSibling
을 사용하여 형제 요소에 접근할 수 있습니다. nextElementSibling
은 선택한 요소의 다음 형제 요소를 반환하고, previousElementSibling
은 이전 형제 요소를 반환합니다.
<div id="parent">
<!-- 주석입니다. -->
텍스트입니다.
<div class="child">Hello</div>
<div class="child">World</div>
<div>Hello</div>
<div>Weniv</div>
</div>
<div id="parent">
<!-- 주석입니다. -->
텍스트입니다.
<div class="child">Hello</div>
<div class="child">World</div>
<div>Hello</div>
<div>Weniv</div>
</div>
const childElement = document.querySelector('.child');
const previousSibling = childElement.previousElementSibling;
const nextSibling = childElement.nextElementSibling;
console.log(previousSibling); // null
console.log(nextSibling); // <div class="child">World</div>
const childElement = document.querySelector('.child');
const previousSibling = childElement.previousElementSibling;
const nextSibling = childElement.nextElementSibling;
console.log(previousSibling); // null
console.log(nextSibling); // <div class="child">World</div>
모든 형제 요소 탐색하기
parentElement
와 children
을 조합하여 모든 형제 요소를 탐색할 수 있습니다.
const childElement = document.querySelector('.child');
const parentElement = childElement.parentElement;
const siblings = parentElement.children;
for (let i = 0; i < siblings.length; i++) {
if (siblings[i] !== childElement) {
console.log(siblings[i]);
}
}
const childElement = document.querySelector('.child');
const parentElement = childElement.parentElement;
const siblings = parentElement.children;
for (let i = 0; i < siblings.length; i++) {
if (siblings[i] !== childElement) {
console.log(siblings[i]);
}
}
3.4 closest
closest
메서드는 선택한 요소에서 가장 가까운 조상 요소를 찾습니다. 이 메서드는 선택한 요소부터 시작하여 부모 요소를 거슬러 올라가며, 주어진 선택자와 일치하는 첫 번째 조상 요소를 반환합니다. 만약 일치하는 조상 요소가 없다면 null을 반환합니다.
<section class="first">
<div>Hello</div>
<div class="target">World</div>
</section>
<section class="second">
<div>Hello</div>
<div>Weniv</div>
</section>
<section class="first">
<div>Hello</div>
<div class="target">World</div>
</section>
<section class="second">
<div>Hello</div>
<div>Weniv</div>
</section>
const childElement = document.querySelector('.target');
const closestElement = childElement.closest('section');
console.log(closestElement); // <section class="first">...</section>
const childElement = document.querySelector('.target');
const closestElement = childElement.closest('section');
console.log(closestElement); // <section class="first">...</section>