티스토리 뷰
Deep Link, Universal Link, App Link를 간단하게 훑어보자.
Deep link - 딥링크
모바일 애플리케이션을 자동으로 열어 앱 내의 특정화면으로 보낼 수 있는 링크
- 앱 연결의 소요 시간을 단축하고, UX를 개선할 수 있음
- URL 매개변수를 이용해 토큰/미리 채워진 양식 등의 데이터를 전달할 수 있음
Deep link를 선택하면
- iOS: 앱을 열 것인지 묻는 메시지가 표시되거나
- Android: 사용할 앱을 묻는 대화상자가 표시되거나
Deep link 주소의 구조는 일반적인 https 구조가 아닌 custom한 링크를 가짐
custom_scheme://host/path?param=x
- scheme 부분만 다를 뿐 나머지는 https에서 사용하는 주소처럼 동일하게 설정할 수 있음
Universal and App links
Universal link(iOS), App link(Android)는 일반적인 Deep link와 다름
- 웹과 앱을 다 서빙한다는 전제
- 앱이 설치되어있지 않다면 Depp link 주소로는 아무 것도 서빙할 수 없음.
- 오류 페이지 같은 페이지만 서빙할 수 있을 것.
Universal link(iOS), App link(Android)는 실제 모바일 웹 URL과 바인딩 됨
- 모바일 웹으로 접속할 때, 앱이 설치되어 있지 않으면 모바일 웹으로 컨텐츠가 서빙됨.
- 당연한 것 같지만, Deep link에서는 이게 불가능함. Deep link 용 스킴/주소가 필요했던 것.
- 바인딩 된다는 것은 앱/애플리케이션에 도메인이 할당된다는 것.
- iOS에서는 연관 도메인 권한을 추가하고, Android에서는 새로운 인텐트 필터를 추가하는 등 애플리케이션 코드에서 몇 가지 추가 설정을 수행해야 함.
앱 - 서버에서 전달하는 Link를 위한 파일
을 통해 연결됨.- 양방향 인증이 되어 조금 더 안전함.
그럼, 사용 예제가 Deep link와 무엇이 다른가?
- 사실 사용 예제는 Deep link와 같음. 사용자로 하여금 웹 페이지에서 앱으로 끌고 올 수 있다는 것.
- Web fallback이 지원된다는 것 (앱이 없으면 웹으로 간다)
- 즉, 앱이 설치되어있지 않아도 모바일 웹 주소로 같은 컨텐츠를 서빙할 수 있다.
- 위에서 말했듯 Deep link 주소로는 앱이 없다면 할 수 있는 것이 없다.
- 같은 주소로 웹 서비스, 앱 서비스 둘 다 지원할 수 있다는 것이 사용자로 하여금 더 좋은 UX를 제공할 수 있음.
어떻게 사용할 수 있을까?
- 앞서 이야기했듯 서버에서 Link를 위한 파일을 제공해야 함
- iOS:
apple-app-site-association
파일 (줄여서 AASA 파일이라고도 함) - Android:
assetlinks.json
파일
- iOS:
- 그리고 해당 파일들은 아래의 주소로 제공되어야 함
- iOS:
https://my-app.com/.well-known/apple-app-site-association
- Android:
https://my-app.com/.well-known/assetlinks.json
- iOS:
- 주의할 점
Content-Type
이application/json
으로 전달되어야 한다.- AASA 파일은 확장자가 없다.
apple-app-site-association.json
으로 표기하지 않도록 주의.
- 위 파일들은 암호화 되어 있지 않다. 그렇기에 참조해보고 싶다면, 유명한 사이트들의 해당 경로로 접속해보자.
[iOS] apple-app-site-association (AASA) - 유니버셜 링크
특징
- AASA 파일에는 연결할 주소들을 다 명시해야 한다.
- 좀 있다 이야기 할 것이지만, iOS와 다르게 Android는 내부 애플리케이션 코드에서 path를 명시한다.
- AASA 파일의 확장자는 존재하지 않지만, Json 형식으로 작성해야 한다.
예제 파일을 보자
{
"applinks": {
"details": [
{
"appIDs": [ "ABCDE12345.com.example.app", "ABCDE12345.com.example.app2" ],
"components": [
{
"#": "no_universal_links",
"exclude": true,
"comment": "Matches any URL whose fragment equals no_universal_links and instructs the system not to open it as a universal link"
},
{
"/": "/buy/*",
"#": "payment_method=SOME",
"comment": "Matches any URL whose path starts with /buy/"
},
{
"/": "/help/website/*",
"?": { "lang": "?*" },
"exclude": true,
"comment": "Matches any URL whose path starts with /help/website/ and instructs the system not to open it as a universal link"
},
{
"/": "/????/help/*",
"?": { "articleNumber": "????" },
"comment": "Matches any URL whose path starts with /help/ and which has a query item with name 'articleNumber' and a value of exactly 4 characters"
}
]
}
]
},
"webcredentials": {
"apps": [ "ABCDE12345.com.example.app" ]
},
"appclips": {
"apps": ["ABCED12345.com.example.MyApp.Clip"]
}
}
- Universal link에 대한 설정 값들은
applinks
key 아래에 위치한다. apps
는 왜 빈 배열일까? iOS 12 이하 지원을 위해서는 빈 배열로 제공해야 한다고 함.appID
,appIDs
는 앱 ID를 작성하면 된다. Apple 개발자 페이지에서 확인할 수 있음.components
부분에서 어떤 경로를 앱으로 연결할지 구성할 수 있음.- 오래된 버전에서는
paths
를 통해 인식했었는데, 이젠components
로 다양하게 설정이 가능해졌음.
- 오래된 버전에서는
components
내에서 path마다 패턴을 지원하고,/
,#
,comment
등 여러 옵션을 지원./
: URL path pattern (default:* (everything)
)?
: URL query parameter pattern (default:*
)#
: URL fragment pattern (default:*
)exclude
: stop pattern matching pattern (default:false
)comment
: information about URLs- 하위 필드에 대한 자세한 내용은 공식문서를 참조하자.
- 참고) WWDC에서도 나왔었다.
어떻게 동작할까?
- 애플리케이션이 설치되거나 업데이트 될 때, iOS는 서버에서 이 파일을 다운로드하고 유효성을 검사함
- iOS 14 / macOS BigSur부터는 이러한 파일을 캐시하는 Apple CDN을 도입해 CDN에 없는 경우에만 서버에서 다운로드 함
- 설정된 도메인에 요청하는 경우, OS 단에서 앱을 연결해주는 것으로 이해함
주의
- iOS Universal link의 경우, 구앱까지 함께 트리거 될 수 있다는 것에 주의하자.
- 예시로, 이번에 새롭게 AASA 파일에 특정 endpoint를 추가했다고 하자.
- 단순하게는 "이제 새로운 앱에서 이 endpoint에 맞게 뷰를 띄워주겠지" 라고 생각하기 쉬운데, 그것도 맞지만 "구앱에서도 동작한다"는 것을 주의해야 한다. 다시 말하면 구앱이 설치된 iOS 환경에서 추가한 endpoint를 웹에서 접근할 때 구앱이 켜진다는 것이다.
- 고로, 앱 개발자 단에서 Universal link를 적용 시에 만약 Universal link로 트리거 되었는데 매핑되어 있지 않은 endpoint라면 웹 뷰 또는 웹 브라우저로 띄워주도록 하는 방어코드를 추가하는 것이 좋을 것 같다.
[Android] assetlinks.json - 앱 링크
위에서 이야기했듯 Android assetlinks.json
은 Apple과 달리 연결 구성 설정들을 애플리케이션 코드에서 처리하게 된다.
- 그렇기에
assetlinks.json
에는 도메인에 해당되는 앱 정보만 들어가게 된다.
예제 파일을 보자
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.binux.test",
"sha256_cert_fingerprints":
["22:9D:F9:72:D3:14:99:50:D8:EE:B9:12:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:A3:4F:DE:15:F5"]
}
}]
package_name
는AndroidManifest
파일과 동일해야만 함.sha256_cert_fingerprints
는 앱 서명 인증서의 SHA256 지문을 의미한다.keytool
등을 이용해 fingerprint를 만들어적용해야 한다.- example -
my-key
는 알맞게 수정해 활용keytool -list -v -keystore my-key.keystore
- example -
다수의 앱과 연결하고 싶다면, 한 assertlinks.json
에 명시하면 된다.
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.puppies.app",
"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"]
}
},
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.monkeys.app",
"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"]
}
}]
Android 측에서 이를 이용하기 위한 용도로 intent-filter
를 사용해야 한다.
<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="https"
android:host="my_domain.app"
android:pathPrefix="/my_path"/>
</intent-filter>
<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="https"
android:host="my_domain.app"
android:pathPrefix="/my_second_path"/>
</intent-filter>
- Android 개발은 잘 모르기에 자세한 내용은 공식문서를 참고하자.
320x100
반응형
'Development' 카테고리의 다른 글
[책] Go언어로 배우는 웹 애플리케이션 개발 (0) | 2024.02.14 |
---|---|
🕵🏻 eBPF가 뭘까? (1) | 2024.01.28 |
우리 PostgreSQL은 언제부터 이뻤나? (0) | 2023.08.11 |
[실용주의 프로그래머] 동시성이란 (1) | 2023.04.23 |
git revert에 대해 (1) | 2023.04.16 |
댓글
반응형
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Istio
- java
- c++
- Spring boot
- Clean Architecture
- 로그
- k8s
- Kubernetes
- Log
- HTTP
- 클린 아키텍처
- WebFlux
- Algorithm
- 알고리즘
- 쿠버네티스
- Spring
- gradle
- tag
- 하루
- boj
- docker
- 일상
- container
- MySQL
- 백준
- 비동기
- python
- jasync
- hexagonal architecture
- Intellij
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함