12장. 이벤트 (Event)
이벤트란?
이벤트(Event)는 사용자의 행동(클릭, 키 입력, 마우스 이동 등)이나 브라우저의 동작(페이지 로드, 리사이즈 등)을 의미합니다. JavaScript를 통해 이러한 이벤트에 반응하여 동적인 웹 페이지를 만들 수 있습니다.
1. 이벤트 리스너 추가
addEventListener() (권장)
가장 권장되는 방법입니다.
<button id="btn">클릭</button>
const btn = document.getElementById('btn');
btn.addEventListener('click', function() {
alert('버튼이 클릭되었습니다!');
});
인라인 이벤트 (권장하지 않음)
HTML에 직접 이벤트를 작성하는 방법입니다.
<button onclick="alert('클릭됨')">클릭</button>
단점: HTML과 JavaScript가 섞여서 유지보수가 어려움
2. 주요 이벤트 타입
마우스 이벤트
const btn = document.getElementById('btn');
// click: 클릭
btn.addEventListener('click', function() {
console.log('클릭됨');
});
// dblclick: 더블 클릭
btn.addEventListener('dblclick', function() {
console.log('더블 클릭됨');
});
// mousedown: 마우스 버튼 누름
btn.addEventListener('mousedown', function() {
console.log('마우스 버튼 누름');
});
// mouseup: 마우스 버튼 뗌
btn.addEventListener('mouseup', function() {
console.log('마우스 버튼 뗌');
});
// mouseover: 마우스가 요소 위로 이동
btn.addEventListener('mouseover', function() {
console.log('마우스가 위로 이동');
});
// mouseout: 마우스가 요소 밖으로 이동
btn.addEventListener('mouseout', function() {
console.log('마우스가 밖으로 이동');
});
키보드 이벤트
const input = document.getElementById('input');
// keydown: 키를 누름
input.addEventListener('keydown', function(event) {
console.log('키 누름:', event.key);
});
// keyup: 키를 뗌
input.addEventListener('keyup', function(event) {
console.log('키 뗌:', event.key);
});
// keypress: 키 입력 (deprecated, keydown 사용 권장)
input.addEventListener('keypress', function(event) {
console.log('키 입력:', event.key);
});
폼 이벤트
const form = document.getElementById('form');
const input = document.getElementById('input');
// submit: 폼 제출
form.addEventListener('submit', function(event) {
event.preventDefault(); // 기본 동작 방지
console.log('폼 제출됨');
});
// change: 값이 변경되고 포커스가 벗어남
input.addEventListener('change', function() {
console.log('값 변경됨:', this.value);
});
// input: 값이 변경될 때마다 (실시간)
input.addEventListener('input', function() {
console.log('입력 중:', this.value);
});
// focus: 포커스를 받음
input.addEventListener('focus', function() {
console.log('포커스 받음');
});
// blur: 포커스를 잃음
input.addEventListener('blur', function() {
console.log('포커스 잃음');
});
윈도우 이벤트
// load: 페이지 로드 완료
window.addEventListener('load', function() {
console.log('페이지 로드 완료');
});
// DOMContentLoaded: DOM 로드 완료 (더 빠름)
document.addEventListener('DOMContentLoaded', function() {
console.log('DOM 로드 완료');
});
// resize: 윈도우 크기 변경
window.addEventListener('resize', function() {
console.log('윈도우 크기 변경');
});
// scroll: 스크롤
window.addEventListener('scroll', function() {
console.log('스크롤됨');
});
3. 이벤트 객체 (Event Object)
이벤트 핸들러는 이벤트 객체를 매개변수로 받습니다.
const btn = document.getElementById('btn');
btn.addEventListener('click', function(event) {
console.log(event.type); // 'click'
console.log(event.target); // 클릭된 요소
console.log(event.currentTarget); // 이벤트 리스너가 있는 요소
});
주요 이벤트 객체 속성
btn.addEventListener('click', function(event) {
// 이벤트 타입
console.log(event.type); // 'click'
// 이벤트가 발생한 요소
console.log(event.target); // 실제 클릭된 요소
// 이벤트 리스너가 있는 요소
console.log(event.currentTarget); // btn 요소
// 마우스 위치 (클릭 이벤트)
console.log(event.clientX, event.clientY); // 화면 기준 좌표
console.log(event.pageX, event.pageY); // 페이지 기준 좌표
// 키보드 이벤트
console.log(event.key); // 눌린 키
console.log(event.keyCode); // 키 코드 (deprecated)
console.log(event.code); // 물리적 키 코드
});
4. 이벤트 전파 (Event Propagation)
이벤트는 버블링(Bubbling)과 캡처링(Capturing) 단계를 거칩니다.
버블링 (Bubbling)
이벤트가 자식 요소에서 부모 요소로 전파됩니다 (기본값).
<div id="parent">
<button id="child">클릭</button>
</div>
const parent = document.getElementById('parent');
const child = document.getElementById('child');
// 버블링: child → parent
child.addEventListener('click', function() {
console.log('자식 클릭');
});
parent.addEventListener('click', function() {
console.log('부모 클릭');
});
// child 클릭 시: "자식 클릭" → "부모 클릭"
캡처링 (Capturing)
이벤트가 부모 요소에서 자식 요소로 전파됩니다.
parent.addEventListener('click', function() {
console.log('부모 클릭');
}, true); // true: 캡처링 단계
child.addEventListener('click', function() {
console.log('자식 클릭');
});
// child 클릭 시: "부모 클릭" → "자식 클릭"
이벤트 전파 중지
child.addEventListener('click', function(event) {
console.log('자식 클릭');
event.stopPropagation(); // 전파 중지
});
parent.addEventListener('click', function() {
console.log('부모 클릭'); // 실행 안 됨
});
5. 기본 동작 방지
preventDefault()
폼 제출, 링크 이동 등의 기본 동작을 방지합니다.
<form id="form">
<input type="text" name="username">
<button type="submit">제출</button>
</form>
const form = document.getElementById('form');
form.addEventListener('submit', function(event) {
event.preventDefault(); // 폼 제출 방지
console.log('폼 제출이 방지되었습니다');
// 여기서 유효성 검사 등을 수행
});
링크 기본 동작 방지
<a href="https://example.com" id="link">링크</a>
const link = document.getElementById('link');
link.addEventListener('click', function(event) {
event.preventDefault(); // 링크 이동 방지
console.log('링크 클릭됨 (이동 안 함)');
});
6. 이벤트 위임 (Event Delegation)
부모 요소에 이벤트 리스너를 추가하여 자식 요소의 이벤트를 처리합니다.
<ul id="list">
<li>항목 1</li>
<li>항목 2</li>
<li>항목 3</li>
</ul>
const list = document.getElementById('list');
// 각 li에 이벤트 추가 (비효율적)
// const items = list.querySelectorAll('li');
// items.forEach(item => {
// item.addEventListener('click', function() {
// console.log(this.textContent);
// });
// });
// 이벤트 위임 (효율적)
list.addEventListener('click', function(event) {
if (event.target.tagName === 'LI') {
console.log(event.target.textContent);
}
});
// 새로운 항목 추가해도 자동으로 이벤트 처리됨
const newItem = document.createElement('li');
newItem.textContent = '항목 4';
list.appendChild(newItem);
7. 실전 예제
예제 1: 폼 유효성 검사
<form id="loginForm">
<input type="text" id="username" placeholder="사용자명" required>
<input type="password" id="password" placeholder="비밀번호" required>
<button type="submit">로그인</button>
</form>
<div id="error"></div>
const form = document.getElementById('loginForm');
const error = document.getElementById('error');
form.addEventListener('submit', function(event) {
event.preventDefault();
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
if (username.trim() === '') {
error.textContent = '사용자명을 입력하세요';
return;
}
if (password.length < 6) {
error.textContent = '비밀번호는 6자 이상이어야 합니다';
return;
}
error.textContent = '';
alert('로그인 성공!');
});
예제 2: 실시간 검색
<input type="text" id="search" placeholder="검색...">
<div id="results"></div>
const search = document.getElementById('search');
const results = document.getElementById('results');
search.addEventListener('input', function() {
const query = this.value;
if (query.length > 0) {
// 검색 로직 (예시)
results.textContent = `"${query}" 검색 결과...`;
} else {
results.textContent = '';
}
});
예제 3: 키보드 단축키
document.addEventListener('keydown', function(event) {
// Ctrl + S (저장)
if (event.ctrlKey && event.key === 's') {
event.preventDefault();
console.log('저장됨');
}
// ESC 키
if (event.key === 'Escape') {
console.log('취소됨');
}
});
예제 4: 드래그 앤 드롭 (간단한 예제)
<div id="box" style="width: 100px; height: 100px; background: red; position: absolute;"></div>
const box = document.getElementById('box');
let isDragging = false;
let offset = {x: 0, y: 0};
box.addEventListener('mousedown', function(event) {
isDragging = true;
offset.x = event.clientX - box.offsetLeft;
offset.y = event.clientY - box.offsetTop;
});
document.addEventListener('mousemove', function(event) {
if (isDragging) {
box.style.left = (event.clientX - offset.x) + 'px';
box.style.top = (event.clientY - offset.y) + 'px';
}
});
document.addEventListener('mouseup', function() {
isDragging = false;
});
8. 이벤트 리스너 제거
removeEventListener()
이벤트 리스너를 제거합니다.
function handleClick() {
console.log('클릭됨');
}
btn.addEventListener('click', handleClick);
// 나중에 제거
btn.removeEventListener('click', handleClick);
주의: 같은 함수 참조를 사용해야 제거됩니다.
주의사항
1. 이벤트 리스너 중복 추가
// ❌ 같은 이벤트 리스너가 여러 번 추가될 수 있음
btn.addEventListener('click', function() {
console.log('클릭');
});
btn.addEventListener('click', function() {
console.log('클릭'); // 중복 실행됨
});
// ✅ 함수를 변수에 저장하여 제어
const handleClick = function() {
console.log('클릭');
};
btn.addEventListener('click', handleClick);
2. 이벤트 객체 사용
// ✅ 이벤트 객체 활용
btn.addEventListener('click', function(event) {
console.log(event.target); // 클릭된 요소
console.log(event.type); // 이벤트 타입
});
3. this 바인딩
// 일반 함수: this는 이벤트가 발생한 요소
btn.addEventListener('click', function() {
console.log(this); // btn 요소
});
// 화살표 함수: this는 상위 스코프
btn.addEventListener('click', () => {
console.log(this); // window (또는 상위 스코프)
});
연습 문제
버튼 클릭 이벤트
- 버튼을 클릭하면 콘솔에 메시지를 출력하세요.
입력 필드 이벤트
- 입력 필드에 텍스트를 입력할 때마다 실시간으로 글자 수를 표시하세요.
폼 제출 이벤트
- 폼을 제출할 때 기본 동작을 방지하고 유효성 검사를 수행하세요.
키보드 이벤트
- Enter 키를 누르면 버튼이 클릭되도록 하세요.
이벤트 위임
- 리스트에 동적으로 추가되는 항목들도 클릭 이벤트가 동작하도록 이벤트 위임을 사용하세요.
다음 장 예고
다음 장에서는 스코프(Scope)와 호이스팅(Hoisting)에 대해 학습합니다.
'FrontEnd > Javascript' 카테고리의 다른 글
| 14장. 실습 문제 (0) | 2026.01.13 |
|---|---|
| 13장. 스코프와 호이스팅 (0) | 2026.01.12 |
| 11장. DOM 조작 (0) | 2026.01.10 |
| 10. 객체 (0) | 2026.01.09 |
| 9. 배열 (0) | 2026.01.09 |