🖱️ JavaScript · DOM · 이벤트

클릭 이벤트 기초 완전 정복

버튼을 클릭하면 무슨 일이 일어날까요?
onclick부터 addEventListener, 이벤트 위임까지 — 클릭 이벤트의 모든 것을 실습과 함께 마스터해요.

⏱️ 약 15분 📅 2026년 4월 🏷️ JavaScript · DOM · 이벤트 👶 입문 난이도
① 개념

이벤트란 무엇인가요?

사용자의 행동(클릭, 키 입력, 스크롤 등)을 JavaScript가 감지하는 방법

웹 페이지는 단순히 보는 것에서 끝나지 않아요. 사용자가 버튼을 클릭하거나, 폼에 글자를 입력하거나, 마우스를 올리는 순간 — 이 모든 행동이 브라우저에서 이벤트(Event)로 발생해요. JavaScript는 이 이벤트를 감지해서 원하는 동작을 실행할 수 있어요.

가장 흔하게 쓰이는 이벤트가 바로 클릭 이벤트(click event)예요. 사용자가 마우스로 요소를 클릭하거나, 터치스크린에서 탭(tap)하는 순간 발생해요. 쇼핑몰의 "장바구니 담기" 버튼, 모달창 열기 버튼, 메뉴 토글 버튼 — 모두 클릭 이벤트로 동작해요.

🖱️

이벤트(Event)

브라우저에서 발생하는 모든 사건이에요. click, keydown, mouseover, submit 등 수십 가지 종류가 있어요.

📡

이벤트 리스너(Listener)

이벤트가 발생했을 때 실행할 함수예요. "이 요소에서 click이 발생하면 이 함수를 실행해" 라고 등록해두는 거예요.

🎯

이벤트 타겟(Target)

이벤트가 실제로 발생한 요소예요. event.target으로 접근할 수 있어요. 어떤 버튼을 클릭했는지 알 수 있어요.

🔗

DOM과의 관계

HTML로 만들어진 DOM 요소에 이벤트 리스너를 붙여요. DOM을 먼저 불러온 뒤 JavaScript를 실행해야 정상 동작해요.

💡

DOM이란? Document Object Model의 약자로, HTML 문서를 JavaScript가 다룰 수 있는 객체 구조로 표현한 것이에요. document.getElementById()로 요소를 찾고 그 위에 이벤트를 달아요.

클릭 이벤트의 동작 원리

사용자가 요소를 클릭하면, 브라우저는 다음 순서로 처리해요.

단계 설명 관련 개념
① 클릭 발생 사용자가 마우스 버튼을 누르고 뗌 mousedown + mouseup
② 이벤트 객체 생성 브라우저가 click 이벤트 객체를 만들어 세부 정보 담음 Event 객체
③ 캡처링 단계 document → html → body → ... → 클릭된 요소로 이벤트 내려감 캡처링
④ 타겟 단계 클릭된 요소에 등록된 리스너 실행 타겟
⑤ 버블링 단계 클릭된 요소 → 부모 → ... → document 로 이벤트 올라감 버블링
⚠️

주의: <script> 태그를 </body> 바로 앞에 놓거나, DOMContentLoaded 이벤트 안에서 실행해야 해요. HTML 요소가 생성되기 전에 JavaScript가 실행되면 요소를 찾지 못해서 에러가 나요.

② 3가지 방법

클릭 이벤트를 다는 3가지 방법

HTML 속성, JS 프로퍼티, addEventListener — 상황에 맞는 방법을 골라 써요

onclick="함수()"
① HTML onclick 속성
HTML 태그 안에 직접 onclick="..." 속성으로 이벤트를 붙이는 방법이에요. 빠르게 테스트할 때 편리해요.
✅ 빠르게 작성 가능
✅ HTML만 봐도 동작 파악 가능
❌ HTML과 JS가 섞여서 유지보수 어려움
❌ 이벤트 리스너 하나만 등록 가능
❌ 큰 프로젝트엔 비추천
element.onclick = function
② JS onclick 프로퍼티
JavaScript에서 DOM 요소의 onclick 프로퍼티에 함수를 할당하는 방법이에요. HTML과 JS를 분리할 수 있어요.
✅ HTML과 JS 분리
✅ 직관적인 문법
❌ 이벤트 리스너 하나만 등록 가능
❌ 나중에 할당하면 이전 것이 덮어씌워짐
addEventListener('click', fn)
③ addEventListener
현대적인 방법으로, 가장 권장해요. 여러 리스너 등록, 캡처링/버블링 제어, 나중에 제거(removeEventListener)도 가능해요.
✅ 여러 리스너 등록 가능
✅ removeEventListener로 제거 가능
✅ 캡처링/버블링 단계 선택 가능
✅ 현대 개발 표준

각 방법 코드 예시

methods-comparison.html
/* ① HTML onclick 속성 */
<button onclick="alert('클릭!')">클릭</button>

/* ② JS onclick 프로퍼티 */
<button id="btn">클릭</button>
<script>
  const btn = document.getElementById('btn');
  btn.onclick = function() {
    alert('클릭!');
  };
</script>

/* ③ addEventListener — 권장 방법 */
<button id="btn2">클릭</button>
<script>
  const btn2 = document.getElementById('btn2');
  btn2.addEventListener('click', function() {
    alert('클릭!');
  });
</script>
🤖 바이브코더 TIP

AI에게 코드를 짜달라고 할 때 "addEventListener를 사용해서 버튼 클릭 이벤트를 추가해줘"라고 명시하면 현대적인 코드를 받을 수 있어요. 작은 인라인 핸들러가 필요하다면 "onclick 속성으로" 라고 요청하면 돼요.

③ 완성 코드

실전에서 자주 쓰는 클릭 이벤트 패턴

복붙하면 바로 쓸 수 있는 4가지 핵심 패턴이에요

패턴 1 — 기본 버튼 클릭

가장 기본적인 버튼 클릭 이벤트 처리 방법이에요.

pattern1-basic.html
<button id="myBtn">클릭해보세요</button>
<p id="result"></p>

<script>
  const btn = document.getElementById('myBtn');
  const result = document.getElementById('result');

  btn.addEventListener('click', function(event) {
    // event 객체에는 클릭 좌표, 타겟 등 정보가 담겨있어요
    result.textContent = `클릭! X: ${event.clientX}, Y: ${event.clientY}`;
  });
</script>

패턴 2 — 토글 (ON/OFF 전환)

다크모드 전환, 메뉴 열기/닫기, 좋아요 버튼 등에 활용해요.

pattern2-toggle.html
<button id="toggleBtn">🌙 다크모드 켜기</button>

<script>
  const btn = document.getElementById('toggleBtn');
  let isDark = false;

  btn.addEventListener('click', () => {
    isDark = !isDark; // true/false 반전

    if (isDark) {
      document.body.style.background = '#111';
      document.body.style.color = '#fff';
      btn.textContent = '☀️ 라이트모드 켜기';
    } else {
      document.body.style.background = '#fff';
      document.body.style.color = '#111';
      btn.textContent = '🌙 다크모드 켜기';
    }
  });
</script>

패턴 3 — 이벤트 위임 (Event Delegation)

동적으로 추가되는 요소들을 효율적으로 처리하는 핵심 패턴이에요.

pattern3-delegation.html
<ul id="list">
  <li><button class="del-btn">삭제</button> 항목 1</li>
  <li><button class="del-btn">삭제</button> 항목 2</li>
</ul>

<script>
  const list = document.getElementById('list');

  // 각 li마다 이벤트를 달지 않고, 부모 ul에 하나만 달아요
  list.addEventListener('click', function(event) {
    if (event.target.classList.contains('del-btn')) {
      // 클릭된 것이 삭제 버튼이면, 부모 li 제거
      event.target.closest('li').remove();
    }
  });

  // 나중에 동적으로 추가해도 자동으로 이벤트 적용돼요!
  function addItem(text) {
    const li = document.createElement('li');
    li.innerHTML = `<button class="del-btn">삭제</button> ${text}`;
    list.appendChild(li);
  }
</script>

패턴 4 — event.preventDefault()

기본 동작(폼 제출, 링크 이동 등)을 막고 커스텀 처리하는 방법이에요.

pattern4-prevent-default.html
<form id="myForm">
  <input type="text" id="nameInput" placeholder="이름 입력">
  <button type="submit">제출</button>
</form>
<p id="msg"></p>

<script>
  const form = document.getElementById('myForm');

  form.addEventListener('submit', function(event) {
    event.preventDefault(); // 기본 폼 제출(페이지 새로고침) 막기

    const name = document.getElementById('nameInput').value;

    if (!name.trim()) {
      document.getElementById('msg').textContent = '이름을 입력해주세요!';
      return;
    }
    document.getElementById('msg').textContent = `${name}님, 제출 완료!`;
  });
</script>
④ 만들어보기

클릭 이벤트 실습장

직접 클릭해보며 각 패턴이 어떻게 동작하는지 체험해보세요

🔢 실습 ① — 클릭 카운터
아직 클릭하지 않았어요
🎨 실습 ② — 색상 토글 버튼
🎨
📝 실습 ③ — 동적 리스트 추가/삭제
    📡 실습 ④ — 이벤트 위임 체험

    부모 컨테이너 하나가 모든 버튼 클릭을 처리해요

    버튼을 클릭해보세요
    ⑤ FAQ

    자주 묻는 질문

    클릭 이벤트를 배우면서 자주 헷갈리는 것들을 모았어요

    onclick과 addEventListener, 언제 어떤 걸 써야 하나요?

    간단한 프로토타입이나 1회성 테스트라면 onclick이 빠르고 간편해요. 하지만 실제 프로젝트에서는 addEventListener를 쓰는 것을 강력히 권장해요.

    이유는 세 가지예요. 첫째, onclick은 하나의 이벤트 핸들러만 등록할 수 있어서 나중에 또 다른 onclick을 붙이면 이전 것이 사라져요. addEventListener는 여러 개를 등록해도 모두 실행돼요. 둘째, removeEventListener로 나중에 이벤트를 깔끔하게 제거할 수 있어요. 셋째, 캡처링 단계를 사용하고 싶을 때도 addEventListener만 가능해요.

    이벤트 버블링이란 정확히 무엇인가요?

    이벤트 버블링(Event Bubbling)은 자식 요소에서 발생한 이벤트가 부모 → 조상 요소로 순서대로 전파되는 현상이에요. 마치 물속에서 거품(bubble)이 위로 떠오르는 것처럼요.

    예를 들어 <div> 안의 <button>을 클릭하면, button의 click 이벤트가 발생한 뒤 div의 click 이벤트도 순서대로 발생해요. 이 특성을 활용한 것이 이벤트 위임(Event Delegation)이에요. 부모에 이벤트 하나만 달아서 여러 자식의 이벤트를 한꺼번에 처리할 수 있어요.

    stopPropagation()은 언제 쓰나요?

    event.stopPropagation()은 이벤트가 부모 요소로 버블링되는 것을 막아요. 자식 요소의 이벤트 처리가 부모 이벤트에 영향을 주지 않게 하고 싶을 때 써요.

    가장 흔한 사례는 모달창이에요. 모달 배경(오버레이)을 클릭하면 모달이 닫히는데, 모달 내부 콘텐츠를 클릭할 때는 닫히면 안 되잖아요. 이때 모달 내부에 event.stopPropagation()을 추가하면 배경 클릭 이벤트로 전파되지 않아요. 단, 남발하면 디버깅이 어려워지니 꼭 필요한 경우에만 써요.

    동적으로 생성한 요소에 클릭 이벤트를 붙이는 가장 좋은 방법은?

    JavaScript로 나중에 document.createElement()로 만든 요소에는 기존에 등록한 이벤트 리스너가 자동으로 붙지 않아요. 해결 방법은 두 가지예요.

    방법 1 — 요소 생성 직후 이벤트 달기: 요소를 만들고 DOM에 추가하기 전에 element.addEventListener()로 이벤트를 달아요. 요소별로 이벤트를 달아야 해서 요소가 많으면 메모리를 많이 써요.

    방법 2 — 이벤트 위임(권장): 동적 요소의 공통 조상(부모) 요소에 이벤트를 달고, 이벤트가 발생했을 때 event.target으로 어떤 자식이 클릭됐는지 확인해요. 요소가 동적으로 추가/제거돼도 자동으로 작동하고 메모리 효율도 좋아요.

    더블클릭, 우클릭 이벤트도 감지할 수 있나요?

    네! addEventListener의 첫 번째 인자에 이벤트 타입을 바꾸면 돼요.

    더블클릭: element.addEventListener('dblclick', handler) — 요소를 빠르게 두 번 클릭하면 발생해요.

    우클릭(컨텍스트 메뉴): element.addEventListener('contextmenu', handler) — 마우스 오른쪽 버튼 클릭 시 발생해요. event.preventDefault()를 함께 쓰면 브라우저 기본 우클릭 메뉴를 막을 수 있어요. 커스텀 컨텍스트 메뉴를 만들 때 활용해요.

    이 밖에도 mousedown, mouseup, mouseover, mouseout, mousemove 등 다양한 마우스 이벤트가 있어요.

    ⑥ 다음 단계

    이제 뭘 배우면 좋을까요?

    클릭 이벤트를 마스터했다면, 자연스럽게 이어지는 주제예요