이벤트 버블링 핸들링을 통한 컴포넌트 상호관계 이해하기
어머님이 누구니
들어가며😃
프로젝트에서 알람 컴포넌트를 다루게 되었다. 알람은 페이지 헤더에 속해 있고, 알람 아이콘을 누르면 리스트가 짠 하고 나타나는 전형적인 알람 UI를 따랐다. 단순할 줄 알았던 작업에서 생각보다 많은 이슈들을 만나게 되었고, 오늘은 이슈들을 어떻게 핸들링 했는지 트러블 슈팅 과정에 대해 포스팅 해보려한다.🥲
Issue_01.모바일 화면으로 변경 시 알람창 사라지는 이슈 발생
알람 컴포넌트 내에서 알람이 활성화 된 상태인지를 구분하는 setState를 설정해줬었다. 그런데 데스크탑에서 브라우저 창을 줄여 모바일 사이즈로 넘어갔을때 열려 있던 알람이 사라지는 현상이 나타났다.
오마이갓,,🫥😐🫥😐
원인을 찾으려 알람 컴포넌트를 뜯어보고 css를 여러 방식으로 바꿔보았지만 소용없었다. (이 문제를 찾는데만 거의 반나절을 투자했다지..) 결국 다음날 스프린트 회의 시간에 프론트 팀원들에게 겪고 있는 문제를 공유하니 레이아웃 헤더를 담당하시는 분이 원인에 대해 추측해주셨고 바로 납득이 갔다.
문제가 되는 부분은 헤더 컴포넌트가 데스크탑과 모바일 화면에서 각각 다른 컴포넌트로 배치되고 있는 것이였다. 그래서 데스크탑에서 열려있던 화면의 상태가 모바일에서 유지되지 못하고 상태가 리셋되는 것이였다.
이 문제를 해결하기 위해선 그 알람 컴포넌트가 속해있는 헤더 컴포넌트, 그리고 데스크탑과 모바일 버전을 포함하고 있는 그 상위 컴포넌트에 알람 state를 지정해줬어야 했던 것이다. 험난한 부모찾기..
결국 원인을 알고나서 문제를 해결하는데는 오랜시간이 걸리지 않았지만, 원인을 알아가는데 시간이 꽤 소요됐다. 그리고 그 과정에서 다른 팀원의 컴포넌트에서 해결책을 찾으리라곤 상상도 못했고 원인을 알아버린 순간 아찔했다. 이걸 생각못했다고?😲
사실 기능 자체가 아예 관련없다 생각해서인지 상호관계를 파악할 생각도 못했다. 당연히 내 알람 컴포넌트에 문제가 있을 것이라 생각했던게 탈이였다. 하지만 다행인건 이번 이슈를 계기로 혹시 다른 기능에 원인이 있지 않을까? 하며 문제 파악 범위가 늘어난것이다. 사실 이후 헤더 레이아웃이 변경되서 알람 자체가 짤려보이는 이슈가 또 있었는데, 해당 문제는 아주 수월하게 다룰 수 있었다.
교훈 : 나무를 보지말고 숲을 보라.🌳🌳🌳
Issue_02.알람 외부 영역 클릭 시 알람 창 안닫힘 이슈 발생
원래는 커스텀 훅을 적용하여 ref
를 지정해준 영역 외의 영역 클릭 시 알람창 state
가 변경되어야했다. 하지만 왜인지 전혀 적용되지 않고 닫혀야 할 알림창이 굳게 열려만 있었다. (어쩌다 보니 닫혀라 참깨 챌린지)
처음엔 도무지 이해가 가지않았다. 나는 이 사각형 외부의 영역을 제대로 참조하고 있는데 왜 안되지?!?
하지만 역시 코드는 거짓말 하지 않는다. 거짓말쟁이는 always me..🤥
참조를 가장 상위 컴포넌트에 걸지않은게 원인이였다. 보여지는 사각형 부분의 외부에 알람 아이콘도 포함되어 있다. 그리고 그 아이콘을 눌러야 알람을 열 수 있는데 알람을 여는것과 동시에 알람 외부를 클릭하는 이벤트가 실행되어 state를 변경하는것이였다.
교훈 : 나무를 보지말고 숲을 보라2.🌳🌳🌳🌳🌳🌳
Issue_03.이벤트 버블링 이슈 발생
위 글에서 알수 있듯이 알람 컴포넌트는 다른 컴포넌트와 상호관계를 이루고 있고 로직도 꽤 복잡하다.
알람 아이콘을 누르면 알람 리스트가 나오고, 그 리스트는 각각의 컨텐츠를 담은 컴포넌트로 이루어져있다.
그리고 여기서 간과했던것이 이벤트 버블링이였다. 알람 관련 컴포넌트에서는 대부분의 클릭 이벤트에서 상태 변경을 할당해주었는데 몇몇 부분에서 이벤트가 실행되지 않았다.
아이콘에도, 알람 리스트를 담고있는 컨테이너에도, 각 알람에도, 각 알람의 x버튼에도 ++등등 많은 곳이서 onClick 이벤트가 할당되어있다. 하지만 당시에 이벤트 버블링 이슈를 캐치하지 못해 이게 왜 안되지?를 반복했다.
너무 단순한 e.stopPropagation();
구문 하나 추가 하지 않았어서 문제가 되었던 것이다.
결국 문제가 발생하는 곳을 탐색하며 해당 구문을 추가해주었고, 이슈를 해결할 수 있었다.
처음부터 컴포넌트가 중첩되어 있는 곳에 여러 onClick 이벤트들이 존재한다는 부분을 인지하고 해결법에 접근했다면 더 효율적으로 문제를 해결할 수 있었을텐데 라는 아쉬움이 들었다. 하지만 이제 이벤트 버블링 핸들링 만큼은 기가 막히게 컨트롤 할 수 있다는 것!
교훈 : 나무를 보지말고 숲을 보라3.🌳🌳🌳🌳🌳🌳🌳🌳🌳
회고😃
알람 기능 하나를 구현하는데 예상치 못한 많은 이슈들을 만났다. 단순해보이지만 꽤 까다로웠던 이슈를 해결하는 과정에서 복잡한 로직을 이해하고 컴포넌트간의 상호관계성을 정확히 파악하는 연습이 되었던 것 같다. 지금 완성된 구조를 보면 단순하고 이걸 왜 한번에 못했을까? 싶지만, 그만큼 이슈 핸들링 전 후로 꽤나 성장했다는거겠지? 다음 프로젝트에서는 컴포넌트의 관계성을 더 넓게 봄으로써 더욱 유연하게 문제 해결에 접근할 수 있을것이라 기대해본다.🙃