앱 링크를 지원하려면 assetlinks.json라는 디지털 애셋 링크 JSON 파일을 만들어 웹사이트의 잘 알려진 위치에 게시해야 합니다. 이 파일은 도메인의 링크를 처리할 수 있는 앱을 공개적으로 선언하며, Android 기기는 서버에서 이 파일을 가져와 딥 링크를 확인합니다.
Android 15 이상의 동적 앱 링크의 경우 assetlinks.json 파일은 경로, 프래그먼트, 쿼리 매개변수의 패턴 일치자와 같은 동적 규칙 구성을 정의하는 위치이기도 합니다. Android 15(API 수준 35) 이상을 실행하고 Google 서비스가 설치된 Android 기기는 주기적으로 파일을 가져와 동적 구성을 앱 매니페스트의 정적 구성과 병합합니다.
이 가이드에서는 assetlinks.json 파일을 준비하고 웹사이트에 게시하는 방법을 설명합니다. 원하는 경우 Play 딥 링크 도구 또는 Android 스튜디오 앱 링크 어시스턴트에서 assetlinks.json 파일을 생성할 수 있습니다.
자세한 내용은 App Links 개발자 도구를 참고하세요.
웹사이트 연결 선언하기
웹사이트에 디지털 애셋 링크 JSON 파일을 게시하여 웹사이트와 연결된 Android 앱을 표시하고 앱의 URL 인텐트를 확인해야 합니다. JSON 파일은 다음 필드를 사용하여 연결된 앱을 식별합니다.
package_name: 앱의build.gradle파일에 선언된 애플리케이션 ID입니다.sha256_cert_fingerprints: 앱 서명 인증서의 SHA256 지문입니다. 다음 명령어를 사용하여 Java keytool로 디지털 지문을 생성할 수 있습니다.
keytool -list -v -keystore my-release-key.keystore
- 이 필드는 여러 지문을 지원하며, 이는 디버그 및 프로덕션 빌드와 같은 다양한 버전의 앱을 지원하는 데 사용할 수 있습니다. 앱에 Play 앱 서명을 사용 중인 경우
keytool를 로컬에서 실행하여 생성된 인증서 지문은 일반적으로 사용자 기기의 인증서 지문과 일치하지 않습니다. Play Console 개발자 계정의Release > Setup > App signing에서 앱에 Play 앱 서명을 사용하고 있는지 확인할 수 있습니다. 사용 중인 경우 동일한 페이지에서 앱에 적합한 디지털 애셋 링크 JSON 스니펫도 확인할 수 있습니다.
다음 assetlinks.json 파일 예시에서는 com.example Android 앱에 링크 열기 권한을 부여합니다.
[{
"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"]
}
}]
웹사이트를 여러 앱과 연결하기
웹사이트는 동일한 assetlinks.json 파일 내에서 여러 앱과의 연결을 선언할 수 있습니다. 다음 파일 목록은 두 앱과의 연결을 별도로 선언하고 https://www.example.com/.well-known/assetlinks.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"]
}
}]
서로 다른 앱이 같은 웹 호스트에서 다른 리소스 링크를 처리할 수 있습니다.
예를 들어 app1은 https://example.com/articles의 인텐트 필터를 선언하고 app2는 https://example.com/videos의 인텐트 필터를 선언할 수 있습니다.
여러 웹사이트를 단일 앱에 연결
여러 웹사이트가 각 assetlinks.json 파일에서 동일한 앱과의 연결을 선언할 수 있습니다. 다음 파일 목록은 example.com 및 example.net과 app1의 연결을 선언하는 방법의 예를 보여줍니다. 첫 번째 목록은 example.com과 app1의 연결을 보여줍니다.
https://www.example.com/.well-known/assetlinks.json
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.mycompany.app1",
"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"]
}
}]
다음 목록은 example.net과 app1의 연결을 보여줍니다. 이러한 파일이 호스팅되는 위치만 다릅니다 (.com 및 .net).
https://www.example.net/.well-known/assetlinks.json
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.mycompany.app1",
"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 15 이상의 동적 앱 링크를 사용하면 앱 매니페스트에 정적으로 정의한 규칙과 함께 작동하는 서버 측 딥 링크 일치 규칙을 사용할 수 있습니다. assetlinks.json 파일에서 동적 규칙을 정의합니다. 이 항목은 선택사항입니다.
Android 15 (API 수준 35) 이상을 실행하고 Google 서비스가 설치된 Android 기기는 주기적으로 서버에서 이 파일을 가져와 동적 규칙 구성을 앱 매니페스트의 정적 구성과 병합합니다. 다음은 동적 규칙이 있는 assetlinks.json 파일의 예시입니다.
[
{
"relation": [
"delegate_permission/common.handle_all_urls"
],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints": [...]
},
"relation_extensions": {
"delegate_permission/common.handle_all_urls": {
"dynamic_app_link_components": [
{"?": {"dl": "*"}},
{"#": "app"},
{"/": "/products/*"},
{"/": "/shoes", "?": {"in_app": "true"}},
{"/": "*", "exclude": true}
]
}
}
}
]
코드에 관한 핵심 사항
- 동적 앱 링크는 동적 규칙을 구성하는
dynamic_app_link_components라는 새로운 디지털 애셋 링크 관계 확장 프로그램을 추가합니다. - 동적 규칙에는 경로, 프래그먼트, 쿼리 매개변수의 패턴 일치자가 포함될 수 있습니다.
- 패턴 일치자를 제외됨으로 표시하여 일치하는 URL이 앱을 열지 않도록 할 수도 있습니다.
- 이 예시에서는 경로 (
"/"), 프래그먼트 ("#"), 쿼리 매개변수 ("?")의 일치자와 제외된 일치자 ("exclude")의 예시를 보여줍니다. - 파일의 필드 중 형식이 잘못되었거나 비어 있는 필드가 있으면 Android는 동적 규칙을 삭제하고 기기는 앱의 매니페스트에 정적으로 정의된 규칙으로 대체됩니다.
동적 규칙은 앱의 매니페스트 파일에 선언하는 도메인 범위 내에서 적용되는 규칙만 지정할 수 있습니다. 동적 규칙 선언 섹션을 참고하세요.
동적 규칙 선언
동적 앱 링크는 규칙 객체 배열을 보유하는 새로운 dynamic_app_link_components 관계 확장 프로그램을 지원합니다. 각 규칙은 앱을 여는 경로, 프래그먼트, 쿼리 매개변수의 패턴 일치자를 사용하여 정의됩니다. 일치자는 앱을 열지 않도록 개별적으로 제외할 수도 있습니다. 이 모든 것은 선택사항입니다.
- 경로 일치
- 키: '/'
- 값: 단일 문자열, URL 경로의 일치 표현식
- 프래그먼트 일치
- 키: '#'
- 값: 단일 문자열, URL 프래그먼트의 일치 표현식
- 쿼리 매개변수 일치
- 키: '?'
- 값: URL 쿼리 매개변수의 키/값 쌍과 일치하는 딕셔너리입니다.
- 예를 들어 {"
?", {"dl": "*", "in_app":"true"} 사전은 쿼리 문자열 "?in_app=true&dl=abc"과 일치합니다. - 딕셔너리의 키-값 쌍 순서는 쿼리 문자열의 쌍 순서와 일치하지 않아도 됩니다. 또한 사전은 쿼리 문자열의 모든 키/값 쌍과 일치할 필요는 없지만 모든 사전 항목에 대해 일치하는 항목을 찾아야 합니다.
- 예를 들어 사전은 쿼리 문자열 '
?lang=en&in_app=true&tz=pst&dl=abc'과도 일치하지만 쿼리 문자열 '?lang=en&tz=pst&dl=abc'과는 일치하지 않습니다.
- 제외됨
- 키: 'exclude'
- 값:
dynamic_app_link_components에 정의된 각 규칙의 선택적 참/거짓 값입니다 (예시 참고).
패턴 일치 도구에서 다음 특수문자를 사용할 수 있습니다.
- '*'는 일치하는 문자열에서 패턴의 와일드 카드 뒤에 있는 문자가 발견될 때까지 0개 이상의 문자와 일치합니다.
- '?'는 단일 문자와 일치합니다.
- '?*'는 1개 이상의 문자와 일치합니다.
값에 대한 다른 문자 제한은 없습니다.
동적 규칙 순서
규칙이 선언되는 순서가 중요합니다. Android는 일치하는 항목을 찾을 때까지 각 규칙을 순서대로 평가합니다.
다음 예시에서는 순서가 처리에 미치는 영향을 보여줍니다. 첫 번째 규칙은 모든 경로 ('*')와 일치하지만 일치 항목을 제외하므로 (exclude: true) 모든 URL이 앱을 열지 못하도록 제외합니다. 이 경우 '/path1'을 허용하는 두 번째 규칙은 평가되지 않습니다.
dynamic_app_link_components: [
{"/": "*", "exclude": true},
{"/": "/path1"}
]
하지만 다음 예에서는 '/path1' 규칙이 먼저 선언되므로 먼저 평가되고 '/path1'과 일치하는 URL의 앱을 엽니다. 모든 URL이 앱을 열지 못하도록 제외하는 두 번째 규칙은 두 번째로 평가되지만 첫 번째 규칙이 일치하지 않는 경우에만 평가됩니다.
dynamic_app_link_components: [
{"/": "/path1"},
{"/": "*", "exclude": true}
]
선언된 구성요소 목록에서 일치하는 항목이 없으면 URL이 앱을 열지 않습니다. 다음 예에서는 '/path3'과 일치하는 경로가 없으므로 기기에서 이 경로를 제외된 것으로 처리합니다.
dynamic_app_link_components: [
{"/": "/path1"},
{"/": "/path2"}
]
이 동작은 dynamic_app_link_components가 특정 URL 부분만 제외하고 다른 모든 URL 부분은 허용하도록 하려는 경우에 중요합니다. 다음 예시에서 나머지 경로를 모두 허용하는 최종 규칙을 생략하면 모든 URL이 앱에서 제외됩니다.
dynamic_app_link_components: [
{"/": "/path1", "exclude": true},
{"/": "*"}
]
동적 규칙의 범위를 적절하게 지정하기
Android 15 이상에서 동적 앱 링크와 함께 사용할 서버 측 규칙을 정의할 때는 앱 매니페스트에 선언된 정적 인텐트 필터와 함께 작동하고 이를 보완하도록 적절하게 범위를 지정하는 것이 중요합니다.
assetlinks.json 파일에 선언된 동적 규칙은 앱의 AndroidManifest.xml 파일에 선언한 호스트의 규칙만 지정할 수 있습니다. 동적 규칙은 앱 매니페스트에서 정적으로 선언하는 URL 규칙의 범위를 확장할 수 없습니다.
따라서 동적 규칙과 정적 규칙에 이 접근 방식을 사용하는 것이 좋습니다.
- 앱 매니페스트에서 스키마와 도메인만 선언하는 등 가능한 한 가장 광범위한 범위로 규칙을 설정합니다.
- 경로 수준 라우팅과 같은 추가 미세 조정을 위해 서버 측 동적 규칙을 사용합니다.
이 이상적인 구성을 사용하면 필요에 따라 assetlinks.json 파일에 새 앱 링크 경로를 동적으로 추가할 수 있으며, 이러한 경로가 앱 매니페스트에 설정한 광범위한 범위에 적합하다는 것을 알 수 있습니다.
dynamic_app_link_components를 한 번만 선언
규칙을 올바르게 처리하려면 특정 사이트, 관계, 앱의 문에서 dynamic_app_link_components 객체를 하나만 선언하세요.
- 동일한 사이트, 관계, 앱에 대해 dynamic_app_link_components 객체를 선언하는 여러 문을 찾습니다.
- 단일 문에 선언된 여러 dynamic_app_link_components 객체를 찾습니다.
이러한 경우 Android는 어떤 동적 규칙 구성이 사용될지 보장하지 않습니다.
이전 앱 링크 구성과의 동적 규칙 호환성
이미 앱 링크를 지원하고 있다면 기존 assetlinks.json 파일에 동적 앱 링크 지원을 직접 추가할 수 있습니다. 앱 링크를 확인하는 관계 필드는 동일하게 유지되며 다른 변경사항 없이 동적 규칙에 대한 새 관계 확장 필드를 추가할 수 있습니다.
Android 14 (API 수준 34 이하)를 실행하는 Android 기기는 동적 규칙의 새 관계 확장 필드를 무시하는 반면, Android 15 이상을 실행하는 기기는 이러한 규칙을 매니페스트에 정의된 규칙과 병합합니다.
JSON 인증 파일 게시
다음 위치에서 JSON 인증 파일을 게시해야 합니다.
https://domain.name/.well-known/assetlinks.json
다음 사항을 확인하세요.
assetlinks.json파일은 콘텐츠 유형application/json로 제공됩니다.assetlinks.json파일은 앱의 인텐트 필터가 HTTPS를 데이터 스키마로 선언하는지 여부와 관계없이 HTTPS 연결을 통해 액세스할 수 있어야 합니다.assetlinks.json파일은 리디렉션 없이 액세스할 수 있어야 합니다 (301 또는 302 리디렉션 없음).- 앱 링크가 여러 호스트 도메인을 지원하는 경우 각 도메인에
assetlinks.json파일을 게시해야 합니다. 여러 호스트의 앱 연결 지원을 참고하세요. - 공개적으로 액세스할 수 없는 테스트 URL (예: VPN으로만 액세스할 수 있는 URL)을 매니페스트 파일에 포함하여 앱을 게시하지 마세요. 이러한 경우의 해결 방법은 개발 빌드에 다른 매니페스트 파일을 생성하도록 빌드 변형을 구성하는 것입니다.
다음 관련 가이드를 참고하세요.