HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
👻
개발 기록
/
📚
CS 스터디
/
📚
DOM event flow
📚

DOM event flow

프론트엔드 개발자라면 addEventListener를 어떻게 사용하는지 알 뿐만 아니라
이벤트가 어떻게 동작하는지도 알고 있어야 한다!
📌
가장 직관적인 click 이벤트로 예시를 들어보겠습니다.
 

❓ 뭐가 문제야?

<html> <body> <div></div> </body> </html>
HTML
const div = document.querySelector('div'); div.addEventListener('click', something)
JavaScript

이벤트가 걸린 div를 클릭하면 무슨 일이 일어날까?

HTML을 3D로 표현.
HTML을 3D로 표현.
3D의 단면을 표현.
3D의 단면을 표현.
  • div는 이벤트가 실행되는 직접적인 요소.
  • div 하나만 눌렀다고 말할 수 있을까? 만약 부모들에게도 똑같이 click 이벤트가 있다면?
  • 정답은 다같이 실행한다!
  • 이벤트가 적용 대상에 바로 실행되는 것이 아닌 순차적으로 실행되는 것이 생김 → evnet flow를 가진다!

여기서 중요한 용어 정리!

body의 입장에서 이벤트의 실행 주체는 div지만 이벤트 주인은 div임.
body의 입장에서 이벤트의 실행 주체는 div지만 이벤트 주인은 div임.
  • current target : 이벤트의 진짜 주인.
  • target : 이벤트의 시발점.
  • 이 둘을 분리해서 생각해야 함.
 

🤔 어떻게 실행되는데?

  • event flow는 흐름이 정해져 있음.
  • 브라우저에서 가장 가까이 있는 곳(HTML)부터 시작됨 → Capture phase
  • 이벤트의 당사자가 실행이 됨 → Target phase
  • 다시 내려옴 → bubble phase
    • notion image
  • 아까와 같이 div, body, html 모든 요소에 이벤트가 걸려있다면 모두 실행될 것임.

그럼 이렇게 하자!

  • currentTarget과 target이 일치하지 않을 경우, 캡쳐단계 또는 버블단계에서 발생될지 선택할 수 있음.
  • 기본 값은 버블임. div에 이벤트를 걸고 싶은데 브라우저 상단부터 실행되면 합리적이지 않기 때문.
    • 기본적인 실행 flow
      기본적인 실행 flow
 

💡 직접 실행해보자

출처 MDN
출처 MDN
<html> <body> <div></div </body> </html>
HTML
const html = document.documentElement const body = document.body const div = document.querySelector('div'); div.addEventListener('click', function() { console.log('div다') }) body.addEventListener('click', function() { console.log('body다') }) html.addEventListener('click', function() { console.log('html이다') })
어떠한 옵션 값도 설정하지 않았을 때
const html = document.documentElement const body = document.body const div = document.querySelector('div'); div.addEventListener('click', function() { console.log('div다') }) body.addEventListener('click', function() { console.log('body다') }, true) html.addEventListener('click', function() { console.log('html이다') })
body에 이벤트 flow를 true로 변경했을 때
기본 값은 버블링으로 해당 순서로 실행됨.
기본 값은 버블링으로 해당 순서로 실행됨.
 
body 클릭시 body, html 순으로 호출.
body 클릭시 body, html 순으로 호출.
 
 

😟 매번 신경써야 할까?

  • 웬만하면 버블링을 기본으로 실행하기 때문에 걱정 안해도 됨.
  • 하지만 미세한 이벤트 control이 필요할 땐 true로 바꿀 수 있는 우아함을 기르자.
  • 브라우저의 이벤트 flow는 막을 수 없지만 propagation의 전파는 막을 수 있음.
  • Event.stopPropagation() : 이벤트 캡쳐링과 버블링에 있어 현재 이벤트 이후의 전파를 막음.
  • 실무에선 이벤트를 중첩시킬 일이 많지 않기 때문에 임시로 사용하거나 이벤트를 막는 용도로 사용하기도 함.
const html = document.documentElement const body = document.body const div = document.querySelector('div'); div.addEventListener('click', function(e) { e.stopPropagation() console.log('div다') }) body.addEventListener('click', function() { console.log('body다') }) html.addEventListener('click', function() { console.log('html이다') })
stopPropation() 활용 예시
notion image
 

그 외의 event control

  • Event.preventDefault() : 이벤트를 취소할 수 있는 경우, 이벤트의 전파를 막지않고 그 이벤트를 취소함.
  • JS는 이렇게 HTML을 자유롭게 컨트롤할 수 있지만 markup을 등한시해선 안됨. 시멘틱하게 짜는 것이 좋음.
const form = document.querySelector('form') form.addEventListener('submit', function(e){ e.preventDefault() })
submit을 해도 페이지 이동이나 제출이 되지 않음.
 
참고자료 :
프론트엔드 개발자라면 반드시 알아야 할 필수 DOM 이벤트 10분 정리