[Flutter] Deferred Deep Link 적용 에러 모음

Angela Jeong·2024년 8월 26일

Flutter 딥링크

목록 보기
5/7

App Links 적용기 에서 Universal Link와 App Links에 대해 간단히 설명했지만 사실 딥링크에는 또 다른 유형이 있다.

바로 Deferred Deeplink!!


디퍼드 딥링크란?

생각해보면 어떤 앱은 링크를 눌러 스토어로 이동하여 앱을 설치하고 나면 내가 처음 봤던 페이지로 곧바로 리다이렉트를 시켜주는 반면,

어떤 앱은 스토어에서 다운로드를 받고 나면 그냥 메인에만 머무른다.

이처럼 앱 설치가 끝날 때까지 딥링크 동작을 지연시켰다가 설치 후 앱으로 돌아오면 곧바로 특정 화면으로 이동시켜주는 기술이 바로 디퍼드 딥링크 (= 지연된 딥링크)다 !

디퍼드 딥링크는 SDK로 구현이 가능한데 그 중에서도 가장 많이 쓰이는 AppsFlyer의 Onelink를 적용해보았다.

AppsFlyer 문서를 보면 네이티브 설정 방법에 대해 정말 자세하게 나와 있지만 플러터는 pud.dev의 깃헙과 연결되어 있는게 전부라 리서치 하는 과정이 꽤 힘들었다..

설정 방법을 정리하는 것도 좋지만 일단 내가 겪은 디버깅 과정을 적어보려고 한다.

참고: https://github.com/AppsFlyerSDK/appsflyer-flutter-plugin



1. 앱은 열리는데 원하는 페이지로 이동하지 않는다.


문제 상황)

앱 설치 상태에서 링크를 눌렀을 때 분명히 앱은 열리는데 도대체 원하는 페이지로 이동하지 않았다.
main에서 appsflyer sdk를 초기화 하고, 링크가 열리면 라우팅을 통해 내가 원하는 페이지로 이동이 되야 했다.

알고보니 나는 라우터가 초기화 되기도 전에 context.go 메서드로 딥링크를 통해 받은 경로를 처리하고 있었다. ㅎㅎ
그러니까, 아직 앱은 라우터 경로를 인식하지 못하는 상태인데 나는 딥링크의 정보를 가지고 계속 라우팅을 시도하니 메인에 머무를 수 밖에 없었다.

appsflyer SDK 초기화 로직을 main이 아닌 mainPage로 이동시켜 앱이 시작될 때 가장 먼저 라우터를 초기화 시키고 그 이후에 딥링크 이벤트를 처리함으로써 문제가 해결되었다.

앱 라이프사이클을 제대로 이해하지 못해 생긴 문제였다 ㅠ_ㅠ

2. 릴리즈 모드에서 안드로이드는 백그라운드에 앱이 있을 때만 딥링크가 작동한다.


정말 원인을 알 수가 없어서 sdk 문서를 여러 번 살펴보고 여기저기 프린트를 찍어보며 며칠을 보냈다.

문제 상황)

릴리즈 모드에서 안드로이드 폰에 앱을 빌드하고, 앱을 날린 다음 링크를 누르면 아무 동작도 일어나지 않았다.

정확히는 링크를 눌렀을 때 "사용 가능한 앱"을 고르라는 하단 팝업은 잘 떴지만, 앱을 눌렀을 때 동작을 하지 않았다.

1.앱을 삭제 한 후에 링크를 눌렀을 때는 웹 페이지가 잘 열린다
=> 즉, applinks.json 파일 같은 웹 관련 설정은 문제가 없다.

디버그 모드와 릴리즈 모드의 SHA 26 지문이 달라서 생기는 문제라는 글도 있었지만 웹 페이지가 잘 열리는 것으로 봐서 앱과 웹 간의 신뢰문제는 아니라고 판단했다.

2. 링크를 눌렀을 때 사용 가능한 앱을 고르라는 팝업이 잘 뜬다.
=> App Scheme 설정에도 문제는 없다.

안드로이드의 경우 만약 디바이스 내에 겹치는 App Scheme이 있다면 "사용할 앱을 선택하세요" 팝업이 하단에 올라온다. 반면 iOS는 가장 최근에 열었던 앱이 뜨게 되어있다. 그러니까 디바이스에서 App Scheme을 잘 인식했으니까 이 팝업이 뜨는 거 아닐까?

3. Deferred Deep Link의 원리를 다시 생각해보자..

위 이미지는 AppsFlyer onelink를 설정하는 대시보드다.
app 설치 유무에 따른 작동을 자세히 살펴보면

앱이 설치되었을 때는 먼저 iOS는 Universal links를, Android는 App Links를 실행하고 여기서 실패한다면 fallback으로 example:// 로 되어있는 URI scheme이 동작한다는 걸 알 수 있다.

그러니까 지금 나는 제 3의 sdk를 쓰고 있기는 하지만 어쨌든 Universal links/ Android는 App Links, URI scheme 모든 것이 제대로 설정 되어 있어야 문제 없이 딥링크가 동작한다는 것이다.

다시 App links 설정을 제대로 했는지 살펴봐야 한다.

4. Back to Basic!
친절하지 않은 SDK 문서가 아닌 플러터 공식 App links 문서로 돌아가 하나씩 설정을 살펴봤고 역시 모든 문제는 내 눈에 있다는 걸 느끼며 ^^ 애초에 manifest 파일에 intent를 잘못 넣은 걸 알 수 있었다.

App links 테스트할 때 분명히 확인했었는데.. AndroidManifest.xml 파일의 구조와 흐름을 제대로 이해하지 못한 채, AppsFlyer SDK 문서만 참고하다 보니 일부 중요한 설정을 놓쳐버린 것이다.

처음에는 딥링크를 처리하기 위해 intent-filter를 아무 액티비티의 태그에 추가했었다. ㅎ

AndroidManifest.xml 파일에서 android:name=".MainActivity"는 앱이 시작될 때 실행되는 액티비티, 즉 메인 엔트리 포인트를 지정한다.

그니까 앱이 시작될 때 실행되는 액티비티는 MainActivity 하단에 넣어줘야 한다는 것!!

AndroidManifest.xml 파일을 Read.me 파일 보듯이 한 내 잘못이다 ㅠ_ㅠ
아무 activity 태그에 intent 태그를 넣어서는 안된다!!
아래 처럼 넣어줘야 굿

<activity
   android:name=".MainActivity"
   android:exported="true"
   android:launchMode="singleTop"
   android:theme="@style/LaunchTheme"
   android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
   android:hardwareAccelerated="true"
   android:windowSoftInputMode="adjustResize">
   
   <meta-data
       android:name="io.flutter.embedding.android.NormalTheme"
       android:resource="@style/NormalTheme" />
   
   <intent-filter>
       <action android:name="android.intent.action.MAIN"/>
       <category android:name="android.intent.category.LAUNCHER"/>
   </intent-filter>
   
   <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="exampleapp" />
   </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="example.onelink.me" />
   </intent-filter>
</activity>


가끔 뭔가 잘 안될 때, 내가 예상한 대로 동작하지 않을 때 누가 이기나 한번 해보자!!는 마음으로 이리 저리 정신없이 검색할 때가 있다.

그렇게 해서는 아무것도 안되겠다는 감이 이제는 온다. ㅎㅎ

잘 안될 땐 차라리 리서치를 모두 멈추고 다시 침착하게 코드를 보는 편이 낫다는 생각이 들었다.

이건 내 사수가 일 하는 방식이기도 한데, 사수는 어려운 문제를 만났을 때 리서치를 조금 하다가 다시 코드로 돌아와 문제를 찾는다.

지금보다 훨씬 더 침착하게 개발을 해보길..

화이팅!

0개의 댓글