반응형
DOM 요소 선택이란?
DOM 요소 선택은 HTML 문서에서 특정 요소를 JavaScript로 가져오는 과정입니다. 요소를 선택해야 내용을 변경하거나 이벤트를 추가할 수 있습니다.
🔍 기본 HTML 예제
<div id="header" class="main-header">
<h1 class="title">제목</h1>
<nav>
<ul class="menu">
<li><a href="#home">홈</a></li>
<li><a href="#about">소개</a></li>
</ul>
</nav>
</div>
<p class="description">설명문</p>
이 HTML에서 다양한 방법으로 요소를 선택할 수 있습니다.
getElementById - ID로 선택
getElementById()는 ID 속성으로 하나의 요소를 선택하는 가장 기본적이고 빠른 방법입니다.
기본 문법
// 문법
document.getElementById('아이디명')
// 사용 예제
let header = document.getElementById('header');
console.log(header); // <div id="header" class="main-header">...</div>
특징과 활용
// ID는 문서에서 유일해야 함
let headerElement = document.getElementById('header');
if (headerElement) {
// 요소가 존재할 때만 조작
headerElement.style.backgroundColor = 'lightblue';
headerElement.textContent = '새로운 헤더';
}
// 존재하지 않는 ID
let nonExistent = document.getElementById('not-exist');
console.log(nonExistent); // null
실행 결과:
<div id="header" class="main-header">...</div>
null
장점과 단점
✅ 장점:
- 가장 빠른 선택 방법
- 간단하고 직관적
- 모든 브라우저 지원
❌ 단점:
- ID로만 선택 가능
- 하나의 요소만 반환
- 복잡한 선택 불가능
querySelector/querySelectorAll - CSS 선택자
querySelector()와 querySelectorAll()는 CSS 선택자를 사용해 요소를 선택하는 강력하고 유연한 방법입니다.
querySelector - 첫 번째 요소만 선택
// 클래스 선택
let title = document.querySelector('.title');
// ID 선택 (getElementById와 동일한 결과)
let header = document.querySelector('#header');
// 태그 선택
let firstParagraph = document.querySelector('p');
// 복합 선택자
let firstMenuItem = document.querySelector('.menu li');
// 속성 선택자
let homeLink = document.querySelector('a[href="#home"]');
console.log(title); // <h1 class="title">제목</h1>
console.log(firstMenuItem); // <li><a href="#home">홈</a></li>
querySelectorAll - 모든 일치 요소 선택
// 모든 li 요소 선택
let allMenuItems = document.querySelectorAll('.menu li');
console.log(allMenuItems.length); // 2
// NodeList를 배열처럼 사용
allMenuItems.forEach((item, index) => {
console.log(`${index + 1}번째 메뉴:`, item.textContent);
});
// 모든 a 태그 선택
let allLinks = document.querySelectorAll('a');
for (let link of allLinks) {
console.log('링크:', link.href);
}
실행 결과:
<h1 class="title">제목</h1>
<li><a href="#home">홈</a></li>
2
1번째 메뉴: 홈
2번째 메뉴: 소개
링크: #home
링크: #about
다양한 CSS 선택자 활용
// 자식 선택자
let directChild = document.querySelector('nav > ul');
// 인접 형제 선택자
let nextElement = document.querySelector('h1 + nav');
// 속성 선택자
let externalLinks = document.querySelectorAll('a[href^="http"]');
// 가상 선택자
let firstChild = document.querySelector('li:first-child');
let lastChild = document.querySelector('li:last-child');
// 복잡한 선택자
let specificLink = document.querySelector('.menu li:nth-child(2) a');
기타 선택 메서드
DOM에는 다른 선택 메서드들도 있지만, 현재는 잘 사용되지 않습니다.
getElementsByClassName
// 클래스로 선택 (HTMLCollection 반환)
let titles = document.getElementsByClassName('title');
console.log(titles[0]); // 첫 번째 요소
// querySelector와 비교
let titleQuery = document.querySelector('.title'); // 하나만
let titlesQuery = document.querySelectorAll('.title'); // NodeList
getElementsByTagName
// 태그로 선택
let allParagraphs = document.getElementsByTagName('p');
let allDivs = document.getElementsByTagName('div');
// 특정 요소 내에서 선택
let menuItems = document.getElementById('header')
.getElementsByTagName('li');
HTMLCollection vs NodeList
// HTMLCollection (살아있는 컬렉션)
let liveCollection = document.getElementsByClassName('menu');
// NodeList (정적 컬렉션)
let staticList = document.querySelectorAll('.menu');
// 차이점 확인
console.log('Live:', liveCollection.length); // 1
console.log('Static:', staticList.length); // 1
// 새 요소 추가 후
document.body.innerHTML += '<div class="menu">새 메뉴</div>';
console.log('Live:', liveCollection.length); // 2 (자동 업데이트)
console.log('Static:', staticList.length); // 1 (변경 없음)
성능 비교 및 선택 기준
📊 성능 순서 (빠른 순)
- getElementById ⚡ (가장 빠름)
- getElementsByClassName
- getElementsByTagName
- querySelector
- querySelectorAll (가장 느림)
🎯 언제 어떤 것을 사용할까?
getElementById 사용 시기
// ✅ ID가 있고 하나의 요소만 필요할 때
let loginButton = document.getElementById('login-btn');
let mainContent = document.getElementById('main-content');
querySelector 사용 시기
// ✅ CSS 선택자가 필요할 때
let firstActiveTab = document.querySelector('.tab.active');
let submitButton = document.querySelector('form button[type="submit"]');
// ✅ 복잡한 선택이 필요할 때
let errorMessage = document.querySelector('.form-group.error .message');
querySelectorAll 사용 시기
// ✅ 여러 요소를 처리해야 할 때
let allButtons = document.querySelectorAll('button');
let formInputs = document.querySelectorAll('input, textarea, select');
allButtons.forEach(button => {
button.addEventListener('click', handleClick);
});
실무 활용 패턴
1. 안전한 요소 선택
// 요소 존재 확인 후 조작
function safeElementUpdate(selector, callback) {
let element = document.querySelector(selector);
if (element && typeof callback === 'function') {
callback(element);
}
}
// 사용 예제
safeElementUpdate('#status', (element) => {
element.textContent = '로딩 완료';
element.classList.add('success');
});
2. 여러 요소 일괄 처리
// 모든 버튼에 이벤트 추가
function setupButtons() {
let buttons = document.querySelectorAll('.action-btn');
buttons.forEach(button => {
button.addEventListener('click', (e) => {
let action = e.target.dataset.action;
console.log(`${action} 버튼 클릭됨`);
});
});
}
// 폼 입력 필드 초기화
function clearForm(formSelector) {
let inputs = document.querySelectorAll(`${formSelector} input, ${formSelector} textarea`);
inputs.forEach(input => input.value = '');
}
clearForm('#contact-form');
3. 동적 요소 선택
// 데이터 속성으로 선택
function updateStatus(userId, status) {
let userElement = document.querySelector(`[data-user-id="${userId}"]`);
if (userElement) {
userElement.querySelector('.status').textContent = status;
}
}
// 조건부 스타일 적용
function highlightErrors() {
let invalidInputs = document.querySelectorAll('input:invalid');
let validInputs = document.querySelectorAll('input:valid');
invalidInputs.forEach(input => input.classList.add('error'));
validInputs.forEach(input => input.classList.remove('error'));
}
4. 성능 최적화 패턴
// 한 번 선택해서 재사용
class ComponentManager {
constructor() {
this.elements = {
header: document.getElementById('header'),
nav: document.querySelector('nav'),
content: document.getElementById('content'),
footer: document.querySelector('footer')
};
}
updateHeader(title) {
if (this.elements.header) {
this.elements.header.querySelector('h1').textContent = title;
}
}
showContent(html) {
if (this.elements.content) {
this.elements.content.innerHTML = html;
}
}
}
let pageManager = new ComponentManager();
5. 이벤트 위임 패턴
// 부모 요소에서 이벤트 처리 (성능 향상)
document.getElementById('todo-list').addEventListener('click', (e) => {
if (e.target.classList.contains('delete-btn')) {
// 삭제 버튼 클릭
e.target.closest('li').remove();
} else if (e.target.classList.contains('edit-btn')) {
// 수정 버튼 클릭
let li = e.target.closest('li');
editTodoItem(li);
}
});
마무리
DOM 요소 선택은 JavaScript 웹 개발의 첫 번째 단계입니다. 올바른 선택 방법을 사용하면 효율적이고 안정적인 웹 애플리케이션을 만들 수 있습니다.
'JavaScript > DOM 조작' 카테고리의 다른 글
| JavaScript 실습: 버튼 클릭 시 배경 색 바꾸기 - 단계별 가이드 (1) | 2025.06.24 |
|---|---|
| JavaScript DOM 조작 - 내용 변경, 스타일 변경, 클래스 조작 가이드 (0) | 2025.06.24 |
| DOM이란? 기본 개념 - JavaScript로 웹페이지 조작하기 (0) | 2025.06.24 |