DOM 조작과 이벤트 처리 기초
우리는 지금까지 자바스크립트의 기본적인 문법, 데이터를 저장하고 조작하는 방법, 그리고 코드의 흐름을 제어하는 방법에 대해 학습했습니다. 이제 이러한 지식을 바탕으로 웹 페이지와 직접적으로 상호작용하는 방법을 배울 시간입니다. 정적인 HTML 페이지에 동적인 기능을 추가하고, 사용자의 행동에 반응하게 만들려면 어떻게 해야 할까요?
이것을 가능하게 하는 것이 바로 DOM(Document Object Model) 조작과 이벤트 처리입니다. DOM은 웹 페이지의 모든 내용을 자바스크립트가 접근하고 조작할 수 있도록 객체 형태로 표현한 것이며, 이벤트 처리는 사용자의 클릭, 키보드 입력 등 다양한 상호작용에 응답하는 메커니즘입니다. 이번 장에서는 이 두 가지 핵심 개념을 통해 여러분의 웹 페이지에 생명력을 불어넣는 첫걸음을 내디뎌 보겠습니다.
DOM 조작: 웹 페이지의 요소 다루기
웹 브라우저가 HTML 문서를 로드하면, 그 문서는 객체 형태로 구조화되어 메모리에 저장됩니다. 이것이 바로 DOM(Document Object Model) 입니다. DOM은 HTML 문서의 각 요소를 객체(노드)로 표현하고, 이 객체들을 트리(tree) 구조로 연결하여 구성됩니다. 자바스크립트는 이 DOM을 이용하여 HTML 요소의 내용, 스타일, 속성 등을 읽고 변경하며, 새로운 요소를 추가하거나 기존 요소를 삭제할 수 있습니다.
요소 선택하기: 조작의 첫걸음
어떤 HTML 요소를 조작하려면, 먼저 해당 요소를 자바스크립트 코드 내에서 '선택'해야 합니다. 요소를 선택하는 다양한 방법이 있습니다.
-
document.getElementById('id명')
:id
속성 값으로 요소를 선택합니다.id
는 문서 내에서 유일해야 합니다.<h1 id="mainTitle">안녕하세요, DOM 조작!</h1>
// script.js (HTML 파일에 연결된 자바스크립트 파일) const titleElement = document.getElementById('mainTitle'); console.log(titleElement); // <h1 id="mainTitle">...</h1> 요소 객체가 출력됩니다.
-
document.querySelector('CSS 선택자')
: CSS 선택자와 동일한 방식으로 요소를 선택합니다. 조건에 맞는 첫 번째 요소를 반환합니다.<p class="greeting">반갑습니다.</p> <div id="container"> <span class="text">첫 번째 텍스트</span> <span class="text">두 번째 텍스트</span> </div>
const firstParagraph = document.querySelector('p'); // 첫 번째 <p> 태그 const greetingText = document.querySelector('.greeting'); // class가 greeting인 첫 번째 요소 const containerDiv = document.querySelector('#container'); // id가 container인 요소 const firstSpan = document.querySelector('#container .text'); // container 내부의 첫 번째 class="text" span console.log(firstParagraph); console.log(greetingText); console.log(containerDiv); console.log(firstSpan);
-
document.querySelectorAll('CSS 선택자')
: CSS 선택자와 동일한 방식으로 요소를 선택합니다. 조건에 맞는 모든 요소를 NodeList 형태로 반환합니다. (배열과 유사하지만 완전히 같지는 않습니다.forEach
등을 사용할 수 있습니다.)const allSpansInContainer = document.querySelectorAll('#container .text'); console.log(allSpansInContainer); // NodeList(2) [span.text, span.text] allSpansInContainer.forEach(span => { console.log(span.textContent); }); // 결과: // 첫 번째 텍스트 // 두 번째 텍스트
요소 내용 조작하기
선택한 요소의 텍스트 내용이나 HTML 내용을 변경할 수 있습니다.
element.textContent
: 요소 내부의 텍스트 콘텐츠를 가져오거나 설정합니다. HTML 태그는 순수한 텍스트로 처리됩니다.element.innerHTML
: 요소 내부의 HTML 콘텐츠를 가져오거나 설정합니다. HTML 태그가 포함된 문자열을 할당하면 브라우저가 이를 HTML로 파싱하여 렌더링합니다.<p id="myParagraph">원래 텍스트</p> <div id="myDiv"></div>
const paragraph = document.getElementById('myParagraph'); const myDiv = document.getElementById('myDiv'); // textContent 변경 paragraph.textContent = "새로운 텍스트입니다!"; console.log(paragraph.textContent); // 결과: 새로운 텍스트입니다! // innerHTML 변경 (HTML 태그 포함) myDiv.innerHTML = "<h2>새로운 제목</h2><p>이것은 <b>HTML</b>입니다.</p>";
innerHTML
은 편리하지만, 사용자 입력을 그대로innerHTML
에 넣는 것은 보안상 취약점(XSS 공격)을 야기할 수 있으므로 주의해야 합니다. 순수한 텍스트만 변경할 때는textContent
를 사용하는 것이 안전합니다.
요소 속성(Attribute) 조작하기
HTML 요소의 속성(예: src
, href
, class
, id
등)을 가져오거나 설정할 수 있습니다.
element.getAttribute('속성명')
: 특정 속성의 값을 가져옵니다.element.setAttribute('속성명', '값')
: 특정 속성의 값을 설정합니다.element.removeAttribute('속성명')
: 특정 속성을 제거합니다.<img id="myImage" src="image1.jpg" alt="첫 번째 이미지"> <a id="myLink" href="https://www.google.com">Google로 이동</a>
const image = document.getElementById('myImage'); const link = document.getElementById('myLink'); // src 속성 값 가져오기 console.log(image.getAttribute('src')); // 결과: image1.jpg // src 속성 값 변경 image.setAttribute('src', 'image2.png'); image.setAttribute('alt', '두 번째 이미지'); // href 속성 값 변경 link.setAttribute('href', 'https://www.naver.com'); link.textContent = "Naver로 이동"; // 링크 텍스트도 변경 // class 속성 추가/제거 (class는 특별히 classList 메서드를 주로 사용) // image.removeAttribute('alt'); // alt 속성 제거
클래스(Class) 조작: classList
요소의 class
속성은 스타일링에 매우 중요하며, 자바스크립트에서는 classList
속성을 통해 편리하게 조작할 수 있습니다.
element.classList.add('클래스명')
element.classList.remove('클래스명')
element.classList.toggle('클래스명')
(있으면 제거, 없으면 추가)element.classList.contains('클래스명')
(해당 클래스가 있는지 확인, 불리언 반환)<button id="myButton" class="btn">클릭하세요</button>
/* style.css */ .btn { padding: 10px 20px; background-color: blue; color: white; } .active { background-color: green; font-weight: bold; }
const button = document.getElementById('myButton'); button.classList.add('active'); // 'active' 클래스 추가 console.log(button.className); // 결과: "btn active" button.classList.remove('btn'); // 'btn' 클래스 제거 console.log(button.className); // 결과: "active" button.classList.toggle('active'); // 'active' 클래스 제거 console.log(button.className); // 결과: "" button.classList.toggle('active'); // 'active' 클래스 다시 추가 console.log(button.classList.contains('active')); // 결과: true
요소 스타일(CSS) 조작하기
자바스크립트로 직접 요소의 CSS 스타일을 변경할 수 있습니다. element.style.속성명
형식으로 접근합니다. CSS 속성 이름이 하이픈(-
)으로 연결되어 있다면, 자바스크립트에서는 카멜 케이스(camelCase)로 변환하여 사용해야 합니다.
<p id="styledParagraph">이 문단은 스타일이 바뀔 것입니다.</p>
const styledParagraph = document.getElementById('styledParagraph');
styledParagraph.style.color = 'red'; // 글자색 변경
styledParagraph.style.fontSize = '20px'; // 글자 크기 변경
styledParagraph.style.backgroundColor = 'lightgray'; // 배경색 변경 (CSS: background-color)
하지만, 인라인 스타일로 직접 조작하는 것보다는 CSS 클래스를 토글하여 스타일을 변경하는 것이 더 효율적이고 유지보수가 용이합니다.
새로운 요소 생성 및 추가/제거하기
DOM API를 사용하여 완전히 새로운 HTML 요소를 생성하고, 문서에 추가하거나 제거할 수 있습니다.
document.createElement('태그명')
: 새로운 HTML 요소를 생성합니다.부모요소.appendChild(자식요소)
: 부모 요소의 자식으로 요소를 맨 뒤에 추가합니다.부모요소.removeChild(자식요소)
: 부모 요소에서 특정 자식 요소를 제거합니다.<ul id="myList"> <li>기존 아이템 1</li> <li>기존 아이템 2</li> </ul>
const myList = document.getElementById('myList'); // 새로운 li 요소 생성 const newItem = document.createElement('li'); newItem.textContent = "새로운 아이템 3"; newItem.style.color = "purple"; // 생성된 요소에 스타일 적용 // ul에 li 추가 myList.appendChild(newItem); // 결과: <ul>...<li>새로운 아이템 3</li></ul> // 마지막 아이템 제거 const lastChild = myList.lastElementChild; // 마지막 자식 요소 선택 if (lastChild) { myList.removeChild(lastChild); } // 결과: <ul><li>기존 아이템 1</li><li>기존 아이템 2</li></ul> (새로운 아이템 3은 사라짐)
이벤트 처리: 사용자 상호작용에 반응하기
이벤트(Event) 는 웹 페이지에서 발생하는 모든 종류의 사건을 의미합니다. 예를 들어, 사용자가 버튼을 클릭하는 것, 키보드를 누르는 것, 마우스를 움직이는 것, 페이지 로딩이 완료되는 것 등 모든 것이 이벤트입니다. 이벤트 처리(Event Handling) 는 이러한 이벤트가 발생했을 때 특정 자바스크립트 코드를 실행하도록 하는 메커니즘입니다.
이벤트 리스너 등록하기
요소에 이벤트를 감지하고 처리하는 함수(이벤트 핸들러)를 연결하는 가장 일반적이고 권장되는 방법은 addEventListener()
메서드를 사용하는 것입니다.
// element.addEventListener('이벤트_타입', 함수);
이벤트_타입
: 발생할 이벤트의 종류를 나타내는 문자열입니다. (예:'click'
,'mouseover'
,'keydown'
,'submit'
,'load'
)함수
: 이벤트가 발생했을 때 실행될 코드 블록을 포함하는 함수(이벤트 핸들러)입니다.<button id="clickMeBtn">여기를 클릭하세요</button> <input type="text" id="myInput" placeholder="여기에 입력하세요">
const clickButton = document.getElementById('clickMeBtn'); const myInput = document.getElementById('myInput'); // 1. 클릭 이벤트 (click) clickButton.addEventListener('click', function() { alert("버튼이 클릭되었습니다!"); }); // 2. 입력 이벤트 (input) myInput.addEventListener('input', function() { console.log("현재 입력 값:", myInput.value); }); // 3. 마우스 오버 이벤트 (mouseover) clickButton.addEventListener('mouseover', function() { this.style.backgroundColor = 'lightgreen'; // this는 이벤트가 발생한 요소를 가리킵니다. }); // 4. 마우스 아웃 이벤트 (mouseout) clickButton.addEventListener('mouseout', function() { this.style.backgroundColor = ''; // 원래대로 (또는 특정 색상) });
이벤트 객체 (Event Object)
이벤트 핸들러 함수는 종종 event
객체(관례적으로 e
나 event
로 명명)를 인자로 받습니다. 이 event
객체는 발생한 이벤트에 대한 자세한 정보를 담고 있습니다.
myInput.addEventListener('keydown', function(e) {
console.log("키가 눌렸습니다. 눌린 키:", e.key); // 눌린 키 문자열
console.log("키 코드:", e.keyCode); // 눌린 키의 숫자 코드 (구식)
if (e.key === 'Enter') {
alert("Enter 키를 누르셨군요!");
}
});
// 링크 기본 동작 방지 예시
const preventLink = document.getElementById('myLink');
preventLink.addEventListener('click', function(e) {
e.preventDefault(); // 링크의 기본 동작(페이지 이동)을 막습니다.
console.log("링크 클릭! 하지만 페이지 이동은 막았습니다.");
});
e.target
: 이벤트가 실제로 발생한 요소를 가리킵니다.e.preventDefault()
: 특정 이벤트의 기본 동작(예: 링크 클릭 시 페이지 이동, 폼 제출 시 새로고침)을 막습니다.e.stopPropagation()
: 이벤트 버블링(이벤트가 상위 요소로 전파되는 현상)을 중단합니다. (고급 주제)
이벤트 리스너 제거하기
removeEventListener()
메서드를 사용하여 등록했던 이벤트 리스너를 제거할 수 있습니다. 이는 특히 메모리 누수를 방지하거나, 특정 조건에서만 이벤트를 처리하고 싶을 때 유용합니다. addEventListener()
에 전달했던 것과 동일한 함수 참조를 사용해야 합니다.
const onceButton = document.getElementById('clickMeBtn');
function clickHandler() {
alert("한 번만 실행됩니다!");
onceButton.removeEventListener('click', clickHandler); // 함수 실행 후 리스너 제거
}
onceButton.addEventListener('click', clickHandler);
자주 사용되는 이벤트 타입
몇 가지 일반적인 이벤트 타입을 정리해드립니다.
- 마우스 이벤트:
click
,dblclick
,mousedown
,mouseup
,mouseover
,mouseout
,mousemove
- 키보드 이벤트:
keydown
,keyup
,keypress
- 폼 이벤트:
submit
,focus
,blur
,change
,input
- 문서/창 이벤트:
load
(페이지 로드 완료),DOMContentLoaded
(DOM 트리 구성 완료),resize
,scroll
마무리하며
이번 장에서는 자바스크립트로 웹 페이지에 동적인 생명력을 불어넣는 핵심 기술인 DOM 조작과 이벤트 처리에 대해 학습했습니다.
DOM 조작을 통해 여러분은 웹 페이지의 특정 요소를 선택하고, 그 내용(textContent
, innerHTML
), 속성(setAttribute
, classList
), 스타일(style
)을 자유롭게 변경하는 방법을 익혔습니다. 또한, 새로운 요소를 생성하고 추가하거나 제거하는 능력도 갖추게 되었습니다.
이벤트 처리를 통해 사용자의 상호작용(클릭, 입력 등)에 반응하여 특정 자바스크립트 코드를 실행하는 방법을 배웠습니다. addEventListener()
를 사용하여 이벤트 리스너를 등록하고, event
객체를 통해 이벤트에 대한 상세 정보를 얻는 방법을 이해했습니다.
이 두 가지 개념은 프론트엔드 웹 개발의 심장과 같습니다. 여러분이 배운 지식을 바탕으로 이제 정적인 HTML 페이지를 넘어, 사용자와 소통하고 변화하는 다이내믹한 웹 페이지를 만들 수 있게 되었습니다. 다양한 예제를 직접 코딩해보면서 DOM 조작과 이벤트 처리의 원리를 완전히 자기 것으로 만드시길 강력히 권합니다.