본 글에서는 DOM과 DOM API에 대해 알아보겠습니다.
문서 객체 모델(DOM) 은 웹 브라우저가 HTML 문서를 객체 형태로 변환한 것으로,
자바스크립트 같은 스크립트 언어로 HTML 요소에 접근하고 조작할 수 있게 해줍니다.

document 노드는 HTML 문서 전체를 대표하는 객체로, 다른 요소 노드에 접근할 때 사용하는 진입점 역할을 합니다
DOM API를 사용해서 특정 요소를 변수에 할당할 때에는 일반적으로 요소를 할당할 변수의 이름 앞에 $ 또는 변수 이름 뒤에 element를 작성합니다.
- getElementById
- querySelector
let $color = document.getElementById('color')
let colorElement = document.getElementById('color')
let $animalInfo = document.querySelector('div.animal-info')
let ageElement = document.querySelector('div#age')
- querySelectorAll
- getElementByClassName
- getElementByTagName
let $infoItem = document.querySelectorAll('div.info-item')
let $infoItem = document.getElementByClassName('info-item')
let $infoItem = document.getElementByTagName('div')
- element.className
- element.id
let $name = document.getElementById('name')
$name.className = 'dog-name'
className = property
💬 React 어트리뷰트 네이밍을 DOM property에 따른다고 한다.
React에서는 DOM의 프로퍼티의 이름을 따서 className으로 대신 작성합니다.
let $animalInfo = document.querySelector('div.animal-info')
$animalInfo.id = "animal"
element.classList
특정 요소의 클래스 속성에 접근 가능한 프로퍼티입니다.
추가적으로 add, remove와 같은 다양한 메서드를 제공합니다.
let $color = document.getElementById('color')
console.log($color.classList) // ['info-item', value:'info-item']
let $color = document.getElementById('color')
$color.classList.add('dog-color')
console.log($color.className) // info-item dog-color
className과 classList.add 의 차이점
항목 element.classNameelement.classList.add()기능 클래스 전체 문자열을 설정 특정 클래스를 추가 기존 클래스 유지 ❌ (기존 클래스 덮어씀) ✅ (기존 클래스 유지하며 추가) 다중 클래스 추가 문자열 직접 조작 필요 ✅ add("a", "b")식으로 가능
React에서는?
React는 매 렌더링마다 className을 전체 재설정하므로 classList 방식은 거의 사용되지 않습니다. 외부 라이브러리나 수동 DOM 조작(useRef 등)에서는 classList를 쓸 수 있습니다.
element.textContent
let $age = document.getElementById('age')
$age.textContent = '5'
console.log($age.textContent) // '5'
element.style
let $nameTag = document.querySelector('name-tag')
$nameTag.style.color = 'blue'
$nameTag.style.fontSize = '30px'
- createElement
- createTextNode
- appendChild
DOM 트리 구조
document
|__HTML
| |__body
| | |__div(.dog-info)
| | |__div(.new-dog-info) // 새로 생성된 노드
| | |__textNode('chihuahua') // 새로 생성된 텍스트 노드
|_ |__head
let $newDog = document.crerateElement('div')
$newDog.className = 'new-dog-info'
$newDog.id = 'chihuahua'
let $newDogText.createTextNode(chihuahua)
>
console.log($newDog);
// <div class='info' id='chihuahua'></div>
console.log($newDogText)
// "chihuahua"
// DOM 트리에 요소 추가
let $dogs = document.querySelector('div.dog-info')
$dogs.appendChild($newDog)
$newDog.appendChild($newDogText)
💡 모든 내용을 구성해두고 DOM에 한 번에 붙이기
$dogs.appendChild($newDog) // 텍스트 노드가 추가된 요소 노드를 자식 노드로 추가 => DOM에 붙음 $newDog.appendChild($newDogText) // 텍스트 노드를 자식 노드로 추가 => DOM에 붙음
$newDog.appendChild($newDogText) // 텍스트 노드를 자식 노드로 추가
$dogs.appendChild($newDog) // 텍스트 노드가 추가된 요소 노드를 자식 노드로 추가 => DOM에 붙음
| 비교 항목 | textContent | createTextNode |
|---|---|---|
| 사용 목적 | 요소의 텍스트를 설정하거나 읽기 | 명시적으로 텍스트 노드를 생성 |
| HTML 해석 여부 | 안 됨 (텍스트로 처리됨) | 안 됨 (텍스트로 처리됨) |
| 기존 내용 제거 | 기존 자식 노드를 모두 제거 | 제거하지 않음 (append로 추가만 함) |
| 코드 간결성 | 더 간단함 | 더 세밀한 제어가 가능 |
| DOM 조작 유연성 | 낮음 | 높음 |
기존 자식들을 제거하고 단순 텍스트만 넣을 때 => textContent
복잡한 DOM 트리를 구성할 때 => createTextNode + appendChild
addEventListener
let $button = document.querySelector('button');
$button.addEventListener('click',() => {
window.alert('clicked!');
});
innerHTML
특정 요소의 HTML을 문자열 형태로 읽거나 설정할 수 있음
- 성능이나 보안에 문제가 있기 때문에 주의해야 함
- 대안 : createElement, createTextNode, textContent ...
let $elementNode = document.querySelector('div')
$elementNode.innerHTML = '<div id='test'>안녕하세요</div>'
console.log($elementNode.innerHTML)
//'<div id='test'>안녕하세요</div>'