웹뷰 앱 티 나지 않게 하기: iOS 더블 탭 돋보기 막기
iOS WKWebView에서 텍스트를 두 번 탭할 때 나타나는 돋보기를 막고, 웹뷰 기반 앱을 더 자연스럽게 만드는 ios-double-tap-guard를 소개합니다.

앱을 만들다 보면 네이티브 화면과 웹을 함께 사용해야 할 때가 있습니다. 토스, 당근, CGV처럼 기능과 화면이 많은 서비스도 네이티브와 웹을 함께 활용하는 하이브리드 구조를 적극적으로 사용합니다. 웹 기능을 빠르게 제공하면서 앱 전체 경험을 유지할 수 있기 때문입니다.
이런 앱을 유심히 사용해보면 어느 화면이 WebView인지 짐작되는 순간도 있습니다. 화면 전환 방식, 스크롤 감각, 텍스트 선택처럼 브라우저 고유의 상호작용이 갑자기 나타날 때입니다. 큰 기능보다 이런 작은 차이에서 웹뷰라는 사실이 더 잘 보이기도 합니다.
저도 최근 WKWebView 기반 앱을 만들면서, 웹 기능을 그대로 활용하되 최대한 네이티브 앱처럼 느껴지도록 다듬고 있었습니다.
그런데 사소하지만 꽤 거슬리는 문제가 하나 있었습니다. 사용자가 일반 텍스트를 빠르게 두 번 탭하면 iOS의 텍스트 돋보기가 나타났습니다. 기능이 깨지는 문제는 아니었지만, 이 순간만큼은 "웹사이트를 앱 안에 띄웠구나"라는 느낌이 강하게 들었습니다.
이 문제를 해결하면서 만든 작은 npm 패키지가 ios-double-tap-guard입니다.
웹뷰 앱 티가 나는 더블 탭#
WKWebView는 웹을 앱 안에 자연스럽게 넣을 수 있는 좋은 방법입니다. 하지만 Mobile Safari와 같은 텍스트 상호작용도 함께 따라옵니다.
버튼처럼 보이는 영역이나 선택할 이유가 없는 텍스트를 두 번 탭했을 때 돋보기와 텍스트 선택 UI가 나타나면 앱의 흐름이 갑자기 끊깁니다. 토스나 당근처럼 매끄러운 터치 경험에 익숙한 사용자에게는 이런 짧은 순간도 쉽게 눈에 들어옵니다. 특히 대시보드, 키오스크, 게임, 관리 도구처럼 터치 중심으로 구성한 화면에서는 더 두드러집니다.
WebView 설정에서 텍스트 상호작용 전체를 끄는 방법도 있지만, 그렇게 하면 사용자가 정말 선택해야 하는 텍스트와 입력창까지 영향을 받을 수 있습니다. 제가 원한 건 모든 텍스트 기능을 없애는 것이 아니라, 일반 화면에서 발생하는 의도치 않은 더블 탭 동작만 막는 것이었습니다.
ios-double-tap-guard#
ios-double-tap-guard는 iOS Safari와 WKWebView에서 발생하는 의도치 않은 더블 탭 텍스트 돋보기를 막아줍니다.
기본적인 탭과 스크롤은 유지하고, 다음 요소의 텍스트 상호작용도 기본적으로 보존합니다.
inputtextareaselect[contenteditable]
추가로 텍스트 선택이 필요한 영역은 CSS selector로 직접 제외할 수 있습니다. React 같은 UI 라이브러리의 생명주기에 맞춰 정리할 수 있도록 cleanup 함수도 반환합니다.
패키지는 런타임 의존성이 없고 TypeScript 타입, ESM, CommonJS를 지원합니다. SSR 환경에서 불러와도 안전합니다.
설치#
npm install ios-double-tap-guard기본 사용법#
웹 애플리케이션이 마운트된 뒤 한 번 설치하면 됩니다.
import { installIOSDoubleTapGuard } from "ios-double-tap-guard";
const removeDoubleTapGuard = installIOSDoubleTapGuard();더 이상 필요하지 않을 때 반환된 함수를 호출하면 이벤트 listener가 제거됩니다.
removeDoubleTapGuard();React에서 사용하기#
React에서는 작은 컴포넌트로 만들어 앱이나 WebView용 layout에 넣을 수 있습니다.
import { useEffect } from "react";
import { installIOSDoubleTapGuard } from "ios-double-tap-guard";
export function IOSDoubleTapGuard() {
useEffect(() => installIOSDoubleTapGuard(), []);
return null;
}export function AppLayout({ children }: { children: React.ReactNode }) {
return (
<>
<IOSDoubleTapGuard />
{children}
</>
);
}cleanup 함수를 useEffect에서 그대로 반환할 수 있어서 별도 상태 관리가 필요하지 않습니다.
React Native WebView에서는 어디에 설치해야 할까?#
이 패키지는 React Native 네이티브 코드가 아니라, WebView 안에서 실행되는 웹 애플리케이션에 설치합니다.
예를 들어 react-native-webview가 Next.js 웹을 보여주고 있다면 Next.js 프로젝트에 패키지를 설치하면 됩니다. 이렇게 구성하면 네이티브 앱을 다시 배포하지 않아도 웹 배포만으로 동작을 수정할 수 있습니다.
일반 브라우저와 WebView가 같은 웹 소스를 사용한다면 앱에서만 활성화하는 것도 가능합니다.
const isNativeWebView = "ReactNativeWebView" in window;
const removeDoubleTapGuard = isNativeWebView
? installIOSDoubleTapGuard()
: () => {};앱에서 별도 marker를 주입하고 있다면 그 값을 기준으로 나눠도 됩니다.
선택 가능한 텍스트 남겨두기#
초대 코드, 전화번호, 게시글 본문처럼 사용자가 복사해야 하는 텍스트는 예외로 둘 수 있습니다.
installIOSDoubleTapGuard({
exclude: [
"input",
"textarea",
"select",
"[contenteditable]",
".selectable-text",
"[data-allow-text-interaction]",
].join(", "),
});<p class="selectable-text">이 텍스트는 선택할 수 있습니다.</p>
<code data-allow-text-interaction>ACADEMY-2026</code>exclude를 직접 지정하면 기본 selector를 대체합니다. 입력창과 에디터를 계속 사용할 경우 기본 selector도 함께 넣어야 합니다.
특정 화면에만 적용하기#
문서 전체가 아니라 앱처럼 동작해야 하는 영역에만 제한할 수도 있습니다.
const appSurface = document.querySelector("[data-app-surface]");
if (appSurface) {
installIOSDoubleTapGuard({ root: appSurface });
}일반적인 글과 터치 중심 UI가 한 페이지에 섞여 있다면 root를 제한하는 방식을 권장합니다.
이미지 뷰어의 더블 탭 확대나 동영상 플레이어의 더블 탭 탐색처럼 의도적으로 더블 탭을 사용하는 기능도 exclude에 추가하거나 guard 범위 밖에 두면 됩니다.
직접 사용해 보기#
패키지는 npm과 GitHub에 공개해두었습니다.
- npm: https://www.npmjs.com/package/ios-double-tap-guard
- GitHub: https://github.com/JunDev76/ios-double-tap-guard
아주 작은 패키지지만 WebView 기반 앱에서 은근히 신경 쓰이던 부분을 깔끔하게 정리할 수 있었습니다. 비슷한 문제를 겪고 있다면 한 번 사용해보세요. 다른 환경에서 발견한 문제나 개선 아이디어는 GitHub issue로 남겨주시면 감사하겠습니다.