딥링크와 유니버설 링크 — 앱으로 바로 진입시키기

딥링크는 URL을 통해 앱의 특정 화면으로 바로 진입하는 기능입니다. 공유 링크, 마케팅 캠페인, 푸시 알림 등에서 핵심적인 역할을 합니다.


딥링크 종류

종류예시특징
URI Schememyapp://product/42커스텀 스킴, 앱 미설치 시 에러
Universal Link (iOS)https://example.com/product/42HTTPS, 앱 미설치 시 웹으로
App Link (Android)https://example.com/product/42HTTPS, 앱 미설치 시 웹으로

면접 포인트: Universal Link/App Link가 URI Scheme보다 선호되는 이유는 앱이 설치되지 않았을 때도 웹 페이지로 대체(fallback) 되기 때문입니다.


GoRouter로 딥링크 처리

GoRouter는 딥링크를 자동으로 지원합니다.

DART
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)

XML
<!-- 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 (도메인 검증)

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)

XML
<!-- ios/Runner/Info.plist에 추가 -->
<key>FlutterDeepLinkingEnabled</key>
<true/>

Associated Domains

Xcode에서 RunnerSigning & Capabilities+ CapabilityAssociated Domains 추가:

PLAINTEXT
applinks:example.com

apple-app-site-association

JSON
// https://example.com/.well-known/apple-app-site-association
{
  "applinks": {
    "apps": [],
    "details": [{
      "appID": "TEAM_ID.com.example.app",
      "paths": [
        "/product/*",
        "/profile/*"
      ]
    }]
  }
}

딥링크 수신 처리

GoRouter (자동)

GoRouter를 사용하면 딥링크가 자동으로 라우트에 매칭됩니다. 추가 설정 없이 동작합니다.

수동 처리 (Navigator)

DART
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),
        ),
      );
    }
  }
}

딥링크 테스트

BASH
# 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로 딥링크를 테스트할 수 있습니다
댓글 로딩 중...