AI 이미지 생성 앱을 여러 개 운영하고 있습니다. 코드 골격을 공유하는 형제 앱들이라 한 곳을 고치면 나머지에도 반영해야 하는데, 스토어에 올라간 버전과 개발 중인 버전을 한 기기에서 나란히 비교하고 싶어서 applicationIdSuffix를 붙였습니다. 그랬더니 빌드가 통째로 깨졌습니다.
Execution failed for task ':app:processDebugGoogleServices'.
> No matching client found for package name 'com.example.myapp.debug'
검색해보면 해결책은 금방 나옵니다. 그런데 그 해결책을 그대로 따라가면 두 번째 벽에 부딪힙니다. 이 글은 첫 번째 벽을 넘는 방법과, 아무도 미리 말해주지 않는 두 번째 벽까지 정리한 글입니다.
왜 이 에러가 나는가
원인은 google-services 그래들 플러그인의 동작 방식에 있습니다. 이 플러그인은 빌드할 때 google-services.json 안에 있는 client 목록을 훑으면서, 지금 빌드 중인 변형의 applicationId와 정확히 일치하는 항목을 찾습니다.
문제는 Firebase 콘솔에서 앱을 등록할 때 보통 프로덕션 패키지명 하나만 넣는다는 점입니다. 그래서 google-services.json에는 이런 항목 하나만 들어 있습니다.
"client_info": {
"android_client_info": {
"package_name": "com.example.myapp"
}
}
여기에 build.gradle에서 접미사를 붙이면
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
디버그 빌드의 실제 applicationId는 com.example.myapp.debug가 됩니다. JSON에는 com.example.myapp밖에 없으니 일치하는 항목이 없고, 플러그인은 빌드를 중단시킵니다. 부분 일치가 아니라 완전 일치를 요구한다는 점이 핵심입니다.
해결 방법 세 가지
1. Firebase 콘솔에 debug 패키지를 별도 앱으로 등록한다 (권장)
가장 정석입니다. Firebase 콘솔 → 프로젝트 설정 → 내 앱에서 앱 추가를 누르고, 패키지명에 접미사까지 포함한 com.example.myapp.debug를 넣습니다. 그다음 google-services.json을 새로 내려받아 app/ 폴더의 기존 파일을 교체하면, 이제 그 파일 안에 client 항목이 두 개가 됩니다.
이 방법의 장점은 파일을 하나만 관리하면 된다는 것입니다. 디버그와 프로덕션이 Firebase 프로젝트를 공유하므로 설정도 단순합니다.
2. 빌드 타입별로 google-services.json을 나눈다
디버그를 아예 다른 Firebase 프로젝트로 분리하고 싶을 때 쓰는 방법입니다. 그래들은 빌드 타입 이름의 소스셋 디렉터리를 먼저 찾으므로, 아래 위치에 파일을 두면 됩니다.
app/src/debug/google-services.json ← 디버그용
app/google-services.json ← 그 외(릴리스)
운영 데이터와 테스트 데이터를 완전히 분리할 수 있다는 게 장점입니다. 대신 Firebase 프로젝트를 두 개 관리해야 하고, 콘솔에서 지표를 볼 때 두 곳을 오가야 합니다.
3. 접미사를 붙이지 않는다
가장 소극적으로 보이지만, 경우에 따라 이게 정답입니다. 이유는 다음 단락에서 설명합니다.
여기서 끝나지 않습니다 — 두 번째 벽
위 1번이나 2번으로 빌드는 통과합니다. 그런데 앱을 실행하면 기능이 동작하지 않는 경우가 있습니다. 저는 이걸 실제로 겪고 나서야 알았습니다.
App Check(Play Integrity)가 디버그 패키지에서 통과하지 못합니다
Play Integrity API는 Play 스토어에 등록된 패키지명과 서명을 기준으로 기기와 앱의 무결성을 판정합니다. .debug가 붙은 패키지는 스토어에 존재하지 않는 앱이므로 정상적인 무결성 판정을 받을 수 없습니다. 서버에서 App Check 토큰을 검증하는 구조라면 API 호출이 전부 막힙니다.
이 경우에는 Firebase 콘솔의 App Check 메뉴에서 디버그 제공자(Debug provider)를 따로 등록해야 합니다. 앱을 처음 실행할 때 로그캣에 찍히는 디버그 토큰을 콘솔에 등록하는 방식인데, 기기를 바꾸거나 앱 데이터를 지우면 토큰이 새로 발급되므로 그때마다 다시 등록해야 합니다.
Play Billing도 마찬가지입니다
인앱 결제는 Play 스토어에 업로드된 빌드를 전제로 동작합니다. 스토어에 없는 .debug 패키지에서는 상품 목록 조회부터 실패합니다. 결제 흐름을 테스트하려면 결국 프로덕션과 같은 패키지명으로 빌드해서 내부 테스트 트랙에 올려야 합니다.
그래서 어떻게 판단하면 되나
제 앱들을 정리해보니 기준이 명확해졌습니다.
| 앱의 성격 | 접미사 | 이유 |
|---|---|---|
| google-services를 안 쓰는 앱 (Firebase 미사용) |
붙여도 됨 | 플러그인이 없으니 패키지명 검사 자체가 없습니다. 디버그판과 스토어판을 한 기기에 같이 두고 비교할 수 있어 편합니다. |
| Firebase + App Check + 인앱결제를 쓰는 앱 |
붙이지 않는 편이 낫다 | 빌드는 통과시킬 수 있어도 정작 검증해야 할 기능이 디버그 패키지에서 동작하지 않습니다. 함정을 하나 늘리는 셈입니다. |
실제로 저는 Firebase를 쓰지 않는 앱들에는 .debug를 붙여 두 버전을 한 기기에 공존시키고 있고, AI 이미지 생성 앱들처럼 App Check와 구독 결제가 걸린 앱에는 접미사를 붙이지 않습니다. 대신 테스트 전용 단말을 따로 두고, 거기서는 스토어판을 지운 뒤 디버그 빌드를 올립니다.
앱마다 Firebase 프로젝트를 따로 두고 있다면 판단이 더 분명해집니다. 접미사를 쓰려면 앱 수만큼 debug 앱을 콘솔에 추가로 등록해야 하는데, 앱이 다섯 개면 등록해야 할 항목이 열 개가 됩니다. 관리 비용이 편의성을 넘어서는 지점이 생각보다 빨리 옵니다.
접미사를 붙이지 않으면 같은 기기에 스토어판과 디버그판을 동시에 설치할 수 없다는 불편이 생깁니다. 하지만 무결성 검증과 결제가 실제로 동작하는 상태에서 테스트하는 것이 훨씬 중요합니다. 빌드가 통과하는 것과 기능이 동작하는 것은 다른 문제입니다.
정리
- 이 에러는
google-services.json의package_name과 빌드 중인applicationId가 완전히 일치하지 않아서 발생합니다. - Firebase 콘솔에 debug 패키지를 앱으로 추가하고 JSON을 교체하는 것이 가장 간단합니다.
- 다만 App Check(Play Integrity)와 Play Billing은 디버그 패키지에서 정상 동작하지 않습니다.
- 이 둘을 쓰는 앱이라면 접미사를 포기하고 테스트 전용 단말을 두는 편이 결과적으로 시간을 아낍니다.
'안드로이드 개발' 카테고리의 다른 글
| 오늘의 음주 코딩 23년 5월 25일 (7) | 2023.05.25 |
|---|---|
| Android에서 화면 크기를 픽셀로 얻는 방법 (4) | 2023.05.12 |
| 안드로이드 context란? (6) | 2023.05.12 |
| 안드로이드 키패드 숨기는 방법. InputMethodManager (4) | 2023.05.11 |
| java.lang.ClassCastException: androidx.emoji2.text.SpannableBuilder cannot be cast to java.lang.String (2) | 2023.05.11 |