딥링크와 유니버설 링크 — 앱으로 바로 진입시키기
딥링크와 유니버설 링크 — 앱으로 바로 진입시키기
딥링크는 URL을 통해 앱의 특정 화면으로 바로 진입하는 기능입니다. 공유 링크, 마케팅 캠페인, 푸시 알림 등에서 핵심적인 역할을 합니다.
딥링크 종류
| 종류 | 예시 | 특징 |
|---|---|---|
| URI Scheme | myapp://product/42 | 커스텀 스킴, 앱 미설치 시 에러 |
| Universal Link (iOS) | https://example.com/product/42 | HTTPS, 앱 미설치 시 웹으로 |
| App Link (Android) | https://example.com/product/42 | HTTPS, 앱 미설치 시 웹으로 |
면접 포인트: Universal Link/App Link가 URI Scheme보다 선호되는 이유는 앱이 설치되지 않았을 때도 웹 페이지로 대체(fallback) 되기 때문입니다.
GoRouter로 딥링크 처리
GoRouter는 딥링크를 자동으로 지원합니다.
final router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
),
GoRoute(
path: '/product/:id',
builder: (context, state) {
final id = state.pathParameters['id']!;
return ProductDetailScreen(id: id);
},
),
GoRoute(
path: '/profile/:userId',
builder: (context, state) {
final userId = state.pathParameters['userId']!;
return ProfileScreen(userId: userId);
},
),
],
);
Android 설정 (App Links)
<!-- android/app/src/main/AndroidManifest.xml -->
<activity android:name=".MainActivity"
android:exported="true">
<!-- 기존 intent-filter 유지 -->
<!-- App Links -->
<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="example.com"
android:pathPrefix="/product" />
</intent-filter>
<!-- URI Scheme -->
<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="myapp" />
</intent-filter>
</activity>
assetlinks.json (도메인 검증)
// https://example.com/.well-known/assetlinks.json
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints": [
"AA:BB:CC:DD:..."
]
}
}]
iOS 설정 (Universal Links)
<!-- ios/Runner/Info.plist에 추가 -->
<key>FlutterDeepLinkingEnabled</key>
<true/>
Associated Domains
Xcode에서 Runner → Signing & Capabilities → + Capability → Associated Domains 추가:
applinks:example.com
apple-app-site-association
// https://example.com/.well-known/apple-app-site-association
{
"applinks": {
"apps": [],
"details": [{
"appID": "TEAM_ID.com.example.app",
"paths": [
"/product/*",
"/profile/*"
]
}]
}
}
딥링크 수신 처리
GoRouter (자동)
GoRouter를 사용하면 딥링크가 자동으로 라우트에 매칭됩니다. 추가 설정 없이 동작합니다.
수동 처리 (Navigator)
import 'package:app_links/app_links.dart';
class DeepLinkService {
late final AppLinks _appLinks;
Future<void> initialize() async {
_appLinks = AppLinks();
// 앱이 이미 실행 중일 때 링크 수신
_appLinks.uriLinkStream.listen((Uri uri) {
_handleDeepLink(uri);
});
// 앱이 종료된 상태에서 링크로 실행됐을 때
final initialUri = await _appLinks.getInitialLink();
if (initialUri != null) {
_handleDeepLink(initialUri);
}
}
void _handleDeepLink(Uri uri) {
final path = uri.path;
final params = uri.queryParameters;
if (path.startsWith('/product/')) {
final productId = path.split('/').last;
// 상품 상세 화면으로 이동
navigatorKey.currentState?.push(
MaterialPageRoute(
builder: (_) => ProductDetailScreen(id: productId),
),
);
}
}
}
딥링크 테스트
# Android 테스트
adb shell am start -a android.intent.action.VIEW \
-d "https://example.com/product/42" com.example.app
# iOS 테스트
xcrun simctl openurl booted "https://example.com/product/42"
# URI Scheme 테스트
adb shell am start -a android.intent.action.VIEW \
-d "myapp://product/42" com.example.app
Deferred Deep Links
앱이 설치되지 않은 상태에서 링크를 클릭 → 스토어에서 설치 → 설치 후 해당 화면으로 이동하는 패턴입니다. Firebase Dynamic Links 또는 Branch.io 같은 서비스를 사용합니다.
정리
- 딥링크는 URL로 앱의 특정 화면에 직접 진입하는 기능입니다
- Universal Link(iOS) / App Link(Android)는 HTTPS 기반으로 앱 미설치 시 웹으로 대체됩니다
- GoRouter를 사용하면 딥링크가 자동으로 라우트에 매칭됩니다
- 도메인 검증 파일(
assetlinks.json,apple-app-site-association)을 웹서버에 배치해야 합니다 adb shell이나xcrun simctl로 딥링크를 테스트할 수 있습니다
댓글 로딩 중...