반응형
이벤트 객체란?
이벤트 객체(Event Object)는 이벤트가 발생했을 때 자동으로 생성되는 객체로, 이벤트에 대한 상세한 정보를 담고 있습니다. 이벤트 핸들러 함수의 첫 번째 매개변수로 전달됩니다.
🔍 기본 사용법
// 이벤트 객체 받기
button.addEventListener('click', function(event) {
console.log('이벤트 객체:', event);
console.log('클릭된 요소:', event.target);
console.log('이벤트 타입:', event.type);
});
// 화살표 함수에서도 동일
button.addEventListener('click', (e) => {
console.log('이벤트:', e);
});
이벤트 객체 주요 속성
이벤트 객체는 이벤트에 대한 유용한 정보와 메서드를 제공합니다.
핵심 속성들
document.addEventListener('click', function(event) {
// 이벤트 대상
console.log('클릭된 요소:', event.target);
console.log('이벤트 등록된 요소:', event.currentTarget);
// 이벤트 정보
console.log('이벤트 타입:', event.type); // 'click'
console.log('발생 시간:', event.timeStamp);
// 마우스 위치
console.log('화면 좌표:', event.clientX, event.clientY);
console.log('페이지 좌표:', event.pageX, event.pageY);
// 키 정보 (키보드 이벤트)
console.log('눌린 키:', event.key);
console.log('수식키:', event.ctrlKey, event.shiftKey, event.altKey);
});
이벤트 제어 메서드
// 기본 동작 방지
document.getElementById('link').addEventListener('click', function(event) {
event.preventDefault(); // 링크 이동 방지
console.log('링크 클릭되었지만 이동하지 않음');
});
// 이벤트 전파 중단
document.getElementById('button').addEventListener('click', function(event) {
event.stopPropagation(); // 부모로 전파 방지
console.log('버튼만 클릭, 부모 이벤트 실행 안됨');
});
// 즉시 전파 중단
element.addEventListener('click', function(event) {
event.stopImmediatePropagation(); // 같은 요소의 다른 리스너도 실행 안됨
});
target vs currentTarget
<div id="parent">
<button id="child">클릭하세요</button>
</div>
document.getElementById('parent').addEventListener('click', function(event) {
console.log('target:', event.target.id); // 실제 클릭된 요소: 'child'
console.log('currentTarget:', event.currentTarget.id); // 이벤트 등록된 요소: 'parent'
});
이벤트 위임이란?
이벤트 위임(Event Delegation)은 부모 요소에서 자식 요소들의 이벤트를 처리하는 기법입니다. 이벤트 버블링을 활용하여 효율적인 이벤트 처리가 가능합니다.
기본 개념
<!-- 비효율적인 방법: 각 버튼마다 이벤트 리스너 -->
<div id="container">
<button class="btn" data-action="save">저장</button>
<button class="btn" data-action="delete">삭제</button>
<button class="btn" data-action="edit">수정</button>
</div>
// ❌ 비효율적: 각 버튼마다 개별 리스너
document.querySelectorAll('.btn').forEach(button => {
button.addEventListener('click', function() {
console.log('버튼 클릭:', this.dataset.action);
});
});
// ✅ 효율적: 이벤트 위임 사용
document.getElementById('container').addEventListener('click', function(event) {
if (event.target.classList.contains('btn')) {
console.log('버튼 클릭:', event.target.dataset.action);
}
});
이벤트 위임의 장점
- 성능 향상: 하나의 이벤트 리스너로 여러 요소 처리
- 동적 요소 지원: 나중에 추가된 요소도 자동으로 이벤트 처리
- 메모리 효율: 이벤트 리스너 개수 감소
이벤트 위임 활용법
동적 요소 처리
<div id="todoList">
<div class="todo-item">
<span>할 일 1</span>
<button class="delete-btn">삭제</button>
</div>
</div>
<button id="addTodo">할 일 추가</button>
let todoList = document.getElementById('todoList');
let addButton = document.getElementById('addTodo');
// 이벤트 위임으로 삭제 버튼 처리
todoList.addEventListener('click', function(event) {
if (event.target.classList.contains('delete-btn')) {
// 삭제 버튼 클릭
let todoItem = event.target.closest('.todo-item');
todoItem.remove();
console.log('할 일 삭제됨');
}
});
// 새 할 일 추가 (이벤트 위임으로 자동 처리됨)
addButton.addEventListener('click', function() {
let newTodo = document.createElement('div');
newTodo.className = 'todo-item';
newTodo.innerHTML = `
<span>새 할 일</span>
<button class="delete-btn">삭제</button>
`;
todoList.appendChild(newTodo);
});
다중 액션 처리
// 여러 종류의 버튼을 하나의 리스너로 처리
document.getElementById('container').addEventListener('click', function(event) {
let target = event.target;
// 버튼별 처리
if (target.matches('.save-btn')) {
handleSave(target);
} else if (target.matches('.delete-btn')) {
handleDelete(target);
} else if (target.matches('.edit-btn')) {
handleEdit(target);
}
});
function handleSave(button) {
console.log('저장 처리');
}
function handleDelete(button) {
let item = button.closest('.item');
if (confirm('정말 삭제하시겠습니까?')) {
item.remove();
}
}
function handleEdit(button) {
let item = button.closest('.item');
// 편집 모드 전환
}
실무 활용 예제
1. 테이블 행 클릭 처리
<table id="dataTable">
<tbody>
<tr data-id="1">
<td>사용자 1</td>
<td>user1@example.com</td>
<td><button class="edit">수정</button></td>
</tr>
<tr data-id="2">
<td>사용자 2</td>
<td>user2@example.com</td>
<td><button class="edit">수정</button></td>
</tr>
</tbody>
</table>
document.getElementById('dataTable').addEventListener('click', function(event) {
let target = event.target;
let row = target.closest('tr');
if (target.classList.contains('edit')) {
// 수정 버튼 클릭
let userId = row.dataset.id;
editUser(userId);
} else if (row && row.dataset.id) {
// 행 클릭 (버튼 제외)
if (!target.matches('button')) {
let userId = row.dataset.id;
viewUserDetails(userId);
}
}
});
function editUser(id) {
console.log('사용자 수정:', id);
}
function viewUserDetails(id) {
console.log('사용자 상세 보기:', id);
}
2. 모달 창 관리
// 모든 모달을 하나의 리스너로 관리
document.body.addEventListener('click', function(event) {
let target = event.target;
// 모달 열기
if (target.dataset.modal) {
let modalId = target.dataset.modal;
openModal(modalId);
}
// 모달 닫기
if (target.classList.contains('modal-close') ||
target.classList.contains('modal-overlay')) {
closeModal(event.target.closest('.modal'));
}
});
function openModal(modalId) {
let modal = document.getElementById(modalId);
if (modal) {
modal.style.display = 'block';
}
}
function closeModal(modal) {
if (modal) {
modal.style.display = 'none';
}
}
3. 폼 검증 시스템
document.addEventListener('input', function(event) {
let target = event.target;
// 이메일 필드 검증
if (target.type === 'email') {
validateEmail(target);
}
// 비밀번호 필드 검증
if (target.type === 'password') {
validatePassword(target);
}
// 숫자 필드 검증
if (target.type === 'number') {
validateNumber(target);
}
});
function validateEmail(input) {
let isValid = input.value.includes('@');
toggleValidationClass(input, isValid);
}
function validatePassword(input) {
let isValid = input.value.length >= 6;
toggleValidationClass(input, isValid);
}
function validateNumber(input) {
let isValid = !isNaN(input.value) && input.value !== '';
toggleValidationClass(input, isValid);
}
function toggleValidationClass(input, isValid) {
input.classList.toggle('valid', isValid);
input.classList.toggle('invalid', !isValid);
}
4. 키보드 단축키 시스템
document.addEventListener('keydown', function(event) {
// Ctrl 또는 Cmd 키와 함께 사용되는 단축키
if (event.ctrlKey || event.metaKey) {
switch(event.key) {
case 's':
event.preventDefault();
saveDocument();
break;
case 'z':
event.preventDefault();
if (event.shiftKey) {
redo();
} else {
undo();
}
break;
case 'n':
event.preventDefault();
createNewDocument();
break;
}
}
// ESC 키로 모달 닫기
if (event.key === 'Escape') {
let openModal = document.querySelector('.modal:not([style*="display: none"])');
if (openModal) {
closeModal(openModal);
}
}
});
function saveDocument() {
console.log('문서 저장됨');
}
function undo() {
console.log('실행 취소');
}
function redo() {
console.log('다시 실행');
}
마무리
이벤트 객체와 이벤트 위임은 효율적인 JavaScript 이벤트 처리의 핵심입니다. 이 두 개념을 잘 활용하면 성능이 좋고 유지보수하기 쉬운 웹 애플리케이션을 만들 수 있습니다.
이벤트 객체와 위임을 마스터하면 더 효율적이고 확장 가능한 이벤트 처리 시스템을 구축할 수 있습니다!
'JavaScript > 이벤트 처리' 카테고리의 다른 글
JavaScript 실습: Todo List 만들기 - 초보자도 30분이면 완성! (1) | 2025.06.24 |
---|---|
JavaScript 마우스 이벤트와 키보드 이벤트 - 핵심 가이드 (0) | 2025.06.24 |
JavaScript 이벤트 처리 - onclick vs addEventListener 완전 가이드 (0) | 2025.06.24 |