모바일 웹에서는 디바이스에 어떤 앱들이 설치되어 있는지 알 수 없다. 하지만 특정 앱의 앱링크(URL Scheme)를 알고 있다면(앱에서 정의가 되어있다면) 마치 앱의 설치를 알고 있는 것처럼 동작하도록 만들 수 있고, 원하는 정보들을 전달할 수 있다. 미리 정의된 앱링크를 호출하여 반응하는 앱이 있으면 해당 앱이 실행되고, 반응하는 앱이 없으면 일정 시간이 지난 후에 앱스토어 링크를 호출한다.


  1. 앱링크를 호출할 iframe을 생성한다. (미리 마크업을 해놓아도 상관없다.) iframe을 이용하는 이유는 앱링크가 유효하지 않을 경우 어떤 화면이 보일지 예상할 수 없기 때문이다. css 또는 스크립트를 이용하여 화면에 보이지 않도록 한다. iframe에 올바르지 않은 화면이 뜨더라도 사용자에게 보이지 않는다.

    $("body").append("<iframe id='____sorilink____'></iframe>");
    $("#____sorilink____").hide();
    


  2. 앱링크가 없을 경우를 대비한 앱스토어 링크를 setTimeout과 함께 정의한다.

    var openAt = new Date,
        uagentLow = navigator.userAgent.toLocaleLowerCase();
            
    setTimeout( function() {
                 
        if (new Date - openAt < 4000) { // 페이지가 열릴 때의 시간과 클릭 시점의 시간을 비교
            if (uagentLow.search("android") > -1) { // 안드로이드
                $("#____sorilink____").attr("src","market://details?id=com.soribada.android&hl=ko"); // 안드로이드 마켓 앱링크. "http"가 아닐 경우 iframe에서 호출
            } else if (uagentLow.search("iphone") > -1) { // 아이폰
                location.replace("https://itunes.apple.com/kr/app/solibada-myujig-mujehan-eum/id346528006?mt=8"); // "http"의 경우 스크립트로 호출
            }
        }
     
    }, 1000); // 앱링크를 실행한 후 1초간 반응이 없으면 마켓으로 이동
    


  3. iframe에서 앱링크를 호출한다. 앱링크에 반응하는 앱이 있다면 앱이 실행된다(이때 웹 페이지의 스크립트는 종료된다). 만약 앱이 실행되지 않는다면 일정 시간 후 setTimeout 함수가 실행되고 스토어로 이동한다.

    if(uagentLow.search("android") > -1){ // 안드로이드 $("#____sorilink____").attr("src", 'soribada30://applink?param=value'); // 안드로이드 앱링크 실행 else if(uagentLow.search("iphone") > -1){ // 아이폰 $("#____sorilink____").attr("src", 'soribada30://applink?param=value'); // 아이폰 앱링크 실행 }

    • 모바일 크롬 25버전 이상에서는 iframe에 embeding하는 방식이 동작하지 않는다. 크롬 25버전 이상에서는 intent URI를 이용한다.

      if(uagentLow.search("chrome") > -1 && navigator.appVersion.match(/Chrome\/\d+.\d+/)[0].split("/")[1] > 25){
          document.location.href = "intent://applink?param=value#Intent;scheme=soribada30;package=com.soribada.android;end";
      }else{
          $("#____sorilink____").attr("src", 'soribada30://applink?param=value');
      }
      
    • 안드로이드 킷캣 OS에서는 웹뷰도 크롬으로 바뀌었다. (버전은 30이다.) 하지만 웹뷰에서는 intent URI가 동작하지 않아서 분기가 필요하다.

      // 네이버, 다음에 대해서만 분기 처리. 그 외의 앱에서는 intent URI가 실행되지만 인식하지 못한다.
      if (uagentLow.indexOf("naver") != -1 || uagentLow.indexOf("daum") != -1) { 
          $("#____sorilink____").attr("src", 'soribada30://applink?param=value');
      } else {
          document.location.href = "intent://applink?param=value#Intent;scheme=soribada30;package=com.soribada.android;end";
      }
      


  4. 코드 정리를 하면 아래와 같다.

    var openAt = new Date, uagentLow = navigator.userAgent.toLocaleLowerCase(), chrome25, kitkatWebview; $("body").append("<iframe id='____sorilink____'></iframe>"); $("#____sorilink____").hide(); setTimeout( function() { if (new Date - openAt < 4000) { if (uagentLow.search("android") > -1) { $("#____sorilink____").attr("src","market://details?id=com.soribada.android&hl=ko"); } else if (uagentLow.search("iphone") > -1) { location.replace("https://itunes.apple.com/kr/app/solibada-myujig-mujehan-eum/id346528006?mt=8"); } } }, 1000); if(uagentLow.search("android") > -1){ chrome25 = uagentLow.search("chrome") > -1 && navigator.appVersion.match(/Chrome\/\d+.\d+/)[0].split("/")[1] > 25; kitkatWebview = uagentLow.indexOf("naver") != -1 || uagentLow.indexOf("daum") != -1; if (chrome25 && !kitkatWebview){ document.location.href = "intent://applink?param=value#Intent;scheme=soribada30;package=com.soribada.android;end"; } else{ $("#____sorilink____").attr("src", 'soribada30://applink?param=value'); } } else if(uagentLow.search("iphone") > -1){ $("#____sorilink____").attr("src", 'soribada30://applink?param=value'); }


내용 추가 (2015-10-10)

ios 9부터 앱링크 실행 시 사용자에게 확인 confirm이 추가되었다.

위의 예시코드에서는 눈에 보이지 않는 iframe에서 앱링크를 실행시키고 있는데, 사용자에게 confirm이 노출되지 않고 사용자가 앱열기 버튼을 탭하지 못하기 때문에 앱이 실행되지 않는다. ios 9 이후 버전에서는 iframe의 src 속성을 이용하지 말고, "location.href"를 사용해야 사용자에게 confirm이 노출되고 앱을 실행시킬 수 있다. ("location.href"를 사용하면 앱이 설치되어있지 않은 사용자에게 에러메시지가 노출된 후 스토어로 이동한다. 참조 : http://developer.naver.com/wiki/pages/UrlScheme)


신고
Posted by pilot376

댓글을 달아 주세요

  1. 홍성재 2014.09.30 21:19 신고  댓글주소  수정/삭제  댓글쓰기

    저 soribada30://applink?param=value와
    intent://applink?param=value#Intent;scheme=soribada30;package=com.soribada.android;end라는 url은 어디서 얻으신건가요?

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2014.10.07 00:09 신고  댓글주소  수정/삭제

      "soribada30://applink?param=value"는 해당 앱에서 미리 정의된 앱링크 형식입니다. 예를 들어 soribada30://applink?songId=123의 형식으로 앱을 호출하면, 앱에서는 songId 파라미터에 대한 정의를 미리 해놓고 그것에 맞게 실행합니다.

      intent는 정의된 앱링크를 다른 형식으로 호출하는 방법입니다.
      "intent://applink?파라미터=값"#Intent;scheme=앱의 스키마;package=앱의 패키지명;end

      이 글에서는 미리 정의된 앱링크를 호출하는 방법만 다루고 있습니다.

  2. 홍성재 2014.10.08 19:41 신고  댓글주소  수정/삭제  댓글쓰기

    답변 감사드립니다 ㅎ현재 iframe을 사용해서 설치유무 판단하여 설치되어있으면 인텐트로 앱실행, 안되어있으면 플레이스토어로 리다이렉트해주고있는데요, 혹 크롬에서 설치유무 판단할 방법에 관해 알고계신부분 있으신가요?ㅎㅎ

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2014.10.08 21:55 신고  댓글주소  수정/삭제

      크롬도 원리는 같습니다만, 버전에 따라서 분기가 필요합니다.

      모바일 크롬 25버전 이상에서는 iframe 방식이 동작하지 않습니다. 그래서
      ---------- code ----------
      document.location.href = "intent://applink?param=value#Intent;scheme=스키마;package=패키지;end";
      ---------- code ----------
      와 같이 iframe 대신 "location.href"를 이용하여 페이지 이동을 해야합니다.

      포스트에서 3번 부분 참고하시면 됩니다~~

  3. 홍성재 2014.10.10 11:02 신고  댓글주소  수정/삭제  댓글쓰기

    우선적으로 크롬일 경우에만 location.href로 이동을 하고있는데요, 이 경우 자동으로 설치유무 판단해서 리다이렉트 되더라구요,
    제가 원하는건 설치가 되어있으면 alert("1");이고 안되어있으면 alert("2");를 띄우고싶은데 ㅎㅎ 어렵네요

    혹시 location.href와 document.location.href와 차이는 없겠죠?ㅋㅋ 답변 잘 달아주셔서 감사합니다. 한글날은 잘 쉬셨나 모르겠네요 ㅎ

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2014.10.10 14:37 신고  댓글주소  수정/삭제

      location.href와 document.location.href의 차이는 없습니다. ㅎㅎ

      location.href를 이용하면 현재 창을 해당 링크로 이동시키게 됩니다. (iframe이 현재 창에서는 변화가 없고 iframe 내부에서만 이동시키는 것과 차이가 있습니다.)

      그리고 intent 링크로 실행하면 앱의 유무는 안드로이드 시스템에서 판단하게 됩니다.
      http://developer.android.com/guide/components/intents-filters.html

      iframe 형식에서는 iframe 내부에 링크 에러가 나서 응답이 없으면 앱이 깔려있지 않다고 자바스크립트에서 판단을 할 수 있는데, intent 형식에서는 자바스크립트에서 앱의 유/무 판단이 어렵습니다. ㅜㅠ

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2014.10.10 15:09 신고  댓글주소  수정/삭제

      지금 테스트하다보니 안드로이드는 모두 intent로 통일하셔도 될 것 같아요. 하위 버전 (2.3)도 잘 작동하네요. (단 intent 사용 시 스크립트에서 앱의 유/무 판단은 어렵습니다. 그리고 아이폰은 위의 로직대로 해야합니다.)

      http://developer.naver.com/wiki/pages/UrlScheme에서 "4.2 안드로이드" 부분 참조하세요~~

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2014.10.10 15:54 신고  댓글주소  수정/삭제

      https://github.com/kakao/kakaolink-web 페이지에서 "kakao.link.js" 파일도 참조하시면 도움이 될 것 같아요~

  4. 홍성재 2014.10.14 09:07 신고  댓글주소  수정/삭제  댓글쓰기

    감사합니다^^ 참고할게요~

  5. 홍성재 2014.10.14 15:55 신고  댓글주소  수정/삭제  댓글쓰기

    한가지 더 여쭈어봅니다...
    ios에서 위 방식으로 진행했을 때 앱이 설치되지 않았을 경우 주소가 유효하지 않기 때문에 Safari가 해당 페이지를 표시할 수 없다고 나오는데 이게 나오는 폰도 있고 안나오는 폰도 잇네요ㅡ.ㅡ;;물론 둘다 앱스토어로 이동하긴합니다만.... 원인이 뭘까요?

  6. 홍성재 2014.10.15 16:38 신고  댓글주소  수정/삭제  댓글쓰기

    아뇨 iframe은 괜찮은데 location.href로 했을때 경고창이 뜨는 폰이 있고 안뜨는 폰이 있더라구요 ㅎㅎ 그래서 혹시 차이점을 아실까 하고 ㅎ

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2014.10.15 18:56 신고  댓글주소  수정/삭제

      네이버 문서 ("http://developer.naver.com/wiki/pages/UrlScheme")에서 5.1 아이폰 부분 보시면 "(앱 미설치 시, appstore로 이동 전에 잠시 오류 팝업이 보일 수 있습니다.)"라고 쓰여있는데, 어떤 상황에서 팝업이 뜨는 것인지는 잘 모르겠네요. ^^;;

      저는 iframe으로 작업해서 이 증상을 겪지 않았었는데, 조사를 해봐야겠네요. ㅎㅎ

  7. 홍성재 2014.10.28 11:48 신고  댓글주소  수정/삭제  댓글쓰기

    멘붕이 왔습니다....ㅋㅋ
    IOS 8.1로 업데이트 후 잘되던 앱실행이 안됩니다...ㅜ
    카톡웹뷰?에서는 정상작동되는데 사파리에서 진행이 안되네요....
    혹 IOS 업데이트의 문제일까요?

  8. 홍성재 2014.11.07 08:41 신고  댓글주소  수정/삭제  댓글쓰기

    url에 |가 들어가면 안되더라구요? 아직 확실하게 찾은건아니고 해결중입니다

  9. 이호석 2014.12.24 09:27 신고  댓글주소  수정/삭제  댓글쓰기

    안녕하세요. 궁금한점이 있어서 글을 올리게 되었습니다.
    안드로이드 크롬 브라우저 최신 버전의 버그 일 가능 성도 있는데요.
    바닥창에서 팝업을 호출하여 생성 -> 팝업창안에서 앱 체크 로직 intent & scheme 를 호출하게 되면 앱이 실행이되면서 팝업창을 종료 시켜 버리네요.
    결국에는 부모창만 남는 상황이 되버립니다. 왜그럴까요?

    • 홍성재 2014.12.31 11:54 신고  댓글주소  수정/삭제

      음 제가 알기로 모바일디바이스에서 크롬이 아니더라도 alert창 띄우고 화면전환이 이루어지면 종료되는것으로 알고있는데...
      도움이 되시길...( _ _ )

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2015.01.05 14:08 신고  댓글주소  수정/삭제

      연말 연초에 정신이 없어서 댓글을 이제야 확인했는데, 이미 답변이 달려있네요 ^^;;
      홍성재님께서 공유해주신 내용 확인 부탁드립니다. ^^

  10. 홍성재 2014.12.31 11:53 신고  댓글주소  수정/삭제  댓글쓰기

    오랜만에 댓글남기네요
    IOS8에서 location.href해줄 때 URL상에 | 가 있으면 정상작동을 안하는 부분 처리했는데요
    location.href = "appurl://랜딩URL";

    appurl://이후 랜딩URL을 encodeURIComponent로 인코딩해서 처리했더니 정상작동하네요~

  11. 김명찬 2015.03.04 13:40 신고  댓글주소  수정/삭제  댓글쓰기

    질문이 있습니다..
    다름이 아니라, iOS 사파리에서 특정 앱을 실행하는 것을 알려주신 방법대로 처리했습니다.
    그런데, 문제는 다시 사파리를 실행했을 경우, 앱을 호출하는 페이지가 다시로드 되면서,
    반복 작업이 일어납니다. 앱링크를 호출하는 웹페이지를 첫번째 호출했을 때 닫는 방법이 있나요?

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2015.04.17 15:32 신고  댓글주소  수정/삭제

      안녕하세요. 답이 너무 늦었네요 ^^;;
      self.close()를 이용한 방법이 있는데, 아래 링크 참조하세요.

      - http://taegon.kim/archives/853
      - http://ngio.co.kr/m/post/2792

      close() 메서드는 스크립트( open() 메서드 )로 열린 창만 닫을 수 있는데, 우회하는 꼼수를 볼 수 있어요. 제가 예전에 테스트했을 때 모든 브라우저에서 올바르게 작동하지 않았던 것으로 기억하는데, 테스트가 필요할 것 같아요.

      감사합니다.

  12. 홍성재 2015.06.23 18:01 신고  댓글주소  수정/삭제  댓글쓰기

    저도 김명찬님처럼 같은 증상이 있어서 해결하려고하는데... 혹 위에 언급하신 방법 말고 해결하신게 있으신가요? os 버전에 따라 위에처럼하면 정상적으로 안닫히는것도있어서....ㅠㅠ

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2015.07.06 11:00 신고  댓글주소  수정/삭제

      사파리가 페이지를 다시 로드하면 스크립트가 다시 실행되기 때문에 막을 방법이 없어 보입니다. ㅠㅠ 실제로 다른 서비스들을 보아도 같은 증상이 있고요.

      다만 UI적으로 어떤 버튼을 클릭했을 때에만( 예 : 앱에서 자세히 보기 ) 앱으로 이동한다든지 하면 그나마 사용자가 불편을 줄일 수는 있을 것 같습니다.

      제가 작업한 서비스에서는 별도 버튼을 만들지는 않았지만, 통 이미지에 (앱에서 스플래시 이미지 같은) 회사 로고 및 안내 문구를 넣어서 자동으로 앱이 실행된다고 알려주었습니다. 사파리에 흰 화면만 덩그러니 있다가 앱이 뜨는 것보다는 보기 좋았습니다. :D

  13. 홍성재 2015.07.08 09:40 신고  댓글주소  수정/삭제  댓글쓰기

    아...그런식으로 처리하셨군요~ ㅋ 좋은정보 감사합니다( _ _ )

    항상 배우면서가네요

  14. ㅇㅇ 2015.09.21 17:11 신고  댓글주소  수정/삭제  댓글쓰기

    ios9에서는 앱실행이 안되는거 같은데 다른분들은 어떤가요?

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2015.09.25 22:55 신고  댓글주소  수정/삭제

      테스트를 해봐야겠군요. 좋은 정보 감사합니다.

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2015.10.10 22:45 신고  댓글주소  수정/삭제

      ios 9부터 앱링크 실행 시 사용자에게 confirm을 띄워주고 확인받은 후에 앱을 실행시킵니다.

      위의 예시코드에서는 눈에 보이지 않는 iframe에서 앱링크를 실행시키고 있는데, 사용자에게 confirm이 노출되지 않고 사용자가 앱열기 버튼을 탭하지 못하기 때문에 앱이 실행되지 않습니다. ios 9 이후 버전에서는 "location.href"를 사용해야 사용자에게 confirm이 노출되고 앱을 실행시킬 수 있습니다.

      ios9 이전 버전에서도 "location.href"를 사용하여 앱을 실행시킬 수 있는데, 굳이 iframe을 사용한 이유는 appstore로 이동 전에 오류 팝업이 노출되는데 이를 숨기기 위함입니다.

  15. 유성동 2015.11.09 18:22 신고  댓글주소  수정/삭제  댓글쓰기

    안녕하세요.. 윗분들은 주로 ios관련해서 질문을 드렸네요
    저는 안드쪽인지라... 안드에서 막혀서 질문드립니다..

    안드에서 기본브라우저를 이용하여 네이버앱을 체크하여 호출하려 합니다..
    location.href를 사용하면 잘 호출은 됩니다.
    문제는 네이버앱이 없는 상태서 location.href를 사용하면 그냥 없는페이지로 넘어가버리더라구요.. 그럼 안되잔아요.. ㅡ,ㅡ
    그래서 iframe도 사용해보고 별짓을 다 하는데 제 능력이 부족한건지 도저히 해결을 못하고 있습니다..
    location.href를 사용해서 네이버앱을 호출하더라도...
    네이버앱이 설치되어 있지 않다면 무작동상태로 둬야 하는데 방법이 없을런지요..
    일주일째 헤매고 있습니다...

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2015.11.10 11:43 신고  댓글주소  수정/삭제

      안녕하세요.

      안드로이드에서 location.href에 앱링크를 실행하면 없는 페이지로 이동합니다. (이는 검색창에 앱링크를 바로 입력한 것과 같습니다) 그래서 iframe의 src 어트리뷰트에 앱링크를 적용하여 iframe 내부에서만 앱링크를 실행합니다. 이렇게 하면 앱이 설치되어 있지 않아도 iframe 내부에서만 오류화면이 뜨게 됩니다. 추가로 css를 이용하여 iframe을 숨겨놓으면 아예 사용자에게 노출되지 않습니다.

      만약 이 방법이 어렵다면 무조건 intent 링크를 실행시키는 방법도 있습니다. intent 링크를 실행하면 안드로이드 기기에서 앱 유무를 판단하여 실행해줍니다. http://developer.naver.com/wiki/pages/UrlScheme 링크에서 4.2 안드로이드 부분 참조해주세요. ~

  16. choi 2015.11.27 19:25 신고  댓글주소  수정/삭제  댓글쓰기

    안녕하세요
    ios9 에서 location.href 로 하던중 앱이 설치가 되어 있지 않으면
    경고창이 뜬 후에 앱스토어로 이동하라는 팝업이 뜨는데
    혹시 이문제를 해결하셨는지 궁금합니다.

    제가 한 방법은 a 태그에 href로 앱스토어 url주고,
    앱 실행 url 주고 있는데
    문제는 setTimeout 때문에 앱이 설치가 되어 있어도 앱스토어 url 이 href에 입력이 됩니다..

    답답하네요...하...

    • Favicon of http://pilot376.tistory.com BlogIcon pilot376 2015.12.09 11:49 신고  댓글주소  수정/삭제

      안녕하세요.

      location.href로 이동 시 앱이 설치되어있지 않을 때 뜨는 에러메시지는 아쉽지만 숨길 수가 없습니다. ㅠㅠ

      예전 버전에서는 iframe을 이용하여 에러메시지를 숨겼지만, ios9 이후에는 iframe을 사용하면 사용자 확인 컨펌창도 함께 숨겨버려서 앱이 설치되어 있어도 스토어로만 이동합니다. 따라서 iframe을 사용할 수 없고, 에러메시지 또한 숨길 수 없습니다.

      http://developer.naver.com/wiki/pages/UrlScheme 페이지에서 4.1 아이폰 부분을 보시면 "앱 미설치시, appstore로 이동 전에 잠시 오류 팝업이 보일 수 있습니다." 문구를 확인하실 수 있습니다. 실제로 네이버도 에러메시지를 숨기지 못하고 노출하고 있습니다. (네이버 지도, 네이버 뮤직 등)

  17. scjang 2016.03.28 20:22 신고  댓글주소  수정/삭제  댓글쓰기

    pilot376 짱짱맨