인앱 브라우저 감지 및 외부 브라우저로 리디렉션하는 방법
date
Jun 22, 2025
slug
detect-inapp-redirect-to-browser
author
status
Public
tags
React
COMATCHING
summary
카카오톡, 라인, 인스타그램 등의 인앱 브라우저에서는 웹사이트 기능이 제한되거나 비정상 동작하는 경우가 많습니다. 이 글에서는 사용자 에이전트를 기반으로 인앱 브라우저를 감지하고, 사용자를 크롬 또는 사파리 등 외부 브라우저로 유도하는 코드 구현 방식을 자세히 설명합니다.
type
Post
thumbnail
category
💻 Frontend
updatedAt
Jun 22, 2025 05:44 PM
COMATCHING은 사용자 매칭 기능을 중심으로 한 대학 축제 기반 서비스로, 카카오톡 공유 링크, 인스타그램등 다양한 모바일 채널에서 유입이 이루어질 것으로 예상되었습니다.
하지만 서비스 출시 전 QA 단계에서, 크롬/사파리 기준으로 개발된 기능들이 특정 환경에서 예기치 않게 동작하지 않는 문제가 확인되었습니다.
소셜 로그인 실패, 버튼 클릭 무반응, 앱 비정상 종료 등
이슈를 재현해본 결과, 문제는 카카오톡·라인·인스타그램 등의 인앱 브라우저에서 발생하고 있었습니다.
문제 원인 분석: 인앱 브라우저는 일반 브라우저가 아니다
대부분의 SNS 앱은 자체 WebView 기반 브라우저를 사용합니다. 모든 인앱 브라우저가 그렇지는 않지만 몇몇 브라우저들은 다음과 같은 제한이 있습니다:
window.open()차단
- 팝업 로그인(OAuth) 실패
- 쿠키 및 로컬 스토리지 제한
- 외부 링크 차단
- 사용자 에이전트 조작 등
특히 Android Chrome이나 iOS Safari에서는 정상 작동하는 기능이 인앱에서는 제한되는 경우가 많았고, 이는 사용자 기준에서 “서비스가 불안정하다”는 인상을 주기 충분했습니다.
해결 전략: 외부 브라우저로 유도하자
단순한 대응이 아닌, 환경을 정확히 진단한 후 우리는 다음과 같은 대응 전략을 세웠습니다.
인앱 브라우저 접속을 감지하고, React 앱 진입 시 외부 브라우저(크롬/사파리)로 유도하는 방식으로접근성과 기능 안정성을 확보하자.
구현 요약
핵심 전략
userAgent기반 인앱 브라우저 감지
- 플랫폼(Android/iOS) 분기 처리
- 카카오톡/라인 등 앱별 대응
- Safari에선 URL 복사 및 안내 메시지 제공
- React
useEffect활용한 자동 리디렉션
실제 코드
import { useEffect } from "react"; const OpenExternalBrowser = () => { useEffect(() => { const userAgent = navigator.userAgent.toLowerCase(); const currentUrl = window.location.href; const inappdeny_exec_vanillajs = (callback) => { if (document.readyState !== "loading") { callback(); } else { document.addEventListener("DOMContentLoaded", callback); } }; const redirect = () => { if (userAgent.includes("kakaotalk")) { window.location.href = "kakaotalk://web/openExternal?url=" + encodeURIComponent(currentUrl); } else if (userAgent.includes("line")) { window.location.href = currentUrl.indexOf("?") !== -1 ? currentUrl + "&openExternalBrowser=1" : currentUrl + "?openExternalBrowser=1"; } else if ( userAgent.match( /inapp|naver|snapchat|wirtschaftswoche|thunderbird|instagram|everytimeapp|whatsApp|electron|wadiz|aliapp|zumapp|iphone(.*)whale|android(.*)whale|kakaostory|band|twitter|DaumApps|DaumDevice\/mobile|FB_IAB|FB4A|FBAN|FBIOS|FBSS|SamsungBrowser\/[^1]/i, ) ) { if (/iphone|ipad|ipod/.test(userAgent)) { alert( 'URL주소가 복사되었습니다.\n\nSafari가 열리면 주소창을 길게 터치한 뒤, "붙여놓기 및 이동"를 누르면 정상적으로 이용하실 수 있습니다.', ); copyToClipboard(currentUrl); window.location.href = "x-web-search://?"; } else { window.location.href = "intent://" + currentUrl.replace(/https?:\/\//i, "") + "#Intent;scheme=https;package=com.android.chrome;end"; } } }; const copyToClipboard = (val) => { const textarea = document.createElement("textarea"); document.body.appendChild(textarea); textarea.value = val; textarea.select(); document.execCommand("copy"); document.body.removeChild(textarea); }; inappdeny_exec_vanillajs(redirect); }, []); return null; }; export default OpenExternalBrowser;
이 컴포넌트는 React 앱 최상단에서 한 번만 실행되며, 접속 환경에 따라 자동 리디렉션을 수행합니다.
적용 효과
- 인앱 브라우저에서의 소셜 로그인 오류 사라짐
- 버튼 무응답, 화면 깨짐 문제 해결
- 크롬/Safari 기준의 안정적인 UX로 통일
- QA 재현이 어려운 플랫폼별 이슈 예방
전체 트래픽의 절반 이상이 인앱 브라우저였다는 점에서,사전 대응 없이는 서비스 신뢰도에 큰 영향을 줄 수 있는 문제였습니다.
회고: 환경도 UX의 일부다
해당 이슈는 단순한 기능 버그가 아닌, 환경 기반의 문제였습니다.
문제가 발생했을 때 “인앱 브라우저 문제니까 어쩔 수 없다”는 식으로 넘기지 않고, 실제 유입 경로를 분석하고 적극적으로 대응한 점이 사용자 경험을 지켜낸 핵심이었다고 생각합니다.
사용자 입장에서 불편은 곧 ‘서비스에 문제가 있다’는 인식으로 이어지기 때문에, 환경에 최적화된 경험을 제공하는 것 또한 개발자의 중요한 역할입니다.
이처럼 작아 보이는 대응이 서비스 전체의 신뢰도에 큰 영향을 미칠 수 있다는 점을 다시금 깨달은 계기였습니다.
결론
인앱 브라우저는 기능 제한이 심하고 예측 불가한 경우가 많다.
따라서 브라우저 환경을 감지하고, 상황에 따라 UX를 유도하는 것 또한 개발자의 중요한 역할임을 느꼈습니다.
앞으로도 모든 화면에서 동일한 서비스를 제공할 수 있도록 크로스브라우징, 플랫폼 감지, 브라우저 유도 같은 대응 코드를 더 정리하고 체계화해보고 학습할 예정입니다.