꼭 정리하겠다고 벼르고 있던 DOM API. 드디어 정리한다.
DOM(Document Object Model)
1. 개념
2. DOM API
3. DOM API 주요 기능
- 요소 선택 : querySelector, querySlectorAll, getElementById
- 요소 다루기
- 이벤트 관리 `addEventListener`
1. 개념 : DOM 이란?
DOM은 HTML 문서 요소의 집합체로, 문서는 각각의 노드와 객체의 집합으로 문서를 표현한다. 웹 페이지가 로드되면, 브라우저는 HTML 문서를 분석하고 DOM을 생성해서 개발자가 자바스크립트를 통해 페이지를 다룰 수 있게 한다.
노드
- 요소 노드(Element Node): HTML 태그 요소 예: <div>, <p>.
- 텍스트 노드(Text Node): HTML 요소 내부의 텍스트
- 속성 노드(Attribute Node): 요소의 속성(예: id, class)
DOM의 역할
- 페이지 구조 표현: HTML 문서를 트리 구조로 표현하여 각 요소와 텍스트를 노드로 관리
- 콘텐츠 및 스타일 변경 가능: JavaScript를 통해 DOM에 접근하여 요소를 추가, 삭제, 수정 가능
- 이벤트 처리 가능: DOM을 통해 사용자 이벤트(클릭, 입력 등)를 처리 가능
2. DOM API
브라우저는 html 문서를 로드하고 DOM 트리를 만든 후, document 객체로 제공한다. DOM API는 DOM을 조작하기 위해 브라우저가 제공하는 도구들로, 자바스크립트로 html 요소를 다룰 수 있다.
console.log(document);
console.log(document.URL);
console.log(document.documentElement);
console.log(document.head);
console.log(document.body);
console.log(document.title);
*API : Application Programming Interface
3. DOM API의 주요 기능
3-1. 요소 선택
- getElementById
- querySelector('CSS선택자') : 문서에서 만나는 제일 첫번째 요소 반환 → 반환값: 태그
- querySlectorAll : 배열(같은) 데이터로 만들어줌 → 반환값: 배열 형태의 노드리스트
- 기타 : getElementByClassName, getElementsByTagName, getElementByName(name 속성값)
3-2. 요소 다루기
- 내용 변경 :`.textContent` `.innerText` `innerHTML`
- 요소의 속성 접근 및 설정 (함수) : `getAttribute()` `setAttribute()`
- 클래스 관리 : `classList` (add, remove, toggle, contains, replace), `className`
- 부모, 자식, 형제 노드 찾기 : `.children` `.parentNode` `.previousElementSiblings`
- 노드 생성, 추가, 삭제:`.createElement` `.append` `.prepend` /`.before` `.after`/ `.remove` `.removeChild`
#내용 변경
/* 1. 태그 내부 내용 변경 */
/**
* -inner Text
* -textContent
* -innerHTML
*/
let div1 = document.getElementById('div1');
div1.innerText = ' 여기는 <b>첫번째</b> 태그입니다.♥ /';
// 2칸이상의 공백문자 제거, 앞뒤로 공백문자 제거
console.log(div1.innerText);
div1.innerHTML = `여기는 <b>첫번째</b> 태그입니다.♥`;
console.log(div1.innerHTML);
div1.textContent = ' 여기는 <b>첫번째</b> 태그입니다.♥ /';
console.log(div1.textContent);
단순히 텍스트만 출력한다면 `innerText`, `textContent` 거의 구분 없이 쓰지만, `textContent`는 모든 공백을 그대로 유지하고 `innerText`는 공백을 제거한다는 차이가 있다. 만약 변경하는 내용에 html 태그나 엔티티 코드가 포함되어 있다면, html 태그를 해석해서 렌더링한 결과를 보여 주는 `innerHTML`을 쓴다.
# 요소의 속성에 접근 및 설정
<!-- 2. 속성 다루기 -->
<a href="https://www.naver.com" id="naver">네이버로 이동</a>
<img src="../../02.css/img/pooh.png" alt="pooh" id="pooh" />
/* 2. 속성에 접근 */
/**
* - 요소.속성명
* - getAttribute(): 속성값 가져오기 (함수; 인자는 1개)
* - setAttribute(): 속성값 설정하기
*/
//pooh, naver 아이디
let naver = document.getElementById('naver');
console.log(naver);
// naver.setAttribute('속성이름', '바꿔줄 속성값') -> 모두 문자열로 전달~!
naver.setAttribute('href', 'http://www.google.com');
console.log(naver.href); //http://www.google.com
console.log(naver.getAttribute('href')); //http://www.google.com
console.log(document.querySelector('#pooh').src);
//setAttribute뿐 아니라 `.속성값`으로도 변경 가능
document.querySelector('#pooh').alt = '푸사진';
#클래스 관리
/* 3. CSS 변경 */
//- h1, li*4개(배열) 가져오기
//-- getElementByID도 가능
let h1 = document.querySelector('h1');
let list = document.querySelectorAll('li');
console.log(h1, list);
//-li태그 배경색 분홍색, 글자색 흰색, 글씨크기 1.3rem -> CSS 속성
//--`style.속성` 또는 `classList.메서드` 이름
for (let el of list) {
// el.style.color = '#fff';
// el.style.backgroundColor = 'pink';
// el.style.fontSize = '1.3rem';
el.classList.add('friends');
}
h1.classList.add('add-h1');
// h1.classList.remove('add-h1');
// h1.classList.toggle('add-h1'); //현재 상태의 반대로 만들어줌 (add+remove)
// 주로 조건문과 함께 쓰임
console.log(h1.classList.contains('add-h1')); //true
console.log(h1.classList.contains('add-h2')); //false
console.log(h1.classList); //선택된 요소의 적용된 클래스 목록 확인
#부모, 자식, 형제 노드 찾기
/* 4. 부모, 자식, 형제 노드 찾기 */
// querySelector, getElementById
let friends = document.querySelector('#friends');
let tigger = document.querySelector('#tigger');
// console.log(friends);
// console.log(tigger);
console.log('--자식 노드 접근--');
//배열 형태로 가져옴
console.log(friends.children);
console.log(friends.children[0]);
console.log('--부모 노드 접근--');
// 배열 형태가 아닌 요소 자체를 가져옴
console.log(tigger.parentNode);
console.log('--형제 노드 접근');
// 배열 형태가 아닌 요소 자체를 가져옴
console.log('이전 형제', tigger.previousElementSibling);
console.log('다음 형제', tigger.nextElementSibling);
#노드의 생성, 추가, 삭제
요소를 생성한 후 선택된 요소의 맨 뒤 자식 요소로 추가할 때, `append` 또는 `appendChild`를 쓸 수 있는데, `append()`는 여러 요소를 한 번에 추가할 수 있어서 추천한다. 추가하는 요소의 이름은 문자열로 전달하는 게 아니라 요소의 이름 자체로 전달하자. 문자열로 전달하면 문자 자체가 출력된다.
아래 코드에서 살펴보면 `container.append(p2, p3, '재밌다!')`에서 요소인 p2와 p3는 문자열로 전달하지 않았고, 마지막에 추가한 자식 요소 '재밌다!'는 화면에 그대로 문자로 출력된다.

/* 5. 노드 생성, 추가, 삭제 */
let container = document.querySelector('.container');
// (1) 요소 생성
let p = document.createElement('p');
p.innerText = '새로 추가된 p';
p.style.fontWeight = '700';
p.style.background = 'red';
p.id = 'append-p';
// (2)요소 추가
console.log(p);
//-- 선택된 요소(container)의 맨 뒤 자식요소로 추가됨
container.append(p);
let p2 = document.createElement('p');
let p3 = document.createElement('p');
//-- 간단 실습 : 각 p2, p3에 글자 요소 추가, 클래스 (p-2, p-3) 추가
p2.innerText = 'p2 점심 뭐 먹지💭';
p3.textContent = 'p3 점심 뭐 먹지💭';
p2.classList.add('p-2');
p3.classList.add('p-3');
console.log(p2, p3);
// container.append(p2);
// container.append(p3);
// container.appendChild(p3);
container.append(p2, p3, '재밌다!'); //⭐️append 추천 >> appendChild
//prepend(): 선택된 요소의 맨 앞자식으로 추가
// friends = documnet.querySelector('#friends')
// 간단 실습 : li 태그 만들고, '캉가', friends 클래스 추가
let li = document.createElement('li');
li.textContent = '캉가';
li.classList.add('friends');
friends.prepend(li);
console.log(h1);
// before()
let h3 = document.createElement('h3'); //문자열 처리 안하면 변수 취급
h3.innerText = 'h3 tag';
h1.before(h3); //h1의 이전 형제로 추가
// after()
let h2 = document.createElement('h2');
h2.innerText = 'h2 tag';
h1.after(h2); //h1의 다음 형제로 추가
삭제는 remove(), removeChild()로 요소 자체에서 직접 호출되기 때문에 문자열로 전달할 필요가 없다.
`firstLi.remove()` `ul.removeChild(firstLi)`와 같이 삭제할 자식 요소를 문자열 처리하지 않고 바로 인수로 전달 할 수 있다.
//-요소 삭제! -> remove(), removeChild()
let firstLi = document.querySelector('li');
// console.log(firstLi); //캉가
let ul = firstLi.parentElement;
// console.log(ul);
// firstLi.remove(); // 선택된 요소가 삭제됨
// 삭제할 요소.remove()
ul.removeChild(firstLi);
3-3. 이벤트 관리
element.addEventListener(event, handler, options);
- event: 반응할 이벤트의 종류 (예: 'click', 'keydown', 'mouseover' 등)
- handler: 이벤트가 발생했을 때 실행할 함수 `function(){동작}`
- options: 이벤트에 대한 추가 설정 (선택사항, 예: { once: true })
버튼 4개를 만들어서 `addEventListner` 이벤트 관리에 대해 알아보자. `querySelector()`를 사용해서 html의 요소를 선택해서 가져오자.
/**
* 동작의 종류: click, dbClick, scroll, change, submit, ...
* - addEventListenr(동작의 종류, function(){})
* - <태그 onChange='함수의 이름()', onClick='함수의이름()'></태그>
* on[동작의 종류] 속성으로 이벤트 제어 가능
*/
const btn1 = document.querySelector('.btn--black');
const btn2 = document.querySelector('.btn--green');
const btn3 = document.querySelector('.btn--blue');
const btn4 = document.querySelector('.btn--red');
버튼3에서 `btn3.addEventListener('click', changeColor);`와 같이 함수를 따로 만들어 두고 호출하면 재사용에 용이하다. 이벤트가 일어났을 때만 changeColor함수가 동작하게 하려면, 반드시 괄호를 생략해야한다. `btn3.addEventListener('click', changeColor());`와 같이 괄호를 쓰면 함수가 즉시 호출되어 작동이 되지 않는다.
// **btn1.addEventListener('동작의이름', function(){동작})
btn1.addEventListener('click', function () {
console.log('버튼1이 클릭되었습니다!!');
alert('버튼1을 클릭하셨군요!');
});
//-hover의 반정도만(올릴때만 실행, 이전 상태로 돌아오지 않음) 실행됨
btn1.addEventListener('mouseover', function () {
//this는 자기 자신을 가리킴
// btn1.style.backgroundColor = 'aqua';
this.style.backgroundColor = 'aqua';
});
//**btn2를 눌렀을 때, div를 자식으로 붙이기
const container = document.getElementById('container');
btn2.addEventListener('click', () => {
let div = document.createElement('div');
div.innerText = 'hi!';
div.style.backgroundColor = 'pink';
container.append(div);
});
// **btn3
//만들어진 div의 배경색 변경
//함수 호출 시 괄호 필수적으로 생략
// - 이벤트가 일어났을 때만 적용되려면 chageColor() 이렇게 쓰면 안됨 -> 즉시 호출됨
btn3.addEventListener('click', changeColor);
// btn3.addEventListener('click', changeColor); //재사용 용이
function changeColor() {
const divs = document.querySelectorAll('#container div');
// [div, div, div, ...]
for (let div of divs) {
div.style.backgroundColor = 'skyblue';
}
//막내 요소만 노랑색으로 변경 (나중에 만들어보세요~!)
}
// **btn4
// 클릭 시 배경색 노랑으로 변경, 글자색 검정색으로 변경
btn4.addEventListener('click', changeBtnColor);
function changeBtnColor() {
this.style.backgroundColor = 'yellow';
this.sytle.color = '#000';
}
#클릭 이벤트
사용자가 버튼을 클릭할 때 특정 작업을 수행하도록 하는 경우가 많음
- 예: 버튼 클릭 시 양식 제출, 모달 창 열기, API 호출 등)
const button = document.querySelector("button");
button.addEventListener("click", () => {
console.log("버튼이 클릭되었습니다!");
});
#폼 제출 이벤트 (submit)
폼 데이터 검증이나 제출 전 작업을 추가할 때 많이 사용
- 예: 데이터 유효성 검사, API로 데이터 전송, 사용자에게 알림 표시 등
const form = document.querySelector("form");
form.addEventListener("submit", (event) => {
event.preventDefault(); // 폼 제출 기본 동작 방지
console.log("폼이 제출되었습니다!");
});
아래 예제 코드 중 `e.preventDefault()`를 쓰지 않은 경우, 오늘의 할 일을 입력하고 [Add] 버튼을 눌렀을 때 브라우저가 자동으로 새로고침되어 input 창에 입력한 데이터가 초기화 되고, 내가 추가한 할 일 목록이 입력 창아래에 보이지 않는 문제가 발생한다.

// 폼이벤트
/* 4. [Submit] */
const todoForm = document.querySelector('#todo-form'); //form태그
const todos = document.querySelector('.todos'); //ul태그
todoForm.addEventListener('submit', function (e) {
e.preventDefault();
//브라우저 기본 동작 막기 : 폼이 제출되는 것을 취소! 이벤트 전달을 막는 방법
//새로고침 막음
console.log('submit');
//폼 내부의 input창 선택
const todoInput = document.querySelector('input[name="todo"]');
// console.log(todoInput);
console.dir(todoInput); //요소가 가지고 있는 데이터를 출력
// console.log(todoInput.value); //input창 안에 입력한 내용 (숫자써도 문자열 타입으로 가져옴)
//(!!!) 공백으로 들어오는 문자는 추가되지 않도록
const todo = todoInput.value.trim();
console.log('todo:' + todo); //''
if (todo !== '') {
//''일 때 막아주기!
//선택된 ul태그의 자식으로 <li>todo</li> 붙이기
const li = document.createElement('li');
li.textContent = todo;
todos.append(li);
} else {
alert('오늘의 할 일을 입력해주세요');
}
todoInput.value = '';
});
#입력 이벤트 (input, change)
입력 필드에서 사용자가 입력할 때마다 실시간으로 처리하거나 값이 변경될 때 실행
- 예: 실시간 검색 기능, 입력 데이터 유효성 검사, 입력된 값을 다른 요소에 동적으로 반영
const input = document.querySelector("input");
input.addEventListener("input", (event) => {
console.log("입력값:", event.target.value);
});
#마우스 이벤트 (mouseover, mouseout)
특정 요소에 마우스를 올리거나 뗄 때 동작을 추가
- 예: 사용자 피드백을 위해 요소의 스타일을 변경하거나, 툴팁을 표시할 때 자주 사용
const box = document.querySelector(".box");
box.addEventListener("mouseover", () => {
box.style.backgroundColor = "lightblue";
});
box.addEventListener("mouseout", () => {
box.style.backgroundColor = "";
});
#키보드 이벤트 (keydown, keyup)
키보드 입력을 감지하여 특정 동작을 실행
- 예: 검색 필드에서 Enter를 눌러 검색을 실행하거나, 특정 키로 동작을 트리거하는 기능을 구현할 때 사용
document.addEventListener("keydown", (event) => {
if (event.key === "Enter") {
console.log("엔터 키가 눌렸습니다!");
}
});
#once 옵션
const button = document.querySelector("button");
button.addEventListener("click", () => {
console.log("이 버튼은 한 번만 클릭할 수 있습니다!");
}, { once: true });
참고
-새싹x코딩온 웹개발자 풀스택 과정
-chatGPT (이벤트관리 사용 예제)
'Today I Learned > SeSAC 웹 2기' 카테고리의 다른 글
| [새싹x코딩온] jQuery와 vanillaJS 비교해보기 (0) | 2024.11.16 |
|---|---|
| [새싹x코딩온] JS 유효성 검사 (value === '') 과 (!value)는 같은 의미일까? (1) | 2024.11.12 |
| [새싹x코딩온] JavaScript 표준객체와 내장 함수 (3) | 2024.11.07 |
| [새싹x코딩온] JS 조건문, 반복문 (0) | 2024.11.07 |
| [새싹x코딩온] JavaScript 기초 (3) | 2024.11.07 |