안드로이드에서의 딥링크(Deep links)와 앱링크(App links)

웹이 지금 처럼 널리 사용되고 강력한 힘을 갖게 된 이유는 링크 덕분이였다고 해도 과언이 아닐거라고 생각을 합니다. 웹에서 사용되는 HTML(Hypertext Markup Language) 문서는 링크를 통해 서로 연결이 되고 우리는 링크를 타고 정보의 세계를 여행합니다.

안드로이드에서도 앱 내의 컨텐츠에 유저가 쉽게 이동 할 수 있도록 링크를 지원합니다. 우리는 이 링크를 딥링크라고 부릅니다.

디지털 세상에서의 링크

URI(Uniform Resource Identifier)

디지털 세상에서는 웹상의 컨텐츠를 URI라는 포맷으로 표시합니다. 앞에서 설명한 링크 역시 URI 포맷으로 표현됩니다. 그럼 먼저 URI가 어떻게 생겼는지 살펴보도록 하겠습니다.

scheme://username:password@host:port/path?query_string#fragment_id

  • 스킴(scheme): 리소스에 접근하기 위한 프로토콜을 나타냅니다. 예를들어 웹 리소스의 경우 http(Hypertext Transfer Protocol), 또는 https(HTTP Secure)를 사용합니다.
  • 유저명 & 비밀번호(Username and Password): 선택 필드로, 인증이 필요한 경우 사용할 수 있습니다. 보안에 취약하기 때문에 사용이 권장되지는 않습니다.
  • 호스트(Host): 리소스가 존재하는 서버의 도메인 또는 IP 주소 입니다. 도메인은 IP 주소를 사람이 읽기 쉬운 형태로 사용할 수 있도록 해줍니다. www.example.com과 같은 형태의 도메인이 있다면 www는 서브도메인, example.com을 도메인이라고 부릅니다.
  • 포트(Port): 선택 필드로, 서버 내에서 어떤 컴포넌트가 요청을 처리할지를 표현합니다. 정의가 되어있지 않은 경우 브라우저는 스킴에 주어진 기본 포트를 사용합니다. 예를 들어 http의 경우 80, https의 경우 443이 기본 포트입니다.
  • 패스(Path): 서버에서의 구체적인 위치를 표현합니다. ex> /path/to/myfile.html
  • 쿼리 스트링(Query String): 서버에 데이터를 전달하기 위해 사용합니다. ?로 시작하며 키-값의 쌍을 표현합니다. 여러개의 쿼리 스트링은 &로 구분합니다. ex> ?key1=value1&key2=value2
  • 프래그먼트 아이디(Fragment ID): 리소스의 특정 파트를 나타내기 위해 사용되며 #로 시작합니다. 보통 웹페이지의 특정 섹션으로 바로 이동하기 위해 사용됩니다.

URI의 예

https://www.example.com:443/path/to/page?query=123#content

위의 URI의 경우 스킴은 https 프로토콜로 443 포트를 사용하며 서버의 위치는 www.example.com 도메인을 통해 접근합니다. /path/to/page는 접근하려는 자원이고, 키가 query 이고 123인 값을 쿼리 스트링으로 서버에 전달합니다. content는 해당 리소스에서 접근하고자 하는 부분입니다.

좀 더 이해를 돕기 위해서는 아래처럼 말할 수도 있겠네요. (조금 억지스런 예제일 수 있습니다. ^^;)

한국어://경기도용인시XX아파트:관리실/관리비?청구월=11월#전기료

프로토콜은 한국어입니다. 즉 한국어로 클라이언트와 서버가 소통합니다. 리소스를 받을 서버의 주소는 경기도 용인시 XX아파트이고 XX아파트의 관리실에서 요청을 처리합니다. 받고자 하는 리소스 즉 경로는 관리비입니다. 11월 관리비만 궁금하기 때문에 청구월 쿼리스트링으로 11월을 포함하여 관리비를 요청합니다. 그리고 관리비 고지서에서 전기료 파트에 바로 접근합니다.

안드로이드에서 사용할 수 있는 링크의 종류

안드로이드는 웹과 유사하게 링크를 통해 유저가 앱에서 제공하는 컨텐츠에 접근할 수 있도록 딥링크(Deep Link)라는 기능을 제공합니다. 접근하려는 컨텐츠가 웹이 아닌 안드로이드 앱 내부에 있지만 안드로이드에서 제공하는 인텐트(Intent)라는 도구를 이용해서 이를 처리 할 수 있습니다.

아래와 같이 AndroidManifest.xmlintent-filter를 선언하면 URI를 통해 앱의 컨텐츠를 노출 할 수 있습니다. 눈여겨 봐야할 부분은 data 속성인데요. geo라는 스킴을 정의하고 있습니다.

1
2
3
4
5
6
7
8
9
10
11
<activity
android:name=".MyMapActivity"
android:exported="true"
...>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="geo" />
</intent-filter>
</activity>

이렇게 하면 이제 geo라는 스킴을 갖는 URI가 안드로이드 단말의 브라우저에서 클릭이 되거나 다른 앱에서 트리거 되면 우리 앱의 MyMapActivity 가 이를 처리 할 수 있게 됩니다.

위의 인텐트 필터에서 카테고리는 아래와 같은 역할을 합니다.

  • <category android:name="android.intent.category.BROWSABLE" />
    웹 브라우저에서의 링크 클릭을 인텐트로 받을 수 있게 합니다.
  • <category android:name="android.intent.category.DEFAULT" />
    암시적 인텐트를 받을 수 있도록 합니다.

이제 안드로이드 폰에서 웹브라우저를 통해 geo:// 스킴으로 시작하는 링크를 클릭하면 내가 만든 앱의 MyMapActivity가 받아서 처리할 수 있게 되었습니다.

딥링크의 한계

지금까지의 설명만 보면 딥링크 자체는 별 문제가 없어보입니다. 하지만 잘 생각해보면 우리가 받아서 처리하겠다고 AndroidManifest.xml에 선언한 스킴은 우리가 정의한 스킴입니다. 즉 다른 앱에서도 얼마든지 동일한 스킴을 받아서 처리하겠다고 선언할 수 있습니다. 위에서 예를 든 geo라는 스킴을 받아서 처리하는 앱이 스마트폰에 여러 개가 설치되어 있을 수 있습니다. 그런 경우 안드로이드는 아래와 같은 다이얼로그를 띄우게 됩니다.

geo라는 스킴을 받아서 처리하겠다고 선언되어 있는 앱이 MapsChrome 두개가 있으니 둘 중 어디서 이 요청을 처리할지 사용자가 선택하라는 다이얼로그입니다. 하단에 보면 JUST ONCEALWAYS 버튼이 있어서 앞으로 동일한 스킴이 트리거 되었을 때 이번에 선택한 앱이 한번만 실행될지, 항상 실행될지를 결정할 수 있습니다.

유저 입장에선 선택권이 넓다고 할 수도 있지만 어떤 앱이 이걸 처리해야할지 헷갈릴수도 있고 맞는 앱을 선택 해야하는 것 자체가 어렵습니다. 그리고 앱 개발자 입장에서는 내가 만든 앱의 딥링크가 내 앱이 아닌 엉뚱한 앱에서 실행이 될 수도 있는 문제가 있습니다.

명확성 대화상자

딥링크 중복 문제 해결

안드로이드에서는 이러한 문제를 해결하기 위해 앱링크(App Links)라는 해결책을 제공합니다. 이에 대해 알아보기 전에 먼저 웹링크(Web Links)에 대해 알아보도록 하겠습니다.

웹링크는 스킴이 http 또는 https인 링크를 말합니다. 웹에서 웹브라우저를 통해 인터넷을 할 때 사용되는 프로토콜이 http 또는 https 이기 때문에 이를 웹링크라고 하는 것이죠.

그럼 안드로이드 앱에서 아까와 같이 처리할 딥링크를 정의할 때 이를 웹링크로, 즉, 스킴에 http 또는 https를 선언하면 어떻게 동작할까요? 이건 안드로이드 OS 버전에 따라 다른데 12 미만에서는 일반 딥링크와 동일하게 처리되고(웹링크를 처리하는 앱으로 연결, 하나 이상이면 다이얼로그로 처리할 앱 선택) 12 이상에서는 단말에 기본으로 설정된 웹브라우저 앱이 뜹니다. 참고로 웹브라우저 앱은 설정 -> 애플리케이션 웹링크를 스킴으로 설정한 앱들 중에 선택이 가능합니다.

아래는 웹링크의 인텐트 필터 샘플입니다. scheme가 http로 선언된걸 볼 수 있습니다.

1
2
3
4
5
6
7
8
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="http" />
<data android:host="myownpersonaldomain.com" />
</intent-filter>

앱링크

앱링크는 안드로이드 6.0(API Level 23)에서 부터 사용이 가능한 기능입니다. 앱링크는 autoVerify라는 속성을 제공하는데 이 속성은 웹링크를 사용하더라도, 해당 도메인의 소유주가 확인이 되면 웹링크를 사용하는 다른 앱들이 있거나, 기본 브라우저 앱으로 등록이 되어 있지 않더라도 즉시 내가 만든 앱이 링크를 받을 수 있도록 해줍니다.

참고로 iOS에서는 앱링크와 유사한 개념으로 유니버셜 링크(Universal Link)를 제공합니다.

아래는 앱링크를 사용하는 인텐트 필터 샘플입니다. 웹링크와 다른점은 autoVerify속성이 추가되었고 이 값이 true로 세팅되었다는 점입니다.

1
2
3
4
5
6
7
8
9
10
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="http" />
<data android:scheme="https" />

<data android:host="myownpersonaldomain.com" />
</intent-filter>

그럼 이렇게 인텐트 필터만 설정하면 앱링크가 동작할까요? 이것만으로는 부족합니다. 해당 도메인의 소유권이 나에게 있음을 확인할 수 있도록 ‘도메인 소유권 확인’ 처리를 해주어야합니다. 도메인 소유권 확인 절차가 없다면 아무나 동일한 링크를 선언할 수 있으니 딥링크와 다를게 없겠죠.

도메인 소유권 확인

도메인 소유권 확인은 디지털 애셋 링크 JSON 파일을 이용합니다. 특정한 포맷으로 구성된 JSON 파일을 아래의 위치에 업로드 하면 되는 방식입니다.

https://{{domain.name}}/.well-known/assetlinks.json

내가 소유한 도메인에는 나만 파일을 올릴 수 있으니 이를 통해 소유권 확인이 되는 것이죠. 그럼 위에서 언급한 디지털 애셋 링크 JSON(assetlinks.json)은 어떻게 생겼을까요?

디지털 애셋 링크

디지털 애셋 링크의 생성은 아래 링크에서 어떻게 만들 수 있는지, 어떤 속성들이 있고 어떤 역할을 하는지에 대해 자세히 설명이 되어 있습니다.

https://developer.android.com/studio/write/app-link-indexing

안드로이드 스튜디오의 Digital Asset Links File Generator를 이용하면 보다 편리하게 생성이 가능합니다.

Digital Asset Links File Generator

기본적인 형태는 아래와 같습니다.

앱의 기본 정보와 사이닝 키의 해시 값이 들어갑니다. 업로드한 디지털 애셋 링크 파일에 있는 정보와 앱의 정보가 맞지 않으면 앱링크가 동작하지 않으니 주의깊게 디지털 애셋 링크 파일을 작성하고 테스트를 해야합니다.

1
2
3
4
5
6
7
8
9
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example",
"sha256_cert_fingerprints":
["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
}
}]

딥링크 vs 웹링크 vs 앱링크

지금까지 살펴본 딥링크와 웹링크, 그리고 앱링크의 관계는 아래와 같습니다. 딥링크는 앱에서 자유롭게 스킴을 포함한 URI를 정의 할 수 있기 때문에 자유도가 가장 높습니다. 하지만 딥링크가 충돌할 수 있는 위험이 있습니다.

웹링크는 스킴이 http 이거나 https인 링크를 말합니다. 즉 웹에서 사용되는 링크입니다.

안드로이드에서도 딥링크를 정의할 때 스킴을 httphttps로 정의함으로써 웹링크의 형태로 정의가 가능합니다. 하지만 이렇게 하면 딥링크가 제대로 동작하지 않습니다. 해당 웹링크가 얼마든지 중복이 될 수 있으니 결국 이것만으로는 딥링크와 다를게 없기 때문입니다.

이를 해결하기 위해 웹링크에 도메인 소유권 확인 절차를 추가한게 앱링크 입니다. 앱링크는 사용하고자 하는 도메인에 디지털 애셋 링크 JSON 파일을 업로드 함으로써 해당 도메인이 나의 소유임을 안드로이드 OS에서 알 수 있게 합니다. 그리고 이를 통해 다른 앱에서 동일한 링크를 선언했더라도 내 앱이 해당 링크를 처리할 수 있도록 보장해줍니다.

링크의 종류

앱링크의 장단점

장점

  • 도메인 소유권이 확인된 웹링크를 사용하기 때문에 앱 선택 다이얼로그가 뜨지 않아 더 좋은 유저 경험을 제공하고, 다른 앱과 링크가 중복되더라도 내가 만든 앱에서 링크를 받는게 보장됩니다.
  • 안드로이드 인스턴트 앱 기능의 사용이 가능합니다. 인스턴트 앱은 앱의 설치 없이 앱의 일부 기능을 사용할 수 있도록 하는 기능입니다.
  • 유저가 모바일 브라우저나, 구글 검색으로 웹링크 클릭으로 바로 앱의 컨텐츠에 접근이 가능하기 때문에 더 많은 유저 유입이 가능해집니다.

앱링크의 단점

  • 도메인 소유권 확인 처리는 디지털 애셋 링크 생성 및 테스트, 파일 업로드의 과정을 걸치기 때문에 불편하고 추가로 시간과 노력이 필요합니다.
  • 사용하는 도메인의 관리가 중요합니다. 실수로 도메인 연장을 하지 못했다면 해당 앱링크는 사용이 불가능합니다.
  • 팀으로 작업 하는 경우 개발하는 머신마다 디버그 키가 다르기 때문에 디지털 애셋 링크 파일에 디버그 키의 해시 키 등록이 힘듭니다.

더 알아볼 것들

딥링크와 웹링크, 그리고 앱링크 까지 알았다면 안드로이드 앱에서의 링크에 대해 어느정도 알게된 것입니다. 하지만 실제 서비스를 개발할 때에는 마케팅이 필요하고 이를 위해 추가로 지연된 딥링크(Deferred Deep Links)와 파이어베이스(Firebase)에서 제공하는 지연된 딥링크 서비스인 다이나믹 링크(Dynamic Links)에 대해 알아두면 많은 도움이 됩니다.

지연된 딥링크

지연된 딥링크는 주로 마케팅에 많이 쓰이는데 마케팅을 통해 제공된 링크를 통해 앱의 설치를 유도하고 이에 대한 성과 측정을 위해 사용됩니다. UTM 코드라는 것과 함께 사용되며 여기에는 앱 설치를 위해 사용된 링크가 어디서 만들어졌는지, 어떤 캠페인에서 사용되었는지, 어떤 매체를 통해 공유되었는지 등의 정보가 들어갑니다. 즉 앱이 설치 되어 있지 않을때 앱의 설치를 유도 할 수 있고 설치 후 지연된 딥링크에 전달된 파라미터를 전달 받을 수 있습니다.

파이어베이스의 다이나믹 링크

파이어베이스의 다이나믹 링크는 파이어베이스에서 제공하는 지연된 딥링크 서비스입니다. 하나의 링크로 링크가 실행된 플랫폼에 따라 서로 다른 동작을 할 수 있도록 편리하게 구성할 수 있습니다. 또한 해당 링크를 받아서 처리할 수 있는 앱이 있는지 없는지에 따라 다른 동작을 정의할수도 있습니다.

예를 들어, 하나의 링크로 안드로이드에서 링크가 클릭되었다면 해당 링크를 실행할 수 있는 앱을 찾고 없다면 앱을 설치할 수 있도록 안드로이드 마켓으로, 있다면 앱으로 링크를 전달할 수 있습니다. 또한 대시보드를 통해 링크의 성과를 바로 볼 수도 있습니다.

단축 URL 기능도 제공을 하는데 이는 긴 URL을 짧은 URL로 바꿔주는 기능입니다.

즉 파이어베이스의 다이나믹 링크는 지연된 딥링크에 여러가지 추가 기능을 제공하는 솔루션 이라고 보면 됩니다. 그리고 이 솔루션의 핵심은 사실상 다이나믹 링크의 성과를 볼 수 있는 대시보드 일 것입니다. 즉 마케팅의 성과를 볼 수 있는 기능입니다.

Firebase Consoe

Dynamic Links with Analytics

결국 지연된 딥링크와 파이어베이스의 다이나믹 링크의 핵심은 마케팅을 위한 추가 기능이라고 보면 됩니다. 당연히 이런 서비스는 파이어베이스에서만 제공하는 것은 아니고, AppsFlyerBranch 같은 다른 마케팅 솔루션 서비스에서도 제공합니다.

맺음말

안드로이드 앱 개발을 하다보면 딥링크는 반드시 사용해야 하는 기능입니다. 앱의 초기 세팅이나 기초에 해당하는 부분에 딥링크 처리가 반드시 들어갑니다. 개발자는 웹과의 연동이나, 마케팅을 위해 적절한 링크 기능을 제공해야합니다. 그리고 요구사항에 맞는 선택을 하기 위해서는 각각의 개념과 장단점을 잘 알아야합니다. 이런 개념을 전달하는 것이 이번 글의 목적입니다.

딥립크가 한계를 가지고 있지만 앱링크를 사용하지 않더라도 스킴을 잘 겹치지 않을만한 걸로 사용한다거나 하면 실제로는 앱링크를 사용하지 않는게 더 좋은 선택일 수도 있습니다. 앱링크는 도메인 소유권 확이이나, 관리, 디버그 모드에서의 불편함 등을 감안하면 공짜가 아닙니다. 물론 이것은 서비스와, 팀의 상황에 따라 달라지며 팀의 상황에 맞게 맞는 선택을 하기 위해서는 각각의 차이가 무엇인지, 어떤 문제점을 해결하기 위해 등장했는지, 장단점이 무엇인지를 잘 알아야합니다.

마지막으로 서비스를 잘 만드는 것 만큼이나 중요한 것이 마케팅입니다. 모바일 앱의 생태계가 이미 굉장히 성숙해져 있기 때문에 이제는 유저가 스스로 원하는 앱을 찾기보다는 이미 알고 있는 서비스만 사용하는 것이 트렌드입니다. 즉 신규 서비스의 경우 이제는 아무리 잘 만들어도 유저에게 노출 시키기가 굉장히 힘이듭니다.

따라서 운영중인 앱에 대한 마케팅을 준비하고 있다면 적절한 마케팅 서비스를 선택하고 이를 활용할 수 있도록 지연된 딥링크와 이를 제공하는 서비스에 대해 잘 알고 있는것이 중요합니다.

참고 자료

안드로이드에서의 딥링크(Deep links)와 앱링크(App links)

https://jeongmin.github.io/2023/11/25/android/android-applinks/

Author

이정민

Posted on

2023-11-25

Updated on

2023-11-28

Licensed under

댓글