앱개발에서 필요한 유니버셜 링크가 아니라 웹 개발자 입장에서 본 유니버셜 링크를 정리했다.
유니버셜 링크란?
iOS9 사용자들이 웹사이트(사파리)의 링크를 클릭했을 때 사파리가 아닌 앱으로(유니버셜 링크를 지원할 때) 매끄럽게 이동하는 기능을 제공해준다. 유니버셜 스킴을 사용하는 경우 얻을 수 있는 장점은 다음과 같다.
- 커스텀 스킴하는 경우 스킴을 호출할 때 내가 만든 앱이 호출되는 것을 보장해주지 않는다. 만약, 먼저 설치된 앱이 해당 스킴에 대해서 자신이 처리할 수 있다고 iOS에게 응답하면 해당 앱이 실행되게 된다. 그러나, 유니버셜 링크는 앱과 관련된 사이트의 웹주소를 사용하기 때문에 관련 없는 앱이 실행되지 않는다.
- iOS에서 앱이 설치될 때, 관련된 사이트에 올라간 apple-app-site-association(사이트의 URL을 열 때 어떤 앱을 열지를 정의한) 파일을 체크해준다.
- 커스텀 스킴을 실행하는 경우 앱이 없을 때 아무런 동작을 할 수 없지만 (보통은 타이머로 체크해서 스토어로 이동) 유니버셜 링크에서는 해당 컨텐츠를 웹에서 항상 볼 수 있기 때문에 유연성을 제공해준다.
- 마찬가지로 다른 앱에서 사용자의 앱을 호출하는 경우에도 앱 설치 여부에 대해서 고민할 필요가 없게 된다. (없는 경우 대체 웹이 뜨니까)
사실, 위에 적어논 장점은 큰 장점이라 할 수 없어서 9.0.2 전까지는 유니버셜 링크에 대해서 신경도 안썼는데 9.0.2 업그레이드 이후부터 다음의 문제가 생겼다. (장점이라기 보다는 웹 개발은 대체재의 성격을 띄게 되다보니 앱으로 옮겨야 하나 생각이 들게했…)
‘유효하지 않은 링크’ 이슈
iOS 9.0.2로 버전이 업데이트 되면서 해당 버전의 사파리에서 커스텀 스킴을 실행하는 경우 해당 링크가 유효하지 않다는 팝업창이 뜨면서 스킴을 실행할 수 없는 이슈가 발생하였다. 앱이 설치되어 있는 경우라도 Open이 아닌 Cancel을 한 번이라도 누르고 나면 유효하지 않다는 팝업창이 뜨게 된다.
(이러한 이유로 유니버셜 링크를 강제 적용하게 되면서 관련 글을 정리하게 되었다… )
유니버셜 링크의 동작
유니버셜 링크의 동작은 크게 두 개로 나눌 수 있다. 하나는 외부 사이트 또는 앱에서 진입하는 경우이고 또 다른 하나는 내부 사이트에서 웹을 실행하는 경우이다.
외부에서 진입하는 경우 실행하는 유니버셜 링크의 apple-app-site-association 파일을 보고 해당 링크와 연결되어 있는 앱의 ID를 확인해본 후, 앱이 설치되어 있다면 앱을 띄우게 된다. 없다면 웹 사이트를 띄우면서 앱 설치 배너를 보여주게 된다.
배너의 디자인 변경 지점은 제한되어 있고 노출여부를 결정할 수 없었는데 9.2.1 버전에서 유튜브에서 앱배너가 노출이 안되고 있어서 당황…
내부 사이트에서 앱을 띄우는 경우는 조금 복잡해진다. (정확하게는 iOS가 아닌 서비스에서 앱을 띄울 지, 웹을 띄울 지를 결정하고 싶거나 apple-app-site-association의 경로 정책이 애매한 경우 등등… 나의 경우에는 해당 웹페이지가 외부 앱의 인앱 브라우저에서 보여져야 했다.) 고민하다 N사 B서비스에서 괜찮은 방법을 찾았는데, 여기에서는 ul (universal link)이라는 도메인을 새로 추가한 후, 해당하는 도메인에 apple-app-site-association 파일을 올려서 실행할 앱을 지정하였다. 앱에서 보기버튼을 누르게 되면 ul.some.com/blah~ 도메인이 호출되면서 앱이 있는지를 확인하고 앱이 있는 경우에는 앱을 실행, 없는 경우에는 302 리다이렉션 응답에 앱 설치 주소를 내려주는 방법을 사용하여서 해결하였다. (오~~ 굳!)
주의할 점
apple-app-site-association 파일을 변경하더라도 앱이 실행되지 않는 경우가 발생해서 기능이 동작하지 않는 것으로 생각한 경우가 많았었는데 이 경우는 관련 앱을 삭제하면 된다. 앱 설치할 때 해당 파일을 캐시하는 것으로 추측된다. (이 망할놈들은 기술 문서에 iOS 내부 동작에 대한 자세한 설명이 없다.)
이상, 개삽질 공유.. 끝.
끝없는 삽질이 추가되었다.

- 유니버셜 링크 실행 시, xhr 호출이 포함되어 있는 경우 스킴 실행하는 경우처럼 팝업이 떴다.
유니버셜 링크를 a태그의 href에 적용하거나 location.href 값을 바로 실행하는 경우에는 이슈가 없었으나 서버로부터 동적으로 받아와서 유니버셜 링크를 실행하는 경우에 발생. - setTimeout()으로 실행하는 경우에는 동작하는 것으로 봐서는 비동기 상황인 경우보다는 실행 컨텍스트에서만 동작할 수 있는 (팝업 띄우기 같은) 이슈로 생각된다. 그러나, setTimeout()으로 실행하는 경우도 최초 1회는 성공하였으나 폴링방식으로 띄웠던 2회부터는 동작하지 않는 이슈가 있었다.
- setInterval()의 경우 정상적으로 동작하였으나 두 번째 실행할 때부터는 오동작 할 때와 동일한 이슈가 생겼다.
- 페이지 새로 고침하는 경우 또는 location이 변경되었을 때는 정상 동작하는 것으로 보고 location을 초기화 또는 리셑하는 방법을 찾아보았고 http://stackoverflow.com/questions/32689483/ios9-try-to-open-app-via-scheme-if-possible-or-redirect-to-app-store-otherwise 글의 https://bartt.me/openapp 에서 loaction.href.reload()를 초기화하는 것을 보고 시도한 결과 앱띄우는데 성공하였다…
과연 다음 버전 업데이트 할 때까지 이 꼼수가 먹힐런지는…
추가 삽질
특정 url로 페이지 진입시 location.href를 변경해서 유니버셜 링크로 포워딩 시켰는데 스토어로만 이동하는 문제가 있었다. 이 경우에 대해서는 기존 스킴 방식으로 띄우도록 수정;;;
삽질 끝에 질문 하나 드리려고 합니다.. 배포전에 유니버셜 링크를 통한 앱 설치를 테스트 중인데요.. 링크를 통해 앱이 실행이 되질 않아서요.. 혹시 앱 설치시에 캐시하는 것으로 예상하셨는데요… 그게 스토어를 통한 앱설치를 말씀하시는 건가요??
@ds.choi
안녕하세요. 저도 오래 전에 했던 일이라서 정확하게 기억이 나지는 않는데요.
앱과 관련된 앱스킴정보가 저장된 apple-app-site-association 파일이 캐시되는 것으로 생각했구요.
스토어를 통한 앱설치라면 이 부분은 설치하려는 앱이 아닌 앱스토어를 실행하는 앱스킴이라서 apple-app-site-association 와는 상관이 없을 것 같아요. 앱스토어 실행하는 앱스킴은 itunes의 링크를 찾아보시면 될 것 같습니다.