반응형

📱 카카오톡 웹뷰에서 내 웹앱이 안 될 때: 안드로이드와 아이폰 각각의 해결 방법

🔍 웹뷰(WebView)란 무엇이고, 왜 문제가 될까?

요즘은 많은 사람들이 카카오톡, 인스타그램 같은 앱 안에서 링크를 클릭해 웹사이트를 열어본다.

이때 뜨는 창이 바로 웹뷰(WebView) 이다. 웹뷰는 앱 내부에 내장된 간이 브라우저라서, 일반 브라우저와는 다르게 기능 제한이 많다.

대표적으로,

  • 새 창 열기(window.open)가 막혀 있거나,
  • 특정 스킴 호출(intent, deeplink)이 차단되어 있는 경우가 많다.

문제는, 이런 제한된 환경에서는 내 웹앱이 예상대로 동작하지 않는다는 점이다. 특히 외부 브라우저에서 열기를 유도해야 하는 경우(ex. 결제, 다운로드, 고급 기능 사용 등)에는 웹뷰를 탈출시키는 처리가 꼭 필요하다.

이 글에서는, 카카오톡 웹뷰에서 내 웹앱이 제대로 작동하지 않았던 문제를 만나고, 이를 AndroidiOS 각각에서 해결해나간 과정을 정리했다.

💡 문제 상황

회사 플랫폼을 사용하는 사용자들이 카카오톡 웹뷰에서 구글 로그인을 시도해 막혔다는 피드백을 받게 되었다. 왜 그런지 알아보니 웹뷰에서는 이러한 SNS 로그인을 차단한다는 것을 알게 되었다.

"카카오톡으로 열었더니 버튼이 안 눌려!"

직접 확인해보니 카카오톡 웹뷰에서는 다음 문제가 공통적으로 발생했다:

  • window.open('_blank')로 새 창을 열었는데, 화면이 리프레시만 됨
  • 특히 iOS(아이폰)에서는 링크 클릭 후 아무 반응 없음
  • 안드로이드는 새 창 대신 웹뷰에서 그대로 머무름

즉, 내가 의도한 “외부 브라우저로 이동” 기능이 전혀 동작하지 않았다.


🔧 해결 과정 1 – Android: intent://로 Chrome 강제 열기

Android의 경우 다행히 해결이 빨랐다.

intent:// 스킴을 사용하면 카카오톡 웹뷰에서도 Chrome을 강제로 실행할 수 있었다:

const url = location.href;
location.href = `intent://${url.replace(/^https?:\/\//, '')}#Intent;scheme=https;package=com.android.chrome;end;`;

이 코드를 버튼에 연결하니, Chrome이 정상적으로 실행되고 내 웹사이트가 바로 열렸다.


❗ 추가 문제 상황 – iOS는 window.open('_blank')가 안 됨

그런데 iPhone에서는 다르게 굴었다.

window.open('_blank')도, window.location.href = ...웹뷰 안에서만 동작하고, Safari나 Chrome으로 넘어가질 않았다.

특히 iOS의 카카오톡 웹뷰는 새 창 열기 기능을 거의 완전히 차단하고 있었다.


🛠 해결 과정 2 – iOS: googlechrome:// 스킴으로 해결

알아보니 iOS용 Chrome은 커스텀 스킴을 통해 열 수 있다는 사실을 알게 됐다.

function openInChromeiOS() {
  const chromeURL = "googlechrome://" + location.href.replace(/^https?:\/\//, '');
  window.location.href = chromeURL;

  // Chrome이 없을 경우 대비
  setTimeout(() => {
    alert("Chrome이 설치되어 있지 않다면, 우측 상단 메뉴에서 Safari로 열어주세요.");
  }, 1000);
}

이 코드를 통해 iOS 기기에서도 Chrome이 설치되어 있다면 문제없이 내 웹사이트가 열렸다.

단, Chrome이 설치되어 있지 않은 경우엔 아무 반응이 없기 때문에, 사용자에게 안내 메시지를 함께 보여주는 처리가 필요했다.


📌 최종 UX 구성

<button onclick="openInChromeiOS()">브라우저에서 열기</button>
<p>혹시 안 열릴 경우, 카카오톡 우측 상단 ••• 메뉴에서 Safari 또는 Chrome으로 열어주세요.</p>

✍️ 마무리하며

웹앱을 배포할 때 ‘브라우저에서는 되니까 끝!’이라고 생각했지만,

실제 사용 환경인 인앱 웹뷰에서는 동작 방식이 전혀 다르다는 것을 이번에 확실히 체감했다.

  • Android는 intent://로 대응
  • iOS는 googlechrome:// 스킴으로 대응
  • Chrome 미설치 시를 고려한 UX 안내 필수

앞으로는 웹앱 초기 설계 단계부터 인앱 브라우저 대응 전략도 함께 고려해야겠다고 다짐했다.

반응형
반응형

문제

해당 라이브러리의 카카오맵을 생성하기위해서는 width, height 를 입력받아야한다. docs 에서 width, height 의 type 이 String, Number 로 작성되어있어 숫자 혹은 숫자와 단위를 포함한 문자열을 입력할 수 있다는 것을 알 수 있다. 하지만, 예상외로 로컬 환경에서 문자열 값이 적용되지 않는 문제를 발견했다.

문제코드

const r = S(() => ({
      width: isFinite(+i.width) ? i.width + "px" : i.width,
      height: isFinite(+i.height) ? i.height + "px" : i.height
}));

해당 코드는 얼핏보면 문자열과 숫자를 모두 입력받는 것을 의도하지만 정작 문자열값이 적용이 되지 않았다.

<KakaoMap
    :width="`${50}vw`"
    :height="`${90}vh`"
    :lat="37.566826"
    :lng="126.9786567"
    @onLoadKakaoMap="onLoadKakaoMap"
/>
  • 추후에 알게 된 것이지만 width, height 값에 문자열을 삽입하려면 위와 같은 작업을 거쳐야 했다. 이러한 설명이 docs에는 준비되어있지않아 애초에 문자열로 받도록 한다면 문제가 없을것이라 판단했다.

멍청 비용 발생

<KakaoMap
    :width="'50vw'"
    :height="'90vh'"
    :lat="37.566826"
    :lng="126.9786567"
    @onLoadKakaoMap="onLoadKakaoMap"
/>
  • 작은 따옴표로 감싸면 된다 ^^;
  • 멍청비용 한시간 발생
반응형
반응형

배경


useEffect 를 이용해 한번만 함수를 처리하게 하려고 했다.
하지만 왜인지 모르게 자꾸 렌더링이 두번씩 되어 함수가 두번 실행이 되었다.

 

해결

https://youngble.tistory.com/175

 

[React] useEffect 2번 실행되는 이유

다음과 같이 useEffect를 사용하여 jQuery메서드 on 으로 해당 요소를 이벤트 등록을 해주었다. 그런데 해당 태그를 눌러 이벤트가 발생하면 2번이 실행돼서 왜이러지? 찾아보니깐 useEffect부분에서 두

youngble.tistory.com

다음 글을 보면 index.js 의 React.StrictMode 때문이라고 한다.

 

import React from 'react';

function ExampleApplication() {
  return (
    <div>
      <Header />
      <React.StrictMode>
        <div>
          <ComponentOne />
          <ComponentTwo />
        </div>
      </React.StrictMode>
      <Footer />
    </div>
  );
}

 

개발모드에서만 작동되는 StrictMode 는 다음과 같은 효과를 준다고한다.

  1. 안전하지 않은 생명주기를 사용하는 컴포넌트 발견
  2. 레거시 문자열 ref 사용에 대한 경고
  3. 권장되지 않는 findDOMNode 사용에 대한 경고
  4. 예상치 못한 부작용 검사
  5. 레거시 context API 검사
  6. Ensuring reusable state

https://ko.legacy.reactjs.org/docs/strict-mode.html

 

Strict 모드 – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

문서에 들어가면 더 자세히 볼 수 있다.

 

결론은 index.js React.StrictMode 를 제거하면 한 번만 호출 된다.
반응형
반응형

배경

opencv 를 쓰기 위해 파이썬 코드를 작성해 nodejs 서버에서 실행하고 있었다.

결과

https://github.com/pyinstaller/pyinstaller/issues/2613

 

How to generate an executable on Linux for Windows? · Issue #2613 · pyinstaller/pyinstaller

I'm trying to generate an executable from Linux for Windows. pyinstaller --onefile --windowed montecarlo.py I run this command and get a single executable that works on Linux just fine, I can open ...

github.com

 

하지만 조사결과 그렇게하지 못한다고 한다.

Pyinstaller 메뉴얼을 보면 다음과 같은 글이있다.

PyInstaller is tested against Windows, Mac OS X, and Linux. However, it is not a cross-compiler: to make a Windows app you run PyInstaller in Windows; to make a Linux app you run it in Linux, etc. PyInstaller has been used successfully with AIX, Solaris, and FreeBSD, but is not tested against them.

according to the comments in that answer it appears the ability to cross-compile was removed in 1.5, which was many releases ago. However, the secondary answer mentioning wine is correct -- you can usually create working Windows executables if you run pyinstaller under wine.

And as @xoviat mentioned, pyinstaller is cross-platform -- the compilation program works on Linux, OSX, and Windows. However, the resulting executables are platform specific.

 

한마디로 cross-compiler 가 아니라 불가능하다는 것이다. Wine 을 쓰는걸 추천한고 한다.

 

그리고, pyinstaller 는 사용자의 OS 환경에 맞게 실행파일을 만들어준다. linux 에서 배포를 했으면 조금은 달라졌을까?

왠만하면 언어 하나만을 쓰는걸로 생각하는게 정신건강에 좋을 듯 하다.

반응형

+ Recent posts