본문 바로가기
Web

JavaScript 이벤트 흐름: 캡처링과 버블링 쉽게 보자

by 모닝위즈 2025. 9. 16.
반응형

JavaScript 이벤트 흐름: 캡처링(Capturing) vs 버블링(Bubbling) 쉽게 이해하기

요약: 브라우저의 이벤트 전파는 캡처링 → 타겟 → 버블링 순입니다. 기본값은 버블링이며(즉, addEventListener에서 캡처 옵션을 지정하지 않으면 버블링 단계에서 이벤트 리스너가 실행됩니다), 실무에서는 이벤트 위임과 stopPropagation의 영향으로 어떤 단계에서 처리할지 설계하는 것이 중요합니다.


1. 이벤트 전파의 흐름(한눈에)

브라우저는 이벤트를 다음 순서로 전파합니다.

  1. 캡처링(Capturing): document → ... → 부모 → 타깃(요소)로 내려감
  2. 타깃(Target): 이벤트가 실제 발생한 요소에서 핸들러 실행(타깃 단계)
  3. 버블링(Bubbling): 타깃 → 부모 → ... → document 로 거슬러 올라감

참고: addEventListener(type, handler, options)에서 options.capture = true이면 캡처 단계에서 실행, 기본값(false)이면 버블링 단계에서 실행됩니다.

2. 기본은 버블링이다 — 반드시 넣어야 하나?

네 — 기본 동작은 버블링입니다. 즉, `addEventListener(..., false)` 또는 세 번째 인자를 생략하면 버블링 단계에서 이벤트가 호출됩니다. 캡처링을 따로 선언하지 않으면 자동으로 버블링이 동작하므로, **“캡처링을 선언하지 않으면 버블링”** 이라는 문구는 블로그에 반드시 넣어야 합니다.

3. 실습 데모 — 캡처링과 버블링의 차이(인터랙티브)

아래 박스들을 클릭해 보세요. 우측 로그에 이벤트가 발생한 순서(단계)를 보여줍니다.

이벤트 로그 (최신 20)

4. 캡처링 vs 버블링 — 장단점 & 실무에서의 한계

캡처링(Capturing)

  • 장점: 이벤트가 내부로 도달하기 전에 상위 요소에서 미리 가로채서 처리 가능(예: 권한 체크, 공통 전처리).
  • 단점: 실무에서 잘 사용되지 않아 다른 개발자가 의도를 모를 수 있고, 내부 요소의 세밀한 처리(특정 버튼 로직)를 예기치 않게 차단할 수 있음.
  • 한계: 부모가 캡처 단계에서 이벤트를 중단하면 실제 타겟의 로직이 실행되지 않을 수 있음. (예: 내부 버튼에서 반드시 실행해야 할 로직이 있다면 문제가 될 수 있음)

버블링(Bubbling)

  • 장점: 이벤트 위임(event delegation)에 유리 — 동적으로 추가되는 자식 요소를 부모 하나의 리스너로 처리 가능(성능/관리 측면 유리).
  • 단점: 내부 요소가 stopPropagation() 또는 stopImmediatePropagation()을 호출하면 부모의 리스너가 실행되지 않음.
  • 한계: 광고 차단, 서드파티 스크립트가 내부에서 프로파게이션을 차단하면 의도한 상위 처리(예: 분석용 트래킹)가 실행되지 않을 수 있음.

5. stopPropagation vs stopImmediatePropagation

  • event.stopPropagation(): 현재 이벤트의 전파(같은 단계의 상위/하위로의 전파)를 막음 — 같은 요소의 다른 리스너(같은 단계)에는 영향 없음.
  • event.stopImmediatePropagation(): 해당 이벤트에 등록된 이후의 다른 리스너들까지 모두 실행되지 않도록 즉시 중단함(같은 요소에 여러 핸들러가 있으면 모두 차단됨).
  • 두 함수 모두 이벤트의 기본 동작(예: 링크 이동, 폼 제출)을 막지는 않음 — 그 목적은 event.preventDefault()입니다.

6. 실무 권장 (결론 및 체크리스트)

  • 기본은 버블링 — 특별한 이유가 없으면 캡처링을 남발하지 마세요.
  • 동적 요소 처리는 이벤트 위임(event delegation)으로 부모에 한 번만 리스너를 달아 관리 효율을 높이세요.
  • 부모 레벨에서 이벤트를 가로채야 하는 경우(예: 접근 제어)는 캡처링을 신중히 사용하되, 문서화하여 팀에 알리세요.
  • stopPropagation을 사용하면 상위 처리 로직이 무력화될 수 있으니, 오탐/중복 실행 방지 목적이라면 once 옵션이나 플래그 변수를 고려하세요.
  • 팀 코드 컨벤션으로 "리스너 등록 시 capture 사용 사유 표기" 같은 규칙을 도입하면 유지보수에 도움이 됩니다.

댓글