stopPropagation 과 preventDefault 차이

리오·2023년 10월 15일
0

Front End

목록 보기
10/10
post-thumbnail

컨테이너 안에 버튼이 존재하는 컴포넌트를 구현하는 중에, 버튼을 클릭했을 때, 이벤트 버블링이 발생하여 컨테이너에 등록된 클릭 이벤트 핸들러가 동작하는 문제가 있었습니다.
이벤트 버블링 떄문에 발생하는 문제라는 것은 알고 있었지만, 어디에서나 자주 써왔던preventDefault를 사용해서 막을 수 있을 줄 알고 사용했다가 계속 이벤트버블링이 발생하는 걸 보고 당황했습니다. 몇 분동안 헤매다 stopPropagation의 존재를 깨닫고 이벤트버블링을 막을 수 있었습니다. 이 참에 두 메소드의 차이점을 정리해놓습니다.

두 메소드의 차이

stopPropagation()과 preventDefault()는 자바스크립트와 웹 개발에서 이벤트 처리와 관련하여 사용되는 메소드입니다. 이들의 주요 차이점은 아래와 같습니다.

stopPropagation()

  • 목적: 이벤트가 현재 요소에서 상위 요소로 전파되는 것을 막습니다 (이벤트 버블링 또는 캡처링을 방지).
  • 사용 케이스: 특정 이벤트가 해당 요소에서만 처리되도록 하고, 상위 요소로 전달되어 추가적인 이벤트 핸들러가 호출되는 것을 방지하고자 할 때 사용됩니다.
  • 예시: 만약 버튼이 클릭되었을 때 상위 요소에도 할당된 이벤트 핸들러가 반응하는 것을 원치 않을 때, 버튼의 이벤트 핸들러 내에서 stopPropagation()을 호출하여 이벤트가 상위로 전파되는 것을 막을 수 있습니다.

preventDefault()

  • 목적: 이벤트의 기본 행동을 방지합니다. 즉, 브라우저가 해당 이벤트에 대해 기본적으로 수행하는 행동을 수행하지 않도록 합니다.
  • 사용 케이스: 폼 제출, 링크 클릭 등의 브라우저 기본 행동을 막고 싶을 때 사용됩니다.
  • 예시: 폼을 제출할 때 페이지가 새로고침 되는 것을 방지하거나, 하이퍼링크를 클릭했을 때 새 페이지로 이동하는 것을 막기 위해 사용됩니다.

이 두 메소드의 차이점은

  • stopPropagation()은 이벤트가 다른 요소로 전파되는 것을 막는 반면,
  • preventDefault()는 이벤트 자체의 기본 동작을 방지합니다는 것입니다.

이벤트 버블링

제가 겪었던 문제는 다음과 같습니다. 이미 버튼을 클릭했을 때 이벤트가 동작하는 컴포넌트가 존재하는 상황에서, 버튼을 감싸고 있는 컨테이너를 클릭했을 때도 다른 이벤트가 동작하는 기능을 추가해야 했습니다. 아래는 예시 코드입니다.

function App() {
    const [contents, setContents] = useState('')
  return (
    <div className="App">
      <section className='py-16 px-10 flex flex-col items-center'>
        <div className='shadow-lg rounded-md hover:bg-green-500 border w-60 h-28 flex justify-center items-center'
          onClick={() => { setContents("container click!") }}>
          <button className='p-5 rounded-full bg-gray-200 hover:bg-gray-300 shadow-xl border-2' onClick={() => { setContents("button Click") }}>
            <IcPower />
          </button>
        </div>
        <p className='text-green-400 font-bold text-lg'>{contents}</p>
      </section>
    </div>
  );
}

이 코드에 따르면 div 영역을 클릭했을 때, "container click!" 이라는 문구가 나타나야 하고, 가운데 전원 버튼을 클릭했을 때는 "button Click" 문구가 나타냐야 합니다..

그런데 버튼을 클릭했을 때에도 다음과 같이 "container click!"이라는 문구가 나타났습니다.
stopPropagation 적용 전

사실 이 문제는 이벤트 버블링(event bubbling) 때문에 발생합니다. 웹 브라우저에서는 이벤트가 자식 요소에서 부모 요소로 전파됩니다. 이 경우, 버튼을 클릭하면 먼저 버튼에 대한 클릭 이벤트가 발생하고, 이벤트가 부모의 div까지 버블링됩니다. 따라서 두 이벤트 핸들러가 모두 호출되어 버튼을 클릭했을 때 "button Click"과 "container click!" 두 문구가 순차적으로 나타납니다.

이를 방지하기 위해 버튼의 onClick 이벤트 핸들러에서 event.stopPropagation()을 호출하여 이벤트 버블링을 중단시켜야 합니다. 이렇게 하면 버튼 클릭 이벤트가 div로 전파되지 않습니다.

//stopPropagation을 호출
function App() {
  const [contents, setContents] = useState('')
  return (
    <div className="App">
      <section className='py-16 px-10 flex flex-col items-center'>
        <div className='shadow-lg rounded-md hover:bg-green-500 border w-60 h-28 flex justify-center items-center'
          onClick={() => { setContents("container click!") }}>
          <button className='p-5 rounded-full bg-gray-200 hover:bg-gray-300 shadow-xl border-2' 
                  onClick={(e) => { e.stopPropagation(); setContents("button Click") }}>
            <IcPower />
          </button>
        </div>
        <p className='text-green-400 font-bold text-lg'>{contents}</p>
      </section>
    </div>
  );
}

export default App;

stopPropagation 적용 후

profile
오늘도 승승장구를 위해 연습 중

0개의 댓글