[Flutter] Dynamic Links 를 활용하여 Deep Link 구현하기

Seong-Am Kim
15 min readMay 7, 2022

--

Photo by Aveedibya Dey on Unsplash

웹처럼 주소를 공유하여 특정 페이지로 이동하듯이 우리는 때론 앱에서도 공유시 특정 화면으로 바로 이동하기를 원할때가 있다. 이를 가능하게 하는 것이 Deep Link 인데 이번 시간에는 Firebase 에서 제공 하고 있는 Dynamic Links를 활용하여 Flutter에서 어떻게 이 목적을 달성할 수 있을지 살펴 보려고 한다.

해당 글은 아래의 순서로 진행된다.

  1. Deep Link 와 Dynamic Links 의 개념 및 차이점
  2. Dynamic Links를 이용하기 위한 사전 준비
  3. Android에서의 Dynamic Links의 설정
  4. iOS에서의 Dynamic Links의 설정
  5. Flutter에서 Dynamic Links 가져와 공유 하기
  6. 수신된 Dynamic Links를 통하여 특정 컨텐츠 화면으로 이동하기

해당 글은 다음 패키지를 의존하고 있다.

firebase_core: ^2.27.0
firebase_dynamic_links: ^5.4.17
uni_links: ^0.5.1
share_plus: ^3.0.4

1. Deep Link 와 Dynamic Links 의 개념 및 차이점

Deep Link

우선 Deep Link가 무엇인지에 대해 알아보자.

Deep Link는 앱에서만 쓰이는 단어가 아니며 웹도 함께 포함한다. 하지만 일반적으로 앱에서 Deep Link란 용어를 많이 사용하며, 해당 용어는 일반적으로 검색 가능하거나 특정 웹 컨텐츠로 연결된 하이퍼링크를 사용하는 것이다.

즉, 특정 컨텐츠로 연결된 하이퍼링크 의미한다.

하이퍼링크 예) http://example.com/path/page

Dynamic Links

Dynamic Links는 Firebase에서 제공되는 서비스로 이것이 Deep Link를 의미하진 않는다. 어디까지나 Deep Link를 포함하는 개념으로 보다 포괄적인 상황을 다루고 있다.

앱의 경우 웹과는 다르게 설치가 되어야 특정 화면으로 이동이 가능하며 사용자 마다 디바이스의 환경(Android, iOS 등)이 다르기에 일반적인 웹과는 차이점이 분명 있다.

이를 극복하기 위해 같은 링크지만 상황에 따라 서로 다른 동작을 할 필요성이 있다. Dynamic Links를 이용하며 이를 매우 쉽게 해결할 수 있다.

Firebase에서 제공하는 아래 영상을 보면 어떤 개념인지 잘 이해할 수 있을 것이다.

Introducing Firebase Dynamic Links

아래 도표와 같이 한 링크로 다양한 상황에서 각자 다른 동작을 한다.

Dynamic Links 동작 과정 예시

그럼 본격적으로 이 Dynamic Links를 Flutter에선 어떻게 활용할 수 있는지 알아보도록 하자

2. Dynamic Links를 이용하기 위한 사전 준비

Firebase 프로젝트 생성

당연한 이야기겠지만 Dynamic Links는 Firebase의 서비스이기 때문에 프로젝트를 생성해야 된다.

만약 프로젝트가 없다면 아래 Firebase console URL로 이동하여 Firebase 프로젝트를 생성한다.

Dynamic Links에 도메인 등록

웹에서 프로젝트 생성 후 해당 프로젝트로 들어가면 왼쪽 네비게이션 메뉴에서 Engage 하위로 Dynamic Links를 확인해 볼 수 있다. 이를 클릭한다.

해당 서비스를 이용하기 위해선 도메인 등록이 필요한데 Get started 를 눌러 도메인 등록을 한다.

Dynamic Links 화면

여기서 참고로 할 부분은 반드시 도메인을 구매하여 입력할 필요는 없으며 선택사항이다. Firebase에선 https://your_subdomain.page.link 란 형식으로 도메인을 사용할 수 있도록 하고 있으며 your_subdomain을 본인이 원하는 변경하여 입력하면된다.

만약 도메인을 직접 구입하여 입력한다면 Firebase 에선 프리픽스를 사용해 동적링크를 사용하도록 권장하고 있다.

예) https://your_domain/share 또는 https://share.your_domain

이는 기존에 도메인을 쓰는 웹 URL과 충돌하지 않기 위함인데 자세한 부분은 아래 링크를 참고하기 바란다.

Flutter에서 Firebase 설정

Flutter에서 Firebase 와 관련된 서비스들을 이용하기 위해선 몇가지 설정이 필요한데 과거엔 매우 복잡했으나 발전을 거듭하여 CLI이용 하여 커멘드에 따라 실행 하면 완료되도록 이와 관련된 설정이 매우 편해졌다.

공식 문서에 이와 관련하여 상세하게 잘 설명되어 있으니 참고 바란다.

firebase_dynamic_links 설치

위에서 Firebase와 관련된 설정을 마쳤으면 아래 패키지를 설치하여 Dynamic links를 이용할 수 있게 준비해준다.

flutter pub add firebase_dynamic_links

3. Android에서의 Dynamic Links의 설정

해당 방법은 일반적이 Deep Link의 수신을 위해 설정하는 것과 동일하다.

수신을 위해 android/app/src/main/AndroidManifest.xml 파일에 인텐트 필터 등록을 해준다.

인텐트 필터는 activity 태그의 자식 태그로 포함되어야 하며 아래와 같이 추가해준다.

...
<activity android:name=".MainActivity" ...>
<!--For Dynamic links-->
<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:host="example.app"
android:scheme="https"/>
</intent-filter>
</activity>

여기서 example.app 부분을 앞서 Dynamic Links 에서 등록한 도메인을 적어주면 된다.

4. iOS에서의 Dynamic Links의 설정

우선 iOS에선 URL형태로 동작하는 Deep Links를 Universal Link라고 부르는데 이를 설정해준다.

Universal Link 등록

ios/Runner/Runner.entitlements 파일을 아래와 같이 수정해준다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:example.app</string>
</array>
</dict>
</plist>

여기서 example.app 부분을 앞서 Dynamic Links 에서 등록한 도메인을 적어주면 된다.

참고로 applinks: 부분은 반드시 들어가야 한다.

위의 방법이 불편하다면 또 다른 방법으로 XCode를 이용해서 등록할 수 있다. 위의 것과 같은 것이므로 만약 추가 했다면 필요없다. (둘중 택 1)

Signing & Capabilities 항목에서 Associated Domains를 추가한다. 이후 Domains에 appliks:example.app 를 적어준다.

커스텀 도메인 등록

앞서 무료 제공된 도메인이 아니라 커스텀된 도메인을 등록했다면 ios/Runner/Info.plist 파일에 아래와 같이 추가해줘야 한다.

...
<key>FirebaseDynamicLinksCustomDomains</key>
<array>
<string>https://example.app/share</string>
</array>
...

5. Flutter에서 Dynamic Links 가져와 공유 하기

Dynamic Links를 방법은 여러가지가 있다. Firebase에선 아래 4자기 방법으로 만들 수 있다고 소개하고 있다.

  1. Firebase 콘솔 사용: 소셜 미디어에서 공유할 프로모션 링크를 만드는 경우에 유용합니다. 이렇게 하면 Firebase Console에서 링크의 이름과 커스텀 서픽스를 선택할 수 있습니다. Firebase Console에서 또는 Analytics REST API를 통해 동적 링크의 실적을 추적할 수 있습니다.
  2. iOS AndroidFlutter의 Dynamic Link Builder API 사용. 링크가 여러 개 필요한 경우나 사용자 간의 공유를 위해 앱에서 동적으로 링크를 만드는 데 적합한 방법입니다. Dynamic Links Analytics API를 사용해 Builder API로 만든 동적 링크의 실적을 추적할 수 있습니다.
  3. REST API 사용: Builder API가 없는 플랫폼에서 동적으로 링크를 만드는 데 적합한 방법입니다. Console에서 만든 프로모션 캠페인의 실적을 추적하는 데 Analytics REST API를 사용할 수 있습니다.
  4. 직접 만들기: 클릭 데이터를 추적할 필요가 없고 링크가 길어도 무방하다면, URL 매개변수를 사용해 직접 동적 링크를 만들 수 있습니다. 직접 만드는 경우에는 추가 네트워크 왕복을 피할 수 있습니다.

우리는 여기서 두번째 방법을 이용하여 앱 내에서 동적링크를 생성 하려고 한다.

짧은 Dynamic Links 생성

Dynamic Links는 긴동적링크와 짧은 동적링크로 구분할 수 있는데 결국 동작하는 것은 같으며 길이의 차이이다. 우리는 짧은 Dynamic Links 를 생성하는 코드를 살펴보겠다.

여기서 uriPrefix 에 해당되는 부분이 설정한 도메인에 해당되며 link에선 도메인을 통해 특정 컨텐츠에 접근하기 위한 URL을 생성하면 된다.

필자의 경우 스크린 이름을 하위 path로 설정하였고 각각의 아이디별로 다른 화면을 보여주기 위하여 id란 이름의 쿼리 파라미터를 설정하였다.

생성된 링크 공유하기

생성된 짧은 링크를 유저가 공유한다고 가정하면 아래 라이브러리의 도움을 받아서 손 쉽게 목적을 달성할 수 있다.

아래 명령어를 통해 설치한다.

flutter pub add share_plus

패키지 설치 후 아래 코드와 같이 생성된 짧은 Dynamic links URL 공유하도록 한다.

Share.share(
await getShortLink(
artist,
_artist.id!,
),
);

6. 수신된 Dynamic Links를 통하여 특정 컨텐츠 화면으로 이동하기

Dynamic Links를 수신하는 방법에는 두가지 방법이 있으며 앱이 실행중(포그라운드 또는 백그라운드 상태)와 완전히 종료됐을때 각각의 방법이 다르다.

⚠️ 참고로 Dynamic Links 를 브라우저에 직접 입력했을시는 작동하지 않는다.

다른 앱에 Dynamic links를 공유하여 확인해 보거나 메모앱등에서 붙여넣어 테스트를 해 봐야 한다.

안드로이드의 경우 아래 명령어로 다이나믹 링크 테스트가 가능하다.


adb shell am start -W -a android.intent.action.VIEW -d "https://page.test/test"

여러 기기가 연결되어 있다고 에러가 발생할 경우 adb devices 로 디바이스 확인 이후, -s 옵션을 이용해 실행할 디바이스 이름을 포함시킨다.


adb -s emulator-5554 shell am start -W -a android.intent.action.VIEW -d "https://page.test/test"

앱이 실행중인 경우

먼저 앱이 실행중인 상태에는 리스너를 등록해주면 Dynamic links 가 수신될때 콜백 URL이 동작한다.

FirebaseDynamicLinks.instance.onLink.listen((
PendingDynamicLinkData dynamicLinkData,
) {
_redirectScreen(dynamicLinkData);
}).onError((error) {
logger.e(error);
});

여기서 _redirectScreen에서 원하는 화면으로 네비게이션을 바꿔주면 되는데 나중에 이는 전체 코드를 보여드리면 이해가 가실 것으로 생각 한다.

앱이 종료됐을 경우

앱이 완전히 종료됐을 경우엔 해당 리스너 말고 다른 방법을 이용하여야 하는데 공식문서의 방법은 iOS의 경우 수신되지 않아 별도로 다른 방법을 통해 구현했다.

수신된 Dynamic Links를 가져오기 위해 별도의 라이브 러리가 필요한데 아래 명령어를 통해 해당 라이브러리를 설치해준다.

flutter pub add uni_links

이후 아래 코드를 작성하면 앱 종료 후에도 dynamicLinkData를 수신 할 수 있다.

Future<bool> _getInitialDynamicLink() async {
final String? deepLink = await getInitialLink();

if (deepLink != null) {
PendingDynamicLinkData? dynamicLinkData = await FirebaseDynamicLinks
.instance
.getDynamicLink(Uri.parse(deepLink));

if (dynamicLinkData != null) {
_redirectScreen(dynamicLinkData);

return true;
}
}

return false;
}

위에서 설명한 전체 코드는 아래와 같으며 별도로 DynamicLink 클래스를 생성해 관리하면 편리하다.

위의 코드는 앱이 시작할때 아래와 같이 호출 해주면 Dynamic links가 수신됨에 따라 특정 컨텐츠 화면으로 이동 된다.

DynamicLinks().setup();

결과적으로 아래 영상과 같이 이동함을 볼 수 있다.

--

--