RxBinding을 사용하여 안드로이드 버튼 중복 클릭 방지하기
25 May 2019 | RxBinding RxJava Android버튼을 터치시 발생하는 이벤트를 처리할 때, 대부분의 경우 중복 터치 이벤트를 막아야 한다. 예를 들어 송금 버튼이 있을 경우 사용자가 아주 빠른시간에 연속해서 두번 터치한다고 해서 돈이 두 번이나 빠져나가서는 곤란하다. RxBinding을 사용하면 쉽게 중복터치를 차단할 수 있다(꼭 중복 터치 뿐만 아니라 RxJava의 훌륭한 메서드들을 안드로이드 UI에 적용할 수 있으니 꽤나 유용하다).
debounce() VS throttleFirst()
중복 터치 이벤트를 막기 위해서는 debounce()
와 throttleFirst
메서드를 사용할 수 있다. 둘다 중복 터치를 차단 할 수는 있지만 미세한 차이가 있기 때문에 자세히 알아보자.
debounce()
debounce()
는 특정 시간(예를들어 1초)을 정해주면, 특정 이벤트가 발생한 직후부터 1초 동안은 어떤 이벤트도 발생하지 않아야만 1초 전에 발생한 이벤트가 실행된다. 만약 사용자가 처음 버튼을 클릭한 이후 0.5초 이후에 또 버튼을 클릭했다면, 처음 버튼을 눌렀던 이벤트는 없었던 일이 되어버리고 0.5초 뒤에 누른 두 번째 버튼 이벤트를 다시 1초동안 감시한다. 두 번째 누른 버튼 이벤트 이후 1초 동안 아무 이벤트도 없었다면 그때서야 두 번째 버튼 이벤트만 발생한다.
throttleFirst()
throttleFirst()
역시 특정 시간(예를들어 1초)을 정해주어야 한다. debounce()
와는 다르게 특정 이벤트가 발생한 직후 곧바로 이벤트가 발생하고 이후 1초 동안은 어떤 이벤트가 들어와도 무시된다. 즉 사용자가 “송금” 버튼을 한 번 클릭한 이후 0.5초 뒤에 한 번 더 클릭했다면 두 번째 클릭은 무시된다. 주의해야할 점은 사용자가 처음 “송금” 버튼을 누르고 나서 1.1초뒤에 한 번더 클릭 할 경우에는 이벤트가 두 번 작동한다는 것이다. 이 부분은 바로 아래에서 조금더 다뤄보자.
무엇이 더 적합할까?
위에서 debounce()
와 throttleFirst()
를 알아 보았다. 둘다 간단하게 중복 터치를 막을 수 있는데, 뭐가더 좋을까?
사실 정답은 없다. 정해진 답은 없지만 처해진 상황에 따라 더 적합한 메서드를 선택해야 한다.
“송금” 버튼을 클릭한 이후 서버로 부터 응답을 받아오는 시간이 너무 오래걸린다(3초)고 가정해보자. “송금”버튼을 누르고 서버로부터 응답을 받고 나면 화면이 전환되어야 하는데 사용자에게 3초라는 시간은 너무 긴 시간이다. “버튼눌렀는데 왜 안넘어가지? 버튼이 안눌렸나? 다시눌러야지” 라며 2초 후에 또 버튼을 누를 것이다.
위의 상황에서 debounce()
에 시간을 3초로 걸어놓았을 경우를 생각해 보자. 사용자가 성격이 너무 급해서 2초 마다 버튼을 클릭하며 “아 왜이렇게 느린거야!?”라고 소리칠 수도 있다. 이 사용자가 2초 마다 버튼을 계속 클릭한다면 절대 다음 화면으로 넘어갈 수 없다. 언젠가는 이 사용자가 버튼 클릭 이후 3초를 기다리길 바랄 수 밖에 없다.
이번엔 throttle()
에 시간을 3초로 걸어놓았을 경우를 생각해보자. 성격 급한 사용자가 처음 버튼 클릭 후 2초뒤에 또 버튼을 클릭해도 그 이벤트는 무시된다. 즉 맨 처음 누른 그 시점에만 곧 바로 이벤트가 적용되어 서버로 요청이 날라갔고, 2초 뒤에 누른 이벤트는 무시된다. 대부분 경우 버튼 중복 터치 이벤트 방지는 throttle()
이 좋은 선택이 될 수가 있지만, 서버로 부터의 응답이 조금 늦어져서 3.2초가 걸릴 경우 3.1초에 클릭한 중복 터치 이벤트는 무시하지 못해서 송금이 될 것이다. 따라서 버튼 클릭 이후 해당 버튼이 없어지거나 화면이 바뀐다면 throttle()
의 시간을 넉넉히 잡아주는 것이 좋아보인다.
사실은…
사실 debounce()
는 버튼 중복 클릭 이벤트 방지에도 쓰이긴 하지만, 더 적합한 곳은 주소 검색시 자동완성 기능 같은 곳에 적합한것 같다. 나는 최근에 안드로이드에서 카카오 API를 사용하여 주소 입력시 관련 주소들을 나열해주는 자동완성 기능을 개발했는데, 이때 debounce
를 사용해서 효율성을 높혔다. 내가 찾고 싶은 것은 판교역인데, ㅍ,파,판 … 을 입력 할 때마다 카카오에 쿼리를 날려서 데이터 낭비가 심한 상황이 생겼다. 이때 적당히 debounce
를 준다면 매번 쿼리를 날리지 않게 되고, 사용자가 입력을 하다가 아주 잠시 멈추는 순간에 추천 검색어가 뜨게 된다.