JavaScript Event

업데이트:

자바스크립트의 이벤트는 자바스크립트의 동작과 매우 밀접한 관계를 맺고있다. 자바스크립트는 브라우저와 상호작용 하면서 동작하고 웹브라우저에서 일어나는 모든 이벤트들에 대해서 자바스크립트로 반응하고 처리가 가능하다. 이러한 이벤트를 다루는 함수를 이벤트핸들러 라고 한다.

자바스크립트는 싱글쓰레드로 한번에 하나의 작업만 처리하지만 이벤트루프로 동시성을 지원한다.

자바스크립트의 엔진에있는 콜스택에 요청된 작업이 순차적으로 쌓이고 순차적으로 실행된다. 이때 동시성을 지원하는것은 비동기요청을 처리하는 브라우저가 담당하게된다.

이벤트루프가 콜스택이 비어졌을때를 확인하고 비동기요청으로 들어와있던 결과를 콜스택으로 이동시켜 순차적으로 실행되도록 만든다.

이벤트 흐름

만약 흰 종이위 중앙에 원을 하나 그려넣고 그 가운데 정중앙을 짚으면 그 중앙은 원의 중앙이기도 하지만 흰종이의 중앙이기도하다. 이러한 시각으로 이벤트를 바라보았을때 익스플로러와 넷스케이프의 개발의 차이로인해 두가지 흐름이 존재한다.

이벤트 버블링

인터넷 익스플로러의 이벤트 흐름은 이벤트 버블링 이라고 부르며 문서트리에서 가장 깊은요소에서 시작해 위로 올라가는 흐름이 거품과 비슷하여 버블링 이라고한다.

<html>
  <head></head>
  <body>
    <div id="click">Click Me</div>
  </body>
</html>

해당 페이지에서 div 를 클릭한다면 이벤트 흐름은 div => body => html => document 까지 흐름을타고 올라가게된다. (IE9, 파이어폭스, 크롬, 사파리는 window 객체까지 올라감)

이벤트 캡쳐링

이벤트버블링과는 반대되는 개념으로 최상위노드에서 이벤트가 발생하여 클릭한 node까지 도달하며 이벤트가 발생한다.

여기서 중요한점은 이 두가지 이벤트 흐름은 둘중에 하나만 발생하는것이 아닌 캡처링으로 시작하여 버블링으로 종료하게된다.

addEventListener

addEventListener 는 DOM 레벨 2 에서 정의된 메서드로 이벤트핸들러를 생성하는 역할을하고 세번째 인자의 boolan 값에 따라 캡쳐단계에서 이벤트를 호출할지(ture), 버블링 단계에서 호출할지(false)를 나타낼 수 있다.

button.addEventListener("click", () => {
  console.log('click')
}, false);

위와같은 click 이벤트핸들러를 추가하면 button 이 클릭 이벤트가 발생했을때 버블링단계에서 호출을 하라는것으로 해석할 수 있다.

preventDefault

이벤트 동작을 제어하면서 이 메소드를 많이 사용하는데 주로 요소가 갖고있는 기본동작을 중단시키기위해서 사용한다. 여기서 요소가 갖고있는 기본동작이란 form 태그를 사용할때 발생하는 submit 이라던지 a태그를 사용하여 다른페이지로 이동되는 경우를 말한다.

stopPropagation

이 메소드는 이벤트가 부모로 전파되는 버블링을 막기 위해서 사용한다.

<body>
    <button id="btn">버튼 클릭</button>

    <script>
        const body = document.querySelector('body');
        const btn = document.querySelector('#btn');
        body.addEventListener('click', () => {
            alert('body click');
        })
        btn.addEventListener('click', () => {
            alert('button click');
        })
    </script>
</body>

위와같은 코드를 작성했을때 이벤트 버블링에 의해서 button 을 클릭하면 body에 있는 이벤트까지 연속적으로 발생하게된다. 만약 body와 button 의 이벤트가 서로 다른동작이고 해당 엘리먼트에 이벤트가 발생했을때만 동작하도록 하려면 버블링을 막는 메소드의 사용이 필요로하게된다.

btn.addEventListener('click', (e) => {
  e.stopPropagation();
  alert('button click');
})

이렇게 자식의 요소에 e.stopPropagation(); 를 추가하게되면 부모로의 이벤트 전파를 막을 수 있고 부모와 자식간에 개별적인 이벤트 동작이 가능하다.

댓글남기기