Cordova에서 Android/iOS 분기를 넣다 보면, iOS는 잘 되는데 Android에서만 Gradle 빌드가 터지거나(혹은 반대), 특정 환경(Release만, 특정 ABI만)에서만 실패하는 경우가 종종 생깁니다. 대개는 “분기 처리”를 위해 추가한 설정이 build.gradle에 누적되면서 충돌하는 패턴이에요.
아래는 빌드 로그 → 흔한 원인 → 해결 단계 순서로, Product Flavor/변수/플러그인 hook 때문에 꼬이는 상황을 빠르게 정리하는 가이드입니다.
1) 빌드 로그에서 ‘분기 관련’ 신호 먼저 찾기
먼저 실패 지점을 “플러그인 설치/적용 단계”인지, “Gradle 설정 파싱 단계”인지, “컴파일/패키징 단계”인지 나눠보면 원인 범위가 확 줄어듭니다.
- Gradle 파싱/설정 단계: “Could not find method …”, “A problem occurred evaluating project …”, “Duplicate method …”
- 의존성 해결 단계: “Could not resolve …”, “All com.android.support libraries must use the exact same version”, “Duplicate class …”
- 빌드 변형(variant/flavor) 단계: “Task … not found”, “Variant … was not found”, “Cannot choose between the following variants …”
특히 분기(예: dev/prod, free/paid, China/Global)를 넣은 프로젝트는 로그에 flavor, variant, applicationIdSuffix, manifestPlaceholders, productFlavors 같은 단어가 자주 등장합니다. 이 키워드가 보이면 “설정 충돌” 가능성이 큽니다.
2) 흔한 원인 A: Product Flavor를 Cordova가 모르는 방식으로 추가함
Cordova-Android는 내부적으로 기본 빌드 태스크/variant 구성을 전제로 동작합니다. 여기에 productFlavors를 무리하게 넣으면, Cordova가 호출하는 태스크 이름과 실제 생성된 태스크가 어긋나서 실패하기도 합니다.
자주 보이는 로그 예
- “Task 'assembleDebug' not found in project ':app'”
- “Variant 'debug' was not found. Please specify a variant name.”
해결 단계
- 우선 Android Studio/Gradle 기준으로 실제 생성되는 variant를 확인합니다. (예: devDebug, prodRelease)
- Cordova CLI로 빌드할 때는, 가능하면 Cordova-Android가 지원하는 방식(빌드 타입/환경변수/gradleArg)으로 우회합니다.
- 정말 flavor가 필요하다면, “Cordova가 호출하는 태스크”와 “생성되는 태스크”가 일치하도록 빌드 호출을 flavor에 맞춰 조정합니다. (프로젝트별로 다르니, 먼저 variant 목록을 확정하는 게 핵심입니다.)
포인트는 “flavor를 추가하는 것” 자체보다, Cordova 빌드 파이프라인이 어떤 variant를 기대하는지를 먼저 맞추는 겁니다.
3) 흔한 원인 B: build.gradle 변경이 누적(중복 삽입)되어 충돌
Cordova 플러그인과 hook은 build.gradle에 내용을 “추가 삽입”하는 방식이 많습니다. 분기 로직을 넣으려고 직접 편집까지 섞이면, 어느 순간 아래처럼 중복이 생깁니다.
자주 보이는 로그 예
- “Could not find method implementation() for arguments …” (gradle plugin 버전/DSL 불일치 포함)
- “Cannot add task 'xxx' as a task with that name already exists.”
- “Duplicate class … found in modules …” (의존성 중복으로 이어짐)
해결 단계(안전한 정리 순서)
- platforms/android는 “생성물”로 보고, 우선 백업 후 재생성 가능한 상태인지 확인합니다.
- 직접 수정한 build.gradle이 있다면, “왜 필요한지”를 메모로 남기고(또는 별도 패치 파일로 관리) 재현 가능한 형태로 옮깁니다.
- 플러그인/Hook이 넣는 gradle 설정은 중복 삽입이 쉬우니, 동일 블록(productFlavors, repositories, dependencies, packagingOptions 등)이 두 번 들어가지 않는지 확인합니다.
특히 팀에서 “cordova platform rm/add android”를 자주 하는 프로젝트라면, 수동 편집은 결국 사라지기 쉬워서 더 위험합니다. 가능하면 config.xml/플러그인 변수/Hook 중 한 가지로만 관리 포인트를 정하는 편이 안정적이에요.
4) 흔한 원인 C: Android 전용 gradle 설정을 iOS에도 적용하려고 한 흔적
각 플랫폼 분기 안내를 하다 보면, “공통 스크립트에서 Android/iOS를 한 번에 처리”하려고 하다가 문제가 생깁니다. 예를 들어 Hook이 iOS 빌드에도 실행되는데 Android 전용 파일을 건드리거나, 반대로 Android 빌드에서 iOS 파일을 찾다가 실패하는 식이죠.
자주 보이는 로그 예
- “File not found: platforms/android/app/build.gradle” (플랫폼 추가 전/경로 변경 시)
- “Cannot read property … of undefined” (Hook에서 platform 분기 누락)
해결 단계
- Hook 스크립트에서 platform === 'android' / platform === 'ios' 분기를 먼저 강제합니다.
- 플랫폼 폴더 존재 여부를 체크하고, 없으면 조용히 종료(또는 명확한 메시지로 실패)하도록 합니다.
- Android 전용 변경(build.gradle, AndroidManifest.xml, res/xml 등)과 iOS 전용 변경(Info.plist, entitlements 등)을 한 파일에서 섞지 말고, 최소한 함수/모듈로 분리해둡니다.
분기 자체는 간단하지만, “플랫폼 추가/삭제/재생성” 같은 Cordova의 워크플로우를 고려하지 않으면 로그가 애매해지고 재현이 어려워집니다.
5) 흔한 원인 D: manifestPlaceholders/applicationIdSuffix로 런타임 값이 꼬임
Android/iOS 분기 안내를 하다 보면, Android 쪽에서만 도메인/스킴/키 값을 바꾸기 위해 manifestPlaceholders나 applicationIdSuffix를 쓰는 경우가 있습니다. 이때 플러그인이 참조하는 값이 variant별로 달라져서 빌드/패키징 단계에서 실패할 수 있어요.
자주 보이는 로그 예
- “Manifest merger failed …”
- “Attribute … is also present …” (variant별 manifest가 충돌)
- “INSTALL_FAILED_CONFLICTING_PROVIDER” (빌드는 되는데 설치 단계에서 충돌)
해결 단계
- Manifest merge 로그를 끝까지 보고, 어떤 manifest(플러그인/메인/variant)가 충돌하는지 먼저 확정합니다.
- provider/authority 같은 값은 applicationId에 의존하는 경우가 많아, suffix 적용 시 함께 바뀌도록 규칙을 통일합니다.
- 플러그인 문서에 “manifestPlaceholders를 사용하라”는 가이드가 있다면, 그 키 이름을 variant마다 다르게 만들지 말고 한 키로 유지하는 편이 안전합니다.
6) 빠른 점검 체크리스트(로그 기반)
- 로그에 variant/flavor가 보이면: 생성된 variant 이름과 Cordova가 호출하는 태스크가 맞는지 확인
- “evaluating project”, “could not find method”면: build.gradle 파싱 단계 충돌(중복/버전/DSL)부터 의심
- “duplicate class”면: dependency 중복(플러그인 간 동일 라이브러리) 가능성 → 의존성 정리/버전 통일
- Hook 사용 시: platform 분기와 파일 존재 여부 체크가 있는지 확인
- platforms/android 직접 수정했으면: 재생성 시 사라질 수 있는 변경인지, 재현 가능한 관리 방식인지 점검
마무리
Cordova에서 Android/iOS 분기 처리를 하다가 생기는 Gradle 문제는, 대부분 “설정이 늘어나는 과정에서 중복/불일치가 생긴 것”으로 귀결됩니다. 빌드 로그를 단계별로 나눠 보고(파싱/의존성/variant), flavor·hook·manifestPlaceholders처럼 분기와 맞닿은 지점부터 정리하면 빨리 안정화됩니다.
가능하면 변경 지점을 한 곳(config.xml 또는 플러그인 변수 또는 hook)으로 줄이고, platforms 폴더를 재생성해도 동일하게 재현되는 형태로 관리해두면 이후 유지보수가 훨씬 편해져요.