TIL

[TIL]JavaScript DOM 조작 완벽 정리

namerong 2026. 4. 14. 14:31

1. DOM(Document Object Model)이란?

DOM은 HTML 문서를 트리 구조의 객체로 표현한 것으로, 자바스크립트를 통해 웹 페이지의 요소를 선택하고 수정할 수 있게 해준다.

이를 통해 동적인 사용자 인터페이스를 구현할 수 있다.


2. DOM 요소 선택

2.1 querySelector와 querySelectorAll

CSS 선택자를 사용하여 요소를 선택하는 가장 현대적이고 일관성 있는 방법이다.

const $apple = document.querySelector('#apple'); // 첫 번째 요소 선택
const $firstFruit = document.querySelector('.fruit'); // 클래스가 fruit인 첫 요소
const $fruits = document.querySelectorAll('.fruit'); // 모든 요소 선택 (NodeList)

$fruits.forEach(item => {
  item.style.border = '1px solid blue';
});
  • querySelector: 조건에 맞는 첫 번째 요소 하나를 반환한다.
  • querySelectorAll: 조건에 맞는 모든 요소를 NodeList로 반환하며 forEach 사용이 가능하다.

2.2 기존 선택 방식과의 차이

const $texts = document.getElementsByClassName('text');
  • getElementsByClassName, getElementsByTagName 등은 HTMLCollection을 반환한다.
  • HTMLCollection은 Live Collection으로 DOM 변경 사항이 실시간으로 반영된다.
  • 반복문에서 요소를 수정할 경우 의도치 않은 결과가 발생할 수 있다.

배열로 변환하여 사용

const textArray = [...$texts];
textArray.forEach(item => item.classList.remove('text'));
  • querySelectorAll은 정적인 NodeList를 반환하여 이러한 문제를 방지할 수 있다.

3. DOM 노드 탐색 (Traversal)

특정 요소를 기준으로 부모, 자식, 형제 요소를 탐색할 수 있다.

3.1 자식 요소 탐색

속성 설명

children 모든 자식 요소 반환
firstElementChild 첫 번째 자식 요소
lastElementChild 마지막 자식 요소

3.2 부모 요소 탐색

const $parent = $me.parentNode;

3.3 형제 요소 탐색

속성 설명

nextElementSibling 다음 형제 요소
previousElementSibling 이전 형제 요소

※ childNodes는 텍스트 노드를 포함하므로 children과 같은 Element 전용 속성 사용을 권장한다.


4. DOM 노드 정보 확인

4.1 nodeType과 nodeName

const $infoArea = document.querySelector('#info-area');
const $textInside = $infoArea.firstChild;

console.log($infoArea.nodeType); // 1: 요소 노드
console.log($textInside.nodeType); // 3: 텍스트 노드
console.log($infoArea.nodeName); // DIV
console.log($textInside.nodeName); // #text

nodeType 의미

1 요소 노드
3 텍스트 노드
9 문서 노드

5. 텍스트 조작

5.1 nodeValue (구식 방식)

const $valueArea = document.getElementById('value-area');
$valueArea.firstChild.nodeValue = 'nodeValue로 변경 완료!';
  • 텍스트 노드에만 적용 가능하여 사용이 번거롭다.

5.2 textContent (권장 방식)

const $contentArea = document.getElementById('content-area');
console.log($contentArea.textContent);
$contentArea.textContent = 'textContent로 쉽게 변경!';
  • 요소에 직접 사용 가능
  • 모든 자손의 텍스트를 포함
  • HTML 태그는 문자열로 처리되어 보안상 안전
  • 성능과 일관성이 뛰어나 현대적인 표준으로 권장된다.

6. DOM 요소 조작 및 추가

6.1 innerHTML

const $area1 = document.querySelector('#area1');
$area1.innerHTML = '<ul><li>새로운 리스트 아이템</li></ul>';
  • HTML 문자열로 요소 내부를 한 번에 교체할 수 있다.
  • 사용자 입력을 그대로 삽입할 경우 XSS 공격에 취약할 수 있으므로 주의가 필요하다.

6.2 insertAdjacentHTML

$area2.insertAdjacentHTML('beforebegin', '<p>div 시작 전</p>');
$area2.insertAdjacentHTML('afterbegin', '<p>div 내부의 가장 앞</p>');
$area2.insertAdjacentHTML('beforeend', '<p>div 내부의 가장 뒤</p>');
$area2.insertAdjacentHTML('afterend', '<p>div 끝난 후</p>');

위치 설명

beforebegin 요소 시작 전
afterbegin 요소 내부의 첫 번째
beforeend 요소 내부의 마지막
afterend 요소 종료 후

6.3 createElement와 appendChild

const $newLi = document.createElement('li');
$newLi.textContent = '콜라';
$drinkList.appendChild($newLi);

DocumentFragment를 활용한 성능 최적화

const fragment = document.createDocumentFragment();
['사이다', '우유', '환타'].forEach(text => {
  const li = document.createElement('li');
  li.textContent = text;
  fragment.appendChild(li);
});
$drinkList.appendChild(fragment);

6.4 기타 노드 조작 메서드

메서드 설명

insertBefore(newNode, referenceNode) 특정 요소 앞에 삽입
appendChild(node) 자식으로 추가 또는 이동
replaceChild(newNode, oldNode) 기존 요소 교체
removeChild(node) 요소 삭제

7. 어트리뷰트(Attribute)와 프로퍼티(Property)

7.1 어트리뷰트 기본 조작

const $input = document.getElementById('username');

// 읽기
const inputValue = $input.getAttribute('value');

// 쓰기
$input.setAttribute('value', 'new-user');

// 존재 여부 확인
$input.hasAttribute('class');

// 삭제
$input.removeAttribute('value');
  • getAttribute: 어트리뷰트 값 읽기
  • setAttribute: 어트리뷰트 값 설정
  • hasAttribute: 존재 여부 확인
  • removeAttribute: 어트리뷰트 삭제

7.2 어트리뷰트 vs 프로퍼티

구분 어트리뷰트(Attribute) 프로퍼티(Property)

의미 HTML에 작성된 초기 값 DOM 객체의 실시간 값
변경 시점 초기 상태 유지 사용자 입력에 따라 변경
접근 방법 getAttribute/setAttribute 요소.프로퍼티
const $nickname = document.getElementById('nickname');

$nickname.oninput = () => {
  console.log('프로퍼티(최신값):', $nickname.value);
  console.log('어트리뷰트(초기값):', $nickname.getAttribute('value'));
};

체크박스 예시

const $checkbox = document.createElement('input');
$checkbox.type = 'checkbox';
$checkbox.setAttribute('checked', '');

console.log($checkbox.getAttribute('checked')); // ''
console.log($checkbox.checked); // true
  • 사용자의 입력 값을 가져올 때는 반드시 프로퍼티(.value, .checked 등) 를 사용해야 한다.

8. data 어트리뷰트와 dataset

HTML 요소에 사용자 정의 데이터를 저장할 때 사용한다.

<li data-board-id="13" data-category-name="맛집"></li>
const $boardList = document.querySelector('.board-list');

$boardList.onclick = (event) => {
  if (event.target.tagName !== 'LI') return;

  const boardId = event.target.dataset.boardId;
  const categoryName = event.target.dataset.categoryName;

  console.log(`선택한 게시글의 ID는 ${boardId}이고, 카테고리는 ${categoryName}이다.`);
};
  • data-이름 형식으로 HTML에 작성
  • 자바스크립트에서는 dataset.이름(카멜케이스)으로 접근

9. CSS 조작하기

9.1 인라인 스타일 조작 (element.style)

const $box1 = document.getElementById('box1');

$box1.style.width = '200px';
$box1.style.height = '100px';
$box1.style.backgroundColor = 'skyblue';
$box1.style.fontSize = '1.5em';
  • 간단한 동적 효과에 유용하지만, 스타일 관리가 어려워질 수 있다.

9.2 클래스 제어 (element.classList)

const $box2 = document.getElementById('box2');
const $changeBtn = document.getElementById('changeBtn');
const $toggleBtn = document.getElementById('toggleBtn');

$changeBtn.onclick = () => {
  $box2.classList.add('circle', 'red-bg', 'big-text');
};

$toggleBtn.onclick = () => {
  const isAdded = $box2.classList.toggle('red-bg');
  console.log(isAdded);
};

console.log($box2.classList.contains('box'));

메서드 설명

add() 클래스 추가
remove() 클래스 제거
toggle() 클래스가 있으면 제거, 없으면 추가
contains() 특정 클래스 존재 여부 확인
  • className은 기존 클래스를 덮어쓰기 때문에 사용에 주의해야 한다.
  • 스타일은 CSS에 정의하고, 자바스크립트에서는 클래스를 제어하는 방식이 가장 효율적이다.

10. 최종 정리

DOM 선택

  • querySelector, querySelectorAll 사용을 권장
  • HTMLCollection은 Live Collection이므로 주의

DOM 탐색

  • children, firstElementChild, nextElementSibling 등 Element 전용 속성 사용

텍스트 조작

  • nodeValue 대신 textContent 사용

DOM 조작

  • 간단한 변경: innerHTML
  • 특정 위치 삽입: insertAdjacentHTML
  • 안전하고 정석적인 방법: createElement + appendChild
  • 성능 최적화: DocumentFragment 활용

어트리뷰트와 프로퍼티

  • 초기값: Attribute (getAttribute)
  • 실시간 값: Property (.value, .checked)

CSS 조작

  • 간단한 스타일 변경: element.style
  • 유지보수에 유리한 방법: classList 활용