
웹 페이지는 사용자의 행동에 따라 반응해야 진짜 인터랙티브한 "웹 애플리케이션"이 됩니다.
버튼을 클릭하고, 마우스를 올리고, 키보드를 입력하는 등 사용자의 행동을 감지하고, 그에 따라 코드를 실행시키는 것이 자바스크립트 이벤트의 역할입니다.
이벤트는 브라우저에서 발생한 사용자의 행동 또는 브라우저 자체의 변화를 뜻합니다.
예를 들어,
이런 사건들(Event)이 발생했을 때, 개발자가 미리 등록해 둔 코드(이벤트 핸들러)가 실행됩니다.
이벤트가 발생했을 때, 자바스크립트가 무언가를 실행하려면 그 이벤트가 발생하는지 감시하는 역할이 필요합니다.
그 역할을 하는 것이 바로 이벤트 리스너(Event Listener)입니다.
즉, "이벤트가 발생하면 이 함수를 실행해줘!"라고 브라우저에 알려주는 것이 이벤트 리스너입니다.
| 용어 | 역할 | 예시 |
|---|---|---|
| 이벤트 리스너 | 특정 이벤트가 발생했는지를 감시하고, 발생 시 실행할 함수를 등록함 (개념상 구조) | element.addEventListener("click", handler); |
| 이벤트 핸들러 | 이벤트가 발생했을 때 실제로 실행되는 함수 | function handler(e) { ... } |
실무에서는 이 둘을 거의 동일하게 쓰지만,
엄밀히 말하면 이벤트 리스너는 “감시 대상과 실행 함수가 연결된 상태”,
이벤트 핸들러는 “실행되는 함수 그 자체”입니다.
const button = document.querySelector("button");
function handleClick(event) {
alert("버튼이 클릭되었습니다!");
}
// 이벤트 리스너 등록 (리스너 + 핸들러 연결)
button.addEventListener("click", handleClick);
한 번만 실행되는 리스너도 가능합니다.
button.addEventListener("click", handleClick, { once: true });
리스너를 제거할 수 있습니다.
button.removeEventListener("click", handleClick);
removeEventListener()는 내부적으로
브라우저의 리스너 테이블에서 “같은 함수 객체”를 찾아 제거합니다.
익명 함수는 등록할 때와 제거할 때 서로 다른 참조가 되기 때문에 일치하지 않아 제거되지 않습니다.
<button onclick="alert('클릭!')">클릭하세요</button>
const btn = document.querySelector("button");
btn.onclick = function () {
alert("클릭됨!");
}
btn.addEventListener("click", function () {
alert("이벤트 리스너 실행!");
});
이벤트가 발생하면 브라우저는 자동으로 이벤트 객체(event object)를 핸들러 함수에 전달합니다.
이벤트 객체는 해당 이벤트에 관련한 모든 정보를 가지고 있습니다.
btn.addEventListener("click", function (event) {
console.log("이벤트 종류:", event.type); // click
console.log("발생한 요소:", event.target); // <button>
});
이벤트 객체 내에는 다음과 같은 정보들이 들어 있습니다.
| 속성 | 설명 |
|---|---|
| event.type | 이벤트의 종류 (click, submit 등) |
| event.target | 이벤트가 발생한 실제 요소 |
| event.currentTarget | 현재 이벤트 리스너가 붙은 요소 |
| event.preventDefault() | 기본 동작 방지 (예: form 제출 방지) |
| event.stopPropagation() | 이벤트 전파 막기 (버블링 차단) |
| 이벤트 | 설명 |
|---|---|
| click | 클릭할 때 |
| dblclick | 더블 클릭 |
| mouseover / mouseout | 마우스를 올릴 때 / 뗄 때 |
| keydown / keyup | 키보드 입력 시 |
| input | 입력창 내용 실시간 변경 시 |
| change | <select>, <checkbox> 등 값 변경 시 |
| submit | 폼 제출 시 |
| DOMContentLoaded | 문서 구조(DOM)가 로드되었을 때 |
| 메서드 | 역할 | 상황 | 예시 |
|---|---|---|---|
| preventDefault() | 브라우저의 기본 동작을 막음 | 링크 클릭 시 이동 막기, 폼 제출 시 새로고침 막기 등 | e.preventDefault(); |
| stopPropagation() | 이벤트가 부모 요소로 전파되는 것을 막음 | 부모/자식 요소 둘 다 리스너가 있을 때, 자식 이벤트만 실행되게 하고 싶을 때 등 | e.stopPropagation(); |
<a href="https://google.com" id="link">구글로 이동</a>
<script>
document.getElementById("link").addEventListener("click", function (e) {
e.preventDefault(); // 링크 이동 막기
alert("링크 클릭은 됐지만, 이동은 안 해요!");
});
</script>
<div id="parent">
<button id="child">눌러봐요</button>
</div>
<script>
document.getElementById("parent").addEventListener("click", () => {
alert("부모 div 클릭됨");
});
document.getElementById("child").addEventListener("click", (e) => {
e.stopPropagation(); // 이벤트 전파 막기
alert("버튼만 클릭됨 (부모는 무시됨)");
});
</script>

브라우저는 이벤트가 발생했을 때 “어느 요소에서 발생했는지”만 보는 게 아니라,
이벤트를 위에서부터 아래로, 그리고 다시 아래에서 위로 이동시키며 처리합니다.


<div id="outer">
<button id="inner">눌러보세요</button>
</div>
document.getElementById("outer").addEventListener("click", () => {
console.log("outer");
}, true); // 캡처링 단계
document.getElementById("inner").addEventListener("click", () => {
console.log("inner");
}); // 버블링 단계
사용자가 버튼을 클릭하면 실행 순서는 이렇습니다:
1. outer 캡처링 리스너 실행 (캡처링 단계)
2. inner 버블링 리스너 실행 (버블링 단계)
만약 둘 다 버블링이면 → inner가 먼저, outer가 나중에 실행됨
| 단계 | 방향 | 기본 적용 여부 | 설정 방법 |
|---|---|---|---|
| 캡처링 | 바깥 → 안쪽 | ❌ (기본값 아님) | addEventListener(..., true) |
| 버블링 | 안쪽 → 바깥 | ✅ (기본값) | addEventListener(..., false) 또는 생략 |