Web Development/JavaScript
이벤트 처리
newclass
2025. 3. 30. 22:40
이벤트 처리
이벤트는 사용자의 행동(클릭, 키보드 입력 등)이나 프로그래밍적 변화(로딩 완료, 타이머 완료 등)에 반응하여 JavaScript 코드를 실행할 수 있게 해주는 메커니즘입니다.
이벤트 리스너 등록
요소에 이벤트 리스너(이벤트 핸들러)를 등록하는 방법입니다.
// 1. addEventListener 메서드 (권장 방법)
const button = document.querySelector('#myButton');
button.addEventListener('click', function(event) {
console.log('버튼이 클릭되었습니다!');
console.log('이벤트 객체:', event);
});
// 화살표 함수 사용
button.addEventListener('click', (event) => {
console.log('화살표 함수 핸들러로 클릭 처리');
});
// 이벤트 리스너 제거
function clickHandler(event) {
console.log('클릭 이벤트 발생!');
// 한 번만 실행되고 제거
event.currentTarget.removeEventListener('click', clickHandler);
}
button.addEventListener('click', clickHandler);
// 2. 이벤트 속성 (on + 이벤트 이름)
const secondButton = document.querySelector('#secondButton');
secondButton.onclick = function(event) {
console.log('onclick 속성 사용');
};
// 주의: 이전 핸들러를 덮어씀
secondButton.onclick = function(event) {
console.log('새로운 onclick 핸들러가 이전 것을 대체함');
};
// 3. 인라인 이벤트 속성 (HTML에 직접 작성 - 권장하지 않음)
// <button onclick="console.log('인라인 이벤트')">클릭</button>
주요 이벤트 유형
JavaScript에서 다룰 수 있는 다양한 이벤트 유형들입니다.
// 마우스 이벤트
element.addEventListener('click', () => console.log('클릭'));
element.addEventListener('dblclick', () => console.log('더블 클릭'));
element.addEventListener('mousedown', () => console.log('마우스 버튼 누름'));
element.addEventListener('mouseup', () => console.log('마우스 버튼 뗌'));
element.addEventListener('mousemove', (e) => console.log(`마우스 이동: ${e.clientX}, ${e.clientY}`));
element.addEventListener('mouseover', () => console.log('마우스 요소 위로 이동'));
element.addEventListener('mouseout', () => console.log('마우스 요소 밖으로 이동'));
element.addEventListener('contextmenu', (e) => {
e.preventDefault(); // 기본 컨텍스트 메뉴 방지
console.log('우클릭');
});
// 키보드 이벤트
document.addEventListener('keydown', (e) => console.log(`키 누름: ${e.key}`));
document.addEventListener('keyup', (e) => console.log(`키 뗌: ${e.key}`));
document.addEventListener('keypress', (e) => console.log(`문자 입력: ${e.key}`));
// 폼 이벤트
const form = document.querySelector('form');
form.addEventListener('submit', (e) => {
e.preventDefault(); // 기본 제출 동작 방지
console.log('폼 제출됨');
});
const input = document.querySelector('input');
input.addEventListener('focus', () => console.log('포커스 얻음'));
input.addEventListener('blur', () => console.log('포커스 잃음'));
input.addEventListener('input', (e) => console.log(`입력값 변경: ${e.target.value}`));
input.addEventListener('change', (e) => console.log(`값 변경 확정: ${e.target.value}`));
// 문서 및 윈도우 이벤트
document.addEventListener('DOMContentLoaded', () => console.log('DOM 로드 완료'));
window.addEventListener('load', () => console.log('페이지 완전히 로드됨'));
window.addEventListener('resize', () => console.log('윈도우 크기 변경'));
window.addEventListener('scroll', () => console.log('스크롤 발생'));
window.addEventListener('beforeunload', (e) => {
// 페이지 나가기 전 확인 (현대 브라우저에서는 제한적)
e.preventDefault();
e.returnValue = '';
});
// 터치 이벤트 (모바일)
element.addEventListener('touchstart', () => console.log('터치 시작'));
element.addEventListener('touchend', () => console.log('터치 종료'));
element.addEventListener('touchmove', () => console.log('터치 이동'));
이벤트 객체
이벤트 핸들러에 자동으로 전달되는 이벤트 객체를 통해 이벤트 관련 정보에 접근할 수 있습니다.
document.querySelector('button').addEventListener('click', function(event) {
// 기본 이벤트 정보
console.log('이벤트 타입:', event.type); // "click"
console.log('이벤트 타겟:', event.target); // 실제 클릭된 요소
console.log('현재 타겟:', event.currentTarget); // 이벤트 리스너가 연결된 요소
// 마우스 이벤트 정보
console.log('클릭 좌표 (화면):', event.clientX, event.clientY);
console.log('클릭 좌표 (페이지):', event.pageX, event.pageY);
console.log('Alt키 누름:', event.altKey);
console.log('Ctrl키 누름:', event.ctrlKey);
console.log('Shift키 누름:', event.shiftKey);
console.log('마우스 버튼:', event.button); // 0: 좌클릭, 1: 휠, 2: 우클릭
// 이벤트 제어
event.preventDefault(); // 기본 동작 방지 (예: 링크 클릭 시 페이지 이동 방지)
event.stopPropagation(); // 이벤트 버블링 중단
});
// 키보드 이벤트 특수 정보
document.addEventListener('keydown', function(event) {
console.log('누른 키:', event.key); // 키 이름 ("a", "Enter" 등)
console.log('키 코드:', event.keyCode); // 키 코드 (deprecated)
console.log('Alt키 누름:', event.altKey);
console.log('Ctrl키 누름:', event.ctrlKey);
console.log('Shift키 누름:', event.shiftKey);
// 특정 키 조합 감지
if (event.ctrlKey && event.key === 's') {
event.preventDefault(); // 브라우저 기본 저장 동작 방지
console.log('Ctrl+S 조합 감지');
// 저장 처리 코드
}
});
이벤트 전파(Event Propagation)
DOM에서 이벤트는 캡처링(capturing)과 버블링(bubbling)이라는 두 단계로 전파됩니다.
/* HTML 구조 예시:
<div id="outer">
<div id="inner">
<button id="button">클릭</button>
</div>
</div>
*/
// 이벤트 버블링 (기본): 하위 요소에서 상위 요소로 이벤트가 전파됨
document.querySelector('#button').addEventListener('click', (e) => {
console.log('버튼 클릭됨');
});
document.querySelector('#inner').addEventListener('click', (e) => {
console.log('inner div 클릭됨 (버블링)');
});
document.querySelector('#outer').addEventListener('click', (e) => {
console.log('outer div 클릭됨 (버블링)');
});
// 이벤트 캡처링: 상위 요소에서 하위 요소로 이벤트가 전파됨
document.querySelector('#outer').addEventListener('click', (e) => {
console.log('outer div 클릭됨 (캡처링)');
}, true); // 세 번째 인자를 true로 설정하면 캡처링 단계에서 실행
document.querySelector('#inner').addEventListener('click', (e) => {
console.log('inner div 클릭됨 (캡처링)');
}, true);
document.querySelector('#button').addEventListener('click', (e) => {
console.log('버튼 클릭됨 (캡처링)');
}, true);
// 버튼 클릭 시 콘솔 출력 순서:
// 1. "outer div 클릭됨 (캡처링)" (캡처링 단계)
// 2. "inner div 클릭됨 (캡처링)" (캡처링 단계)
// 3. "버튼 클릭됨 (캡처링)" (캡처링 단계)
// 4. "버튼 클릭됨" (타겟 단계)
// 5. "inner div 클릭됨 (버블링)" (버블링 단계)
// 6. "outer div 클릭됨 (버블링)" (버블링 단계)
// 이벤트 전파 중단
document.querySelector('#inner').addEventListener('click', (e) => {
console.log('inner div 클릭됨 (버블링)');
e.stopPropagation(); // 이벤트 버블링 중단
// outer div의 이벤트 핸들러는 실행되지 않음
});
이벤트 위임(Event Delegation)
부모 요소에 이벤트 리스너를 등록하여 자식 요소들의 이벤트를 효율적으로 처리하는 패턴입니다.
// 비효율적인 방식: 각 버튼마다 이벤트 리스너 등록
// document.querySelectorAll('.button').forEach(button => {
// button.addEventListener('click', () => {
// console.log('버튼 클릭:', button.textContent);
// });
// });
// 이벤트 위임: 부모 요소에 한 번만 이벤트 리스너 등록
document.querySelector('#buttons-container').addEventListener('click', (e) => {
// 클릭된 요소가 버튼인지 확인
if (e.target.matches('.button')) {
console.log('버튼 클릭:', e.target.textContent);
}
// 또는 다른 방식으로 확인
if (e.target.className === 'button') {
console.log('버튼 클릭:', e.target.textContent);
}
// 데이터 속성으로 추가 정보 활용
if (e.target.matches('[data-action]')) {
const action = e.target.dataset.action;
console.log(`액션 "${action}" 실행`);
// 액션에 따른 다른 처리
switch(action) {
case 'save':
saveData();
break;
case 'load':
loadData();
break;
case 'delete':
deleteData();
break;
}
}
});
// 동적으로 추가된 요소에도 자동으로 적용됨
const newButton = document.createElement('button');
newButton.className = 'button';
newButton.textContent = '새 버튼';
document.querySelector('#buttons-container').appendChild(newButton);
커스텀 이벤트
자신만의 이벤트를 생성하고 발생시킬 수 있습니다.
// 커스텀 이벤트 생성 및 발생
const button = document.querySelector('#myButton');
// 이벤트 리스너 등록
button.addEventListener('userLogin', (e) => {
console.log('사용자 로그인 이벤트 발생!');
console.log('로그인 유저:', e.detail.username);
console.log('로그인 시간:', e.detail.time);
});
// 이벤트 발생시키기
const loginEvent = new CustomEvent('userLogin', {
detail: {
username: 'user123',
time: new Date().toLocaleTimeString()
},
bubbles: true,
cancelable: true
});
button.dispatchEvent(loginEvent);
// 간단한 커스텀 이벤트 (데이터 없이)
const simpleEvent = new Event('simpleTrigger', {
bubbles: true,
cancelable: true
});
document.dispatchEvent(simpleEvent);
document.addEventListener('simpleTrigger', () => {
console.log('간단한 이벤트 발생');
});
이벤트 처리:
- addEventListener로 이벤트 리스너 등록
- 다양한 이벤트 유형 처리 (클릭, 키보드, 폼, 로드 등)
- 이벤트 객체를 통한 상세 정보 접근
- 이벤트 전파 (캡처링, 버블링)와 이벤트 위임
- 커스텀 이벤트 생성 및 발생