All Posts

iOS 고유 클릭 이벤트 이슈 해소

iPhone에서만 안되는 click event 버그 대응..

결론만 말하면…(톺아보기)

iOS만의 이슈로 iPhone이나 iPad의 경우, a 태그나 input 태그가 아닌 경우 클릭 이벤트 리스너를 붙여놔도 제대로 동작하지 않는 경우가 있다. 이때는 click 이벤트 리스너를 붙인 태그에 스타일로 cursor: pointer;를 넣어주면 해소된다. 이유는 iOS가 dom이 로딩된 후 클릭 이벤트 리스너가 추가된 dom을 클릭해도 클릭 이벤트를 fire 시켜주지 않기 때문이다.(mouseover, touchstart 등은 정상작동) 스타일로 curosr: pointer를 추가해주면 iOS가 해당 dom이 클릭 대상이라고 인지하고 클릭시 클릭 이벤트를 fire 시켜주게 되어 문제가 해소된다.


그동안 아주 오랜 시간동안 안드로이드 폰을 사용하고 있었다. 최근에 아이폰 XR로 폰을 바꿨다. 카드를 만들고 기기값을 감면받아놓고 공짜폰이라고 좋아한 호구인건 비밀 아이폰 유저가 되니깐 갑자기 애플 덕후가 된 거 같은 기분이… 애플짱! 각설하고 아이폰으로 바꾼 겸사겸사 iOS 이슈 대응 로그를 남긴다.

이슈 현상 리포트

특정 아이콘의 클릭 이벤트가 아이폰에서만 정상적으로 작동하지 않는 문제 발생

  • 아이폰에서는 safari, chrome, firefox 모든 브라우저에서 동작하지 않음 확인

  • 안드로이드 폰에서는 samsung browser까지 정상 동작 확인

  • 맥북에서 safari로 확인할 경우 정상 동작 확인

  • 맥북에서 chrome 개발자 환경 mobile로 설정 한 경우 정상 동작 확인

iOS 고유 버그로 확인

2010년도의 자료에서도 확인할 수 있는 버그(이정도 되면 애플에서는 의도적으로 이 버그를 유지하고 있다고 볼 수 있음)

해당 이슈는 레거시 코드에서 발생한 이슈로 코드 히스토리를 봤을 때 거의 처음부터 제대로 동작하지 않았음을 알 수 있었다.

(QA를 아무리 열심히 하더라도 전혀 예측하지 못하는 버그에는 대응하기가 쉽지 않음을 다시 한번 깨닫…)

2010년 iPhone click event delegation에 대한 글

위 글의 내용을 정리하면 다음과 같다.(영어니깐..)

  1. 이벤트 버블링에 대한 개론
  2. 아이폰에서는 click event 관련 버그가 있음
  3. 애플에서 아마도 의도적으로 이를 무시하도록 해놓은 것 같음

일반적인 웹브라우저는 html 태그 엘리먼트들을 그리고 이를 DOM에 연결해두지,

그렇다면 이벤트는 어떻게 인지할까?

특정 엘리먼트를 사용자가 클릭했을때 해당 DOM은 자신이 클릭 되었음을 알리는 방법으로 Click Event를 Fire 시킬 것이다.

이벤트 전파방식(Event porpagation)을 정해둔대로(버블링 혹은 캡처링) 이벤트는 전달될 것이고, 해당 이벤트를 전달받는 DOM 중에 클릭 이벤트 리스너가 붙어있는 녀석이 있다면 해당 리스너의 콜백 함수가 실행될 것이다.

그럼 애플의 개발자들은 왜 click event만 특수하게 다뤘을까…?(어디까지나 나의 추측임)

DOM을 관리해야하는 브라우저 입장에서는 어떤 DOM이 클릭 될지도 모른다.

사용자는 뭐든 클릭해댈 가능성과 자유가 있고, 특히 모바일에서는 스크롤이든 확대든 휴대폰을 잡는 등 거의 모든 동작이 Click Event를 Fire 시키게 될 가능성이 있다.

모든 엘리멘트들이 수많은 가능성에서 클릭 될 것이고 그때마다 Click Event를 Fire 시키는 건 상당히 많은 리소스를 소비하게 될 가능성이 있다.

iOS 개발자들은 아마도 의도적으로 Click Event만 특별히 다루는 것 같다.

iOS 개발자들이 선택한 방식

  1. 단순히 클릭되었다는 사실만 가지고는 Click Event를 Fire 시키지 않는다.(리소스 개이득)
  2. 단, 엘리먼트가 의도적으로 클릭 됨직하다고 판단 될 경우에만 클릭시 Click Event를 Fire 시킨다.(클릭 됨직한 건 iOS가 정한듯…)

결과적으로 해당 이슈를 해소하기 위해서는 iOS가 클릭 됨직한 엘리먼트로 판단하는 기준에 맞춰서 코드를 수정해주면 된다.

버그 픽스 방법

  1. a 태그나 input 태그로 만든다.

    <a href="javscript:alret('wow');">Press</a>
  2. 태그에 style로 cursor를 포인터로 설정해둔다.

    .clickable {
       cursor: pointer;
    }
  3. 엘리먼트 자체에 Click Event Listener를 inline으로 붙인다.

    <div onclick="location.href='www.naver.com';">Go to Naver<div>

이번에 겪은 이슈는 레거시의 특정 아이콘에서만 클릭이 안되는 이슈였음

PC웹에서는 자연스레 cursor:pointer;를 붙이고 있었고, 그 코드를 복사해서 만든 모바일웹 아이콘은 정상적으로 동작했지만, 새로 만든 icon의 스타일에는 해당 스타일이 빠져있었던 이슈라 2번 방식으로 간단히 해소했다.

반응형웹이라면 default로 cursor:pointer; 설정해주고, 리액트에서는 onClick이 붙어있는 컴포넌트에는 clickable 클래스를 붙여주자.

조금만 검색하면 바로 해결책을 찾을 수 있는 문제였지만 단순히 해결책을 복붙만 하고 싶지 않았다. 아이폰 유저가 된 겸사겸사 iOS 개발자는 왜 이런식으로 구현을 했을까에 대해 고민해보고 싶었다. 시간이 지날수록 더 많이 고민하고 더 많이 생각하고 더 많은 부분을 고려하고 코드를 작성하고 싶다. 그런 개발자가 되고 싶다. 시간적인 여유가 없더라도 이렇게 하고 싶다. 여러가지 이슈들이 치고 들어오지만 어차피 해야하는 일이라면 좀 더 재미있는 방법으로 고민하고 찾아보고 그리고 또 로그를 남기며 일해야집! 회사에 프론트엔드 개발자라고는 혼자밖에 없어서 외롭지만… 같이 고민을 할 수 있는 동료가 있으면 좋겠습니다. 와그 프론트엔드 개발자 채용공고