터치와 클릭, 우리 깐부잖아터치와 클릭을 사용하지 않는 하루를 상상해보자. 과연 어떨까? 필자는 두 동작 없는 하루를 이제는 상상할 수 없다. 사용자일 때는 무의식적으로 사용해서 이 두 동작의 관계에 대해 깊게 생각해 본 적이 없었다. 프론트엔드 개발자가 되고 터치와 클릭의 차이점 때문에 발생하는 문제를 맞닥뜨린 이후에서야 두 동작의 관계에 대해서 생각해보게 되었다. 이 글로 이제 막 프론트엔드 개발에 뛰어든 필자의 경험을 통해 터치와 클릭의 공통점과 차이점, 발생할 수 있는 문제와 그 해결 방안에 대해 공유하고자 한다. 문제의 발단필자는 TOAST UI 오픈소스를 메인테이닝 하면서 아래와 비슷한 함수를 본 적이 있다.
이 함수는 모바일 기기의 경우 마우스 이벤트 대신 터치 이벤트를 사용하기 위해 이벤트 타입을 변환하는 기능을 한다. 이벤트 타입 변경 함수를 사용한 방법은 지금까지 문제없이 동작했었다. 그러나 예상치 못한 문제가 발생했다. TOAST UI DatePicker에서 이벤트 타입 변환 함수를 사용해 터치 이벤트 리스너를 사용하면 날짜를 터치와 클릭
무엇이 문제였는지 확인하기 위해 먼저 터치와 클릭에 대해서 알아보자. 지금까지는 이벤트 타입 변환 함수를 문제없이 사용했다. 터치와 클릭은 어떤 공통점이 있어서 이벤트 타입을 1:1로 변환할 수 있고, 어떤 차이점이 있어서 이벤트 타입을 변환해야 할까? 공통점터치와 클릭은 화면과 상호작용을 위해 화면상의 요소를 눌렀다 뗀다는 단순하지만 아주 중요한 공통점을 가지고 있다. 즉, 두 행위는 모두 누르는 동작과 떼는 동작의 시퀀스이다. 이 때문에 이벤트 타입 변환 함수처럼 이벤트 타입을 변환하는 것만으로 터치와 클릭을 바꿔서 지원할 수 있는 것이다. 차이점두 행위가 그렇게 유사하다면 왜 이벤트 타입 변환 함수가 필요한 것일까?
모바일 장치가 대중화되던 초기에는 앞서 말한 공통점과 차이점을 고려하지 않은 OS나 애플리케이션을 쉽게 볼 수 있었다. 이것들은 사용자에게 불편함과 어색함을 느끼게 했고 원성을 들을 수밖에 없었다. 결국 이 문제들은 머지않아 우리가 알고 있는 방식으로 수정되었다. 진짜 원인
그러나 필자는 문제를 맞닥뜨리고 말았다. 무엇 때문에 발생한 문제인지 알아보기 위해 자바스크립트에서 클릭과 터치가 어떻게 다른지 알아보자. 연속된 동작클릭은 이에 대한 이벤트 타입으로 크롬 개발자 도구를 켜고 장치 툴바 토글( )을 클릭해 터치 동작도 수행해보자.위 예제에서 수행하는 코드는 아래와 같다.
마우스를
이용해 클릭할 때는 터치와 클릭은 누르는 동작과 떼는 동작의 시퀀스라고 했다. 자바스크립트의 이벤트에서도 각 구분 동작에 대한 이벤트를 따로 발생시킨다. 터치와 관련된 이벤트 타입으로는 그러면 각 이벤트가 어떤 순서로 발생하는지 확인해보자. 이번에도 터치 동작을 수행해보자. 위 예제에서 수행하는 코드는 아래와 같이 발생한 이벤트 타입을 출력한다.
수행 결과, 우리는 위와 같은 순서로 이벤트가 발생한다는 것을 알았다. 특이한 점은 단순 터치 동작을 수행할 때만 터치-클릭 딜레이그런데 왜 이벤트 타입 변경 함수를 사용해서 클릭에 대한 이벤트 리스너를 터치에 대한 이벤트 리스너로 변경할까? 일반적으로 실제로 그런지 확인해보자.
위 코드는 터치 동작에는 마우스 동작과 달리 다양한 제스쳐가 있으며 더블 탭 줌도 그런 다양한 제스처 중 하나다. 더블 탭 줌을 시도하려 할 때 해당 위치에 버튼이 있는 경우를 생각해보자. 위 그림처럼 만약 딜레이가 없다면 우리는 첫 번째 터치에서 버튼을 클릭하게 될 것이다. 버튼이 우리가 하려는 동작에 아무런 영향을 미치지 않는다면 괜찮겠지만 그렇지 않다면 우리는 제스쳐를 수행할 수 없을 것이다. 딜레이가 있다면 어떻게 될까? 위 그림을 보자. 첫 번째 터치에서 버튼을 터치하지만, 아직 클릭은 되지 않은 상태이다. 그사이에 다시 한번 터치하면 클릭은 수행되지 않고 우리가 원하는 대로 제스쳐를 수행할 수 있다. 그러나 앞서 필자의 경험처럼 딜레이로 인해 문제가 발생할 수도 있다. TOAST UI DatePicker의 날짜를 터치하면
해결하기
문제점에 대해 봤으니 이제는 문제를 해결하자. 딜레이 제거일반적으로 모바일 기기에 보여줄 페이지는 모바일 기기에 최적화해 만든다. 이 경우 페이지 내 요소의 크기가 충분히 커서 더블 탭 줌 등의 제스쳐가 필요 없을 수 있다. 2014년 배포된 Chrome 32버전부터는 모바일 페이지에 최적화된 사이트의 경우 딜레이를 만들지 않는다. (다른 브라우저도 대부분 지금은 동일하게 동작한다.) 뷰포트의 너비가 기기 화면의 너비와 동일하다면 이를 모바일에 최적화된 사이트라고 한다. 그렇다면 딜레이 예제 페이지
단순히 뷰포트의 너비만 지정해주었을 뿐인데 앞서 보았던
마우스 이벤트 제거그러나 TOAST UI처럼 페이지 전체가 아닌 내부에 들어갈 요소를 만든다면 위 방법은 효과적이지 않다. 그러므로 이벤트 타입 변환 함수를 사용해 마우스 이벤트 리스너를 터치 이벤트 리스너로 변경하는 방법을 사용해보자. 그러나 마우스 이벤트는 계속 발생하므로 필자의 경험처럼 의도하지 않은 사이드 이펙트가 유발될 수 있다. 앞서 본 이벤트 발생 순서에서 다른 터치 동작처럼 마우스 이벤트를 발생시키지 않는다면, 이런 문제를 감수하지 않아도 된다. 이는 이번에도 터치 동작도 수행해보자. 위 예제에서 수행하는 코드는 아래와 같다.
수행 결과 마우스 클릭 시에는 주의할 점앞서 "마우스 이벤트 제거"에서 또한, 리스너에 첫 번째 인자로 전달되는 이벤트 객체도
마치면서
이 글에서는 필자가 경험한 문제와 이를 해결하기 위해 이벤트 타입 변환 함수를 올바르게 사용하여 코드 중복은 최소화하면서 터치와 클릭을 문제없이 지원하는 방법도 같이 보았다. 터치 또는 클릭 시 이벤트 발생 순서를 잘 알고, 딜레이의 제거와 마우스 이벤트 제거 등을 적절히 활용하는 것을 잊지 말자. 모바일 시장의 규모가 데스크톱을 처음 역전한 이후, 모바일 웹 브라우징의 중요성은 계속해서 증가해왔다. 그러나 아직은 데스크톱 브라우징의 규모도 작지 않아 모바일 브라우징에만 집중할 수는 없는 상황이다. 따라서 웹 브라우징의 사용자 상호작용에서 가장 기본인 터치와 클릭을 명확히 구분해서 올바르게 사용하는 것이 매우 중요하다. 프론트엔드 개발에 뛰어들기 시작한 많은 개발자들이 이 글을 모바일 웹 브라우징에서 더 많은 기능을 지원하기 위한 초석으로 삼을 수 있기를 바란다. |