이벤트 처리

2025. 3. 30. 22:40Web Development/JavaScript

이벤트 처리

이벤트는 사용자의 행동(클릭, 키보드 입력 등)이나 프로그래밍적 변화(로딩 완료, 타이머 완료 등)에 반응하여 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로 이벤트 리스너 등록
  • 다양한 이벤트 유형 처리 (클릭, 키보드, 폼, 로드 등)
  • 이벤트 객체를 통한 상세 정보 접근
  • 이벤트 전파 (캡처링, 버블링)와 이벤트 위임
  • 커스텀 이벤트 생성 및 발생

'Web Development > JavaScript' 카테고리의 다른 글

비동기 프로그래밍  (0) 2025.03.30
실전 DOM 조작 예제  (0) 2025.03.30
요소 선택과 조작  (0) 2025.03.30
DOM 조작  (0) 2025.03.30
배열  (0) 2025.03.30