안녕하세요, 코딩하는곰입니다! 오늘은 JavaScript 개발에서 빼놓을 수 없는 DOM 탐색 메서드인 querySelector와 querySelectorAll에 대해 깊이 있게 알아보겠습니다. 이 두 메서드는 CSS 선택자의 강력함을 JavaScript에 그대로 가져와 웹 요소를 정확하게 선택하고 조작할 수 있게 해줍니다. 20년의 JavaScript 개발 경험을 바탕으로 실제 프로젝트에서 활용하는 팁과 함정까지 상세히 설명드리겠습니다.
🌐 웹 개발에 관심이 있다면, (파이썬) 세트(Set) 자료형 완벽 가이드 중복 제거부터 집합 연산까지를 참고해보세요.
querySelector는 CSS 선택자를 사용하여 문서에서 첫 번째로 일치하는 요소를 반환하는 메서드입니다. 기존의 getElementById, getElementsByClassName 등과 비교했을 때 훨씬 더 유연하고 강력한 선택 기능을 제공합니다.
const element = document.querySelector(selector);
여기서 selector는 유효한 CSS 선택자 문자열입니다. document 뿐만 아니라 특정 요소 내에서도 검색이 가능합니다.
// ID로 요소 선택const header = document.querySelector('#header');// 클래스로 요소 선택const button = document.querySelector('.submit-btn');// 태그 이 름으로 선택const firstParagraph = document.querySelector('p');// 복합 선택자const activeListItem = document.querySelector('ul.menu li.active');// 속성 선택자const emailInput = document.querySelector('input[type="email"]');
querySelector의 가장 큰 장점은 CSS에서 사용하던 모든 선택자 패턴을 그대로 사용할 수 있다는 점입니다. 이는 기존에 CSS에 익숙한 개발자들에게 매우 직관적인 API를 제공합니다.
const usernameInput = document.querySelector('#signup-form input[name="username"]');
const firstNewItem = document.querySelector('.dynamic-list .item:first-child');
const activeNavItem = document.querySelector('nav .menu > li.active > a');
querySelector는 단 하나의 요소만 반환하기 때문에, 정확히 하나의 요소를 대상으로 작업해야 할 때 매우 유용합니다. 만 약 일치하는 요소가 없으면 null을 반환하므로, 항상 null 체크를 하는 것이 안전한 코딩 습관입니다.
📚 코딩 지식을 쌓고 싶다면, Java vs Kotlin JVM 개발자의 현실적인 선택 가이드를 참고해보세요.
querySelectorAll은 querySelector와 비슷하지만, 일치하는 모든 요소를 NodeList 형태로 반환합니다. 이 차이는 여러 요소를 동시에 다뤄야 할 때 결정적인 역할을 합니다.
const elements = document.querySelectorAll(selector);
// 모든 버튼 선택const allButtons = document.querySelectorAll('button');// 특정 클래스를 가진 모든 요소const highlightedItems = document.querySelectorAll('.highlight');// 복합 선택자를 가진 모든 요소const menuItems = document.querySelectorAll('nav ul li a');// 의사 클래스 활용const oddRows = document.querySelectorAll('table tr:nth-child(odd)');
querySelectorAll이 반환하는 NodeList는 배열처럼 보이지만 실제 배열은 아닙니다. 따라서 배열 메서드를 직접 사용할 수 없습니다.
const items = document.querySelectorAll('.item');// ❌ 이렇게 사용하면 에러 발생// items.forEach is not a function// items.forEach(item => { ... });// ✅ Array.from()으로 배열 변환const itemsArray = Array.from(items);itemsArray.forEach(item => {console.log(item.textContent);});// ✅ 스프레드 연산자 사용[...items].forEach(item => {console.log(item.textContent);});// ✅ NodeList의 forEach 메서드 사용 (최신 브라우저)items.forEach(item => {console.log(item.textContent);});
const deleteButtons = document.querySelectorAll('.delete-btn');deleteButtons.forEach(button => {button.addEventListener('click', function() {const item = this.closest('.item');item.remove();});});
const errorFields = document.querySelectorAll('.form-field.error');errorFields.forEach(field => {field.style.borderColor = 'red';field.style.backgroundColor = '#ffe6e6';});
const prices = document.querySelectorAll('.product .price');const total = Array.from(prices).reduce((sum, priceElement) => {return sum + parseFloat(priceElement.textContent.replace('$', ''));}, 0);
querySelectorAll을 사용할 때 주의할 점은 반환된 NodeList가 “살아있는(live)” 상태가 아니라는 것입니다. 즉, DOM이 변경되어도 기존 NodeList는 자동으로 업데이트되지 않습니다.
디자인을 해치지 않으면서도 브랜드 이미지를 강조하고 싶다면, 로고 삽입이 가능한 QR 코드 생성기를 활용해보는 것이 좋습니다.
실제 프로젝트에서는 더 정교한 요소 선택이 필요한 경우가 많습니다.
// 자식 선택자와 조합const directChildren = document.querySelectorAll('.parent > .child');// 인접 형제 선택자const nextSibling = document.querySelector('.item + .item');// 일반 형제 선택자const allSiblings = document.querySelectorAll('.item ~ .item');// 가상 클래스 심화 활용const emptyInputs = document.querySelectorAll('input:placeholder-shown');const validEmails = document.querySelectorAll('input[type="email"]:valid');// 사용자 정의 데이터 속성 선택const modalTriggers = document.querySelectorAll('[data-toggle="modal"]');
// ❌ 비효율적 - 너무 일반적임const slow = document.querySelectorAll('.btn');// ✅ 효율적 - 구체적임const fast = document.querySelectorAll('header .navigation .primary-btn');
// 특정 컨테이너 내에서만 검색 범위 제한const container = document.getElementById('app');const items = container.querySelectorAll('.item');
// 이벤트 위임 패턴 사용document.addEventListener('click', function(event) {if (event.target.matches('.dynamic-button')) {handleButtonClick(event.target);}});// 또는 MutationObserver로 동적 요소 감지const observer = new MutationObserver(function(mutations) {mutations.forEach(function(mutation) {mutation.addedNodes.forEach(function(node) {if (node.nodeType === 1 && node.matches('.new-item')) {initializeNewItem(node);}});});});
// 여러 클래스를 동시에 가진 요소 선택const specialItems = document.querySelectorAll('.item.important.featured');// OR 조건 구현 (CSS 선택자만으로는 제한적)const eitherClass = document.querySelectorAll('.class1, .class2');
querySelector와 querySelectorAll은 IE8 이상에서 지원됩니다. 하지만 몇 가지 주의사항이 있습니다:
// IE8에서 :not() 선택자 제한// ❌ IE8에서 작동하지 않음const complexNot = document.querySelectorAll('div:not(.skip)');// ✅ IE8 호환 가능한 방식const allDivs = document.querySelectorAll('div');const filtered = Array.from(allDivs).filter(div => !div.classList.contains('skip'));
이러한 고급 기법들을熟练掌握면 복잡한 DOM 구조에서도 효율적으로 요소를 선택하고 조작할 수 있습니다.
최근 당첨번호와 통계를 한눈에 보고 싶다면, AI 번호 추천과 QR코드 확인이 가능한 지니로또AI를 설치해보세요.
지금까지 querySelector와 querySelectorAll의 모든 것을 자세히 살펴보았습니다. 이 두 메서드는 현대 JavaScript 개발의 핵심 도구로, CSS 선택자의 표현력을 그대로 JavaScript에 가져와 개발 생산성을 크게 향상시킵니다. 하지만 강력한 도구일수록 올바르게 사용하는 것이 중요합니다. 선택자 작성 시 성능을 고려하고, 반환값의 특성을 이해하며, 다양한 브라우저 환경에서의 동작을 검토하는 습관을 기르시기 바랍니다. 다음 시간에는 더 흥미로운 JavaScript 주제로 찾아뵙겠습니다. 코딩하는곰이었습니다!
무거운 앱 대신 가볍게 작동하는 웹 기반 실시간 계산기로 손쉽게 숫자를 처리할 수 있습니다.
