히어릿(hEARit)팀은 평소처럼 새로운 기능에 대한 앱 업데이트를 진행했다.
이번 1.3.1 버전 업데이트에서는 다음과 같은 변경이 있었다.
그런데, 업데이트가 배포되자마자 히어릿을 업데이트한 백엔드 팀원이 이런 말을 했다.
“앱이 업데이트됐는데 갑자기 아이콘이 안 보여요.”
“플레이스토어에서 제거 버튼만 보이고 열기 버튼이 없어요.
백엔드 팀원 외에도 “? 히어릿 업데이트 후 앱 아이콘도 사라지고 실행이 불가능해요.🙄”와 같은 슬랙 메시지를 받기도 했다.

순간 머리가 띵했다.
사실 새로운 기능을 개발하면서도 애뮬레이터에서 빌드할 때 항상 존재하던 hEARit(dev) 앱이 어느 순간부터 설치가 되지 않는 현상을 발견하긴 했었다.
하지만 애뮬레이터는 늘 많은 문제를 일으켰기 때문에, 큰 문제라고 생각하지 않았다.
“에이, 또 에뮬레이터 버그겠지.” 하고 넘겼다.
그런데 이번에는 진짜였다.
실제 서비스 버전이 플레이스토어에 올라간 직후, 앱이 실행되지 않는다는 이야기가 계속 들려왔다.
앱이 아예 실행 불가 상태가 된 것이었다.
결론부터 말하자면,
런처용 인텐트(MAIN/LAUNCHER)와 딥링크용 인텐트(VIEW)를 하나의 intent-filter로 합쳐둔 것이 원인이었다.
<data>가 포함된 필터는 데이터가 없는 런처 인텐트와 매칭되지 않는다.
즉, 앱 아이콘을 눌렀을 때 실행되어야 할 인텐트가 동작하지 않아,
업데이트 직후 앱이 실행 불가 상태가 된 것이다.
이번 업데이트에서는 카카오톡 공유 기능을 추가하면서
딥링크 진입을 SplashActivity에서 처리하도록 AndroidManifest.xml을 수정했는데,
이 과정에서 런처와 딥링크 인텐트를 분리하지 않은 채 하나의 필터로 합친 것이 문제였다.
<activity
android:name=".presentation.splash.SplashActivity"
android:exported="true">
<!-- 런처 + 딥링크를 한 필터에 섞음 -->
<intent-filter>
<!-- 런처 -->
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<!-- 딥링크 -->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="host"
android:scheme="scheme" />
</intent-filter>
</activity>
그 결과 앱 아이콘을 눌러도 실행되지 않았고,
플레이스토어에서도 ‘열기’ 버튼이 사라지게 되었다...
<activity
android:name=".presentation.splash.SplashActivity"
android:exported="true">
<!-- 런처 전용 -->
<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:host="host"
android:scheme="scheme" />
</intent-filter>
</activity>
이처럼 런처용 인텐트와 딥링크용 인텐트를 분리해야 한다.
런처는 데이터를 포함하지 않기 때문에 <data>가 들어간 필터에 매칭되지 않고,
딥링크는 반대로 데이터를 포함하므로 별도의 필터로 분리해야 정상적으로 동작한다.
30분 만에 hotfix로 오류를 수정하고 곧바로 플레이스토어에 검토 요청을 보냈다.
하지만 검토가 진행되는 동안에는 그저 “제발 빨리 승인되라”며 마음속으로 빌 수밖에 없었다.
잠시 동안 끊겨 있는 서비스 지표 그래프를 바라보며 마음이 착잡했다.
그래도 한편으로는 실제로 우리 앱을 사용하는 사용자가 있기 때문에 이렇게 빠르게 문제를 인지하고 대응할 수 있었다는 점이 감사하면서도, 동시에 조금은 슬픈 경험이었다.

다행히 검토가 완료된 후 수정 버전이 빠르게 반영되어,
유저들이 다시 정상적으로 앱을 사용할 수 있게 되었다.
짧은 시간이었지만, 히어릿은 잠시 “설치되어 있지만 들어갈 수 없는 9와 4분의 3 승강장 앱” 이 되었다.

이번 일을 통해 intent-filter 한 줄의 위력이 얼마나 큰지 다시금 실감했고,
앞으로는 이런 실수를 절대 반복하지 않겠다고 다짐했다..
하나의
intent-filter에MAIN/LAUNCHER와VIEW/BROWSABLE을 동시에 넣으면 안드로이드 시스템이 앱 런처를 인식하지 못하나 보네요.좋은 내용 공유해주셔서 감사합니다.