안녕하세요. 김용성입니다.
지난 주에 있었던 코딩테스트 중에 JavaScript를 사용해서 해결해야하는 것들이 있었는데요. 그러다보니 제가 React에만 치중해 있느라 JavaScript에 대한 지식이 많이 부족했었다는 것을 자각하게 되었습니다.
그러한 연유로 당분간은 Vanilla Js를 많이 사용해볼 것 같아요. 그와 동시에 관련된 개발지식들도 포스팅할 예정인데요.
그 첫번째로 JavaScript 이벤트 버블링에 대해 포스팅해보도록 하겠습니다.
우리가 흔히 사용하는 페이지들을 보다보면 정말 많은 컴포넌트 요소들이 중첩되어있는 것을 확인하실 수 있을거예요. 예시로 다음과 같은 화면을 보겠습니다.
사용자 입장에서는 양 옆에 있는 화살표 버튼을 누르면 현재 보고있는 상품이 다른 상품으로 넘어간다고 직관적으로 생각할거예요. 그리고 그 외의 상품 사진 부분을 클릭했을 경우에는 해당 상품페이지로 넘어가는 것을 생각하겠죠.
이러한 컴포넌트를 구현할 때 구조가 이렇게 되어있다고 가정해보겠습니다.
<div class="item-image">
<div class="left-button">
<div class="right-button">
</div>
물론 실제로는 이와 다를 가능성이 높지만 저는 구조를 언급하는 것이기 때문에 이정도로 가정하겠습니다.
그렇다면 left-button을 누를 경우 왼쪽 상품을 보여주게끔, right-button을 누를 경우에는 오른쪽 상품을 보여주게끔, 이를 감싸고 있는 item-image를 누를 경우에는 상품의 상세 페이지로 이동하게끔 각각의 이벤트를 걸어줄거예요.
간단하게 다음과 같이 만들어보았습니다.
이제 우리는 이벤트를 걸어주면 돼요.
'<' 버튼을 누를 경우에는 '왼쪽 버튼을 눌렀습니다.',
'>' 버튼을 누를 경우에는 '오른쪽 버튼을 눌렀습니다.',
검정색 부분을 누를 경우에는 '상품을 클릭하였습니다.' 라는 alert창이 뜨도록 해주겠습니다.
//index.js
const left = document.getElementById("left-button")
const right = document.getElementById("right-button")
const item = document.getElementById("item-image")
left.addEventListener("click", () => {
alert("왼쪽 버튼을 눌렀습니다.")
})
right.addEventListener("click", () => {
alert("오른쪽 버튼을 눌렀습니다.")
})
item.addEventListener("click", () => {
alert("상품을 클릭하였습니다.")
})
이렇게 코드를 작성해서 html파일에 연동해준 뒤에 각각의 버튼을 클릭해줍니다.
그렇다면 어떠한 현상이 발생할까요??
검정색 공간을 눌렀을 때는 우리가 바라던 '상품을 클릭하였습니다.'라는 alert창이 뜨는 것을 확인하실 수 있을거예요. 그렇지만 왼쪽 오른쪽 버튼을 눌렀을 때 문제가 발생할텐데요. alert 이벤트가 두번 발생하는 것을 확인할 수 있을겁니다.
이러한 현상을 바로 JavaScript의 이벤트 버블링 현상이라고 합니다.
여러개의 컴포넌트가 겹쳐져 있을 때 어떠한 것을 선택하였는지 분간을 못하기에 부모 컴포넌트에 걸린 이벤트까지 중첩해서 나타나는 현상을 바로 이벤트 버블링이라고 하죠. 이러한 이벤트 버블링은 어떠한 설정으로 인해 야기되는 것이 아닌 그냥 DOM 자체가 함수를 처리하는 방법일 뿐입니다.
마치 책이 이렇게 겹쳐져 있는데 이 책 더미를 가리키며 '책을 가져오렴' 이라고 말하는 것과 같은 상황입니다.
이러한 것을 고치기 위해서 우리는 어떠한 조치를 내려주어야 할까요??
멈춰!
이러한 이벤트 버블링 현상을 방지하기 위해서 우리는 stopPropagation이라는 JavaScript 내장함수를 사용할 수 있습니다.
사용법은 간단합니다. 이벤트 버블링으로 인한 전파를 원하지 않는 자식 컴포넌트의 함수에 같이 작성해주면 돼요.
left.addEventListener("click", e => {
e.stopPropagation() // 사용법
alert("왼쪽 버튼을 눌렀습니다.")
})
이렇게 변경해주고 난 뒤면 위에서 보여드렸던 것처럼 이벤트 전파가 발생하여 중첩된 이벤트가 발생하는 것을 방지해줄 수 있습니다. 결과는 다음과 같아요:)
당분간 JavaScript 스킬을 늘리기 위해 Jquery나 어떤 외부 모듈을 이용하지 않고 만들고 싶은 동적 이벤트들을 구현할 생각이예요. 그렇기에 이러한 것들에도 생각을 많이 하게 되더라고요. 개인적으로 이러한 현상에 대해서는 머리로는 알고 있지만 이게 무엇이냐 했을 때 머뭇거릴 수 있다고 생각합니다.
제 포스팅과 함께 잘 정리하시고 해결방법에 대해서도 잘 알고 계셨으면 좋겠습니다.:)
읽어주셔서 감사합니다.