Recode Log

  • tech-blog
  • apps
  • device
  • features
Copyright © [WebKBS]. All rights reserved.
  • tech-blog
  • apps
  • device
  • features
  1. Home
  2. tech-blog
  3. EAS 없이 Expo 앱 로컬 빌드해서 Play Console 내부 테스트 배포하기

EAS 없이 Expo 앱 로컬 빌드해서 Play Console 내부 테스트 배포하기

EAS를 사용하지 않고 Expo(React Native) 앱을 로컬에서 prebuild + Gradle로 빌드해 Google Play Console 내부 테스트 트랙까지 배포하는 과정을 정리합니다. 서명(signing) 설정에서 자주 만나는 에러 두 가지도 원인과 함께 다룹니다.

  • expo ^57.0.2
  • react-native 0.86.0
2026년 7월 5일

들어가며

dev-handbook-app(Expo/React Native)을 EAS 없이 로컬에서 직접 빌드해서 Google Play Console 내부 테스트 트랙까지 배포하는 과정을 정리합니다.

EAS를 쓰지 않으면 keystore 관리와 서명 설정을 전부 직접 해야 하고, 이 서명 부분에서 에러를 만나기 쉽습니다. 그래서 4단계 서명 설정에 자주 나오는 에러 두 가지를 원인/해결과 함께 정리했습니다.

전체 흐름은 다음과 같습니다.

  1. expo prebuild로 android/ 생성
  2. keytool로 release용 keystore 생성
  3. gradle.properties에 keystore 변수 등록
  4. app/build.gradle에 서명 설정
  5. bundleRelease로 AAB 빌드
  6. AAB 서명 확인
  7. Play Console 내부 테스트 배포

전제: EAS를 사용하지 않으므로 keystore 생성과 서명 설정을 직접 진행합니다.

1. android 디렉토리 생성 (prebuild)

Expo 관리형 프로젝트에는 android/가 없으므로 먼저 네이티브 프로젝트를 생성합니다.

root directory
npx expo prebuild --platform android

루트에 android/ 디렉토리가 생성됩니다. 이 안의 gradle.properties와 app/build.gradle을 이후 단계에서 수정합니다.

2. release용 keystore 생성

Play에 올릴 AAB는 debug 키가 아니라 release 키로 서명해야 합니다. keytool로 keystore를 생성합니다.

keystore 생성
keytool -genkeypair -v -storetype PKCS12 -keyalg RSA -keysize 2048 \
  -validity 10000 -alias <별칭> -keystore <파일명>.keystore

실행하면 순서대로 입력을 받습니다.

  • keystore 비밀번호 (storePassword)
  • key 비밀번호 (keyPassword)
  • 이름, 조직 단위, 조직, 지역 등 조직 정보 (CN/OU/O ...)

마지막 확인 프롬프트 주의

조직 정보를 모두 입력하면 마지막에 확인 프롬프트가 나옵니다.

CN=..., OU=..., O=..., ... 이(가) 맞습니까? [아니오]:

기본값이 [아니오] 입니다. 그냥 엔터를 치면 "아니오"로 처리되어 입력을 처음부터 다시 받습니다. 반드시 예를 명시적으로 입력해야 넘어갑니다.

... 이(가) 맞습니까? [아니오]:  예

3. gradle.properties에 keystore 변수 등록

생성한 keystore를 Gradle이 참조할 수 있게 변수로 등록합니다. android/gradle.properties에 아래 4개를 추가합니다.

android/gradle.properties
MYAPP_UPLOAD_STORE_FILE=<파일명>.keystore
MYAPP_UPLOAD_KEY_ALIAS=<별칭>
MYAPP_UPLOAD_STORE_PASSWORD=<keystore 비밀번호>
MYAPP_UPLOAD_KEY_PASSWORD=<key 비밀번호>

keystore 파일은 보통 android/app/ 아래에 두고, MYAPP_UPLOAD_STORE_FILE에는 그 파일명을 적습니다. 이 파일과 비밀번호는 git에 커밋하지 않습니다.

4. app/build.gradle 서명 설정

android/app/build.gradle의 android { } 블록에서 서명을 설정합니다. 이 구간에서 서명 관련 에러 두 가지가 자주 발생하므로 원인과 함께 정리합니다.

에러 1 — signingConfigs 블록 안에서 signingConfig() 호출

signingConfigs.release 블록 안에 signingConfig signingConfigs.release 줄을 넣으면 다음 에러가 발생합니다.

에러 메시지
Could not find method signingConfig() for arguments [...]
on SigningConfig$AgpDecorated_Decorated

원인

signingConfigs { release { ... } } 블록에서 정의하는 대상은 SigningConfig 객체입니다. SigningConfig 객체가 가진 프로퍼티는 storeFile, storePassword, keyAlias, keyPassword 뿐이고, signingConfig()라는 메서드는 없습니다.

signingConfig는 SigningConfig가 아니라 BuildType의 프로퍼티입니다. "이 빌드 타입이 어떤 서명 설정을 쓸지 지정"하는 용도라 buildTypes { ... } 블록에서만 사용해야 합니다. 이를 signingConfigs 블록 안에서 호출했기 때문에 Gradle이 "SigningConfig 객체에 signingConfig() 메서드가 없다"고 알려주는 것입니다. 에러 메시지 끝의 on SigningConfig$AgpDecorated_Decorated가 "SigningConfig 객체 위에서 그 메서드를 찾았다"는 의미입니다.

해결

signingConfigs.release 블록에서는 키 정보만 정의하고, signingConfig ... 줄은 넣지 않습니다.

android/app/build.gradle
android {
    signingConfigs {
        release {
            storeFile file(MYAPP_UPLOAD_STORE_FILE)
            storePassword MYAPP_UPLOAD_STORE_PASSWORD
            keyAlias MYAPP_UPLOAD_KEY_ALIAS
            keyPassword MYAPP_UPLOAD_KEY_PASSWORD
            // signingConfig signingConfigs.release  <- 여기 있으면 안 됨
        }
    }
}

에러 2 — 빌드는 성공하지만 Play가 "디버그 서명"이라고 거부

빌드는 정상적으로 완료되는데, AAB를 Play Console에 업로드하면 다음 에러가 발생합니다.

Play Console 업로드 에러
디버그 모드로 서명한 APK 또는 Android App Bundle을 업로드했습니다.

원인

React Native 기본 템플릿의 buildTypes.release 블록에는 서명 설정이 signingConfig signingConfigs.debug로 하드코딩되어 있습니다.

RN 기본 템플릿 (문제의 원본)
buildTypes {
    debug {
        signingConfig signingConfigs.debug
    }
    release {
        // Caution! In production, you need to generate your own keystore file.
        signingConfig signingConfigs.debug   // <- release인데 debug 키를 참조
        ...
    }
}

3~4단계에서 signingConfigs.release(release 키)를 정의만 하고, release 빌드 타입은 여전히 signingConfigs.debug를 참조하고 있는 상태입니다. 그래서 빌드 자체는 debug 키로 정상 서명되어 성공하지만, 결과물은 debug 키로 서명된 AAB이고 Play가 이를 거부합니다.

해결

buildTypes.release의 참조를 signingConfigs.debug → signingConfigs.release로 변경합니다.

android/app/build.gradle
buildTypes {
    debug {
        signingConfig signingConfigs.debug
    }
    release {
        signingConfig signingConfigs.release   // debug -> release 로 변경
        // ...minifyEnabled, proguardFiles 등은 그대로
    }
}

5. release 빌드 (AAB)

서명 설정을 수정했으면 이전 빌드 캐시를 지우고 다시 빌드합니다. Play는 APK가 아니라 AAB(Android App Bundle) 를 요구하므로 bundleRelease를 사용합니다.

android directory
./gradlew clean && ./gradlew app:bundleRelease

성공하면 결과물은 다음 경로에 생성됩니다.

android/app/build/outputs/bundle/release/app-release.aab

6. AAB 서명 확인

업로드 전에 release 키로 서명됐는지 확인합니다. 아래 명령은 파일명을 상대 경로로 참조하므로, AAB 파일이 있는 폴더로 이동한 뒤 실행합니다.

서명 확인
# app-release.aab가 있는 폴더로 이동
cd android/app/build/outputs/bundle/release
 
keytool -printcert -jarfile app-release.aab

다른 폴더에서 실행하려면 app-release.aab 대신 전체 경로 (android/app/build/outputs/bundle/release/app-release.aab)를 넣어야 합니다.

출력의 CN 값을 확인합니다.

  • ❌ CN=Android Debug, O=Android, C=US → debug 키로 서명된 상태 (에러 2 미해결)
  • ✅ keystore 생성 때 입력한 본인 조직 정보(CN) → 정상

debug가 아니라 본인이 입력한 CN이 나와야 Play 업로드에서 거부되지 않습니다.

7. Play Console 내부 테스트 배포

빌드/서명이 정리되면 Play Console에서 배포를 진행합니다.

7-1. 개발자 계정 등록

  • Google Play 개발자 계정 등록 ($25 1회 결제, 이후 추가 비용 없음)

7-2. 앱 생성 & 앱 콘텐츠 설정

  • Play Console에서 앱 생성
  • 앱 콘텐츠 섹션 작성: 개인정보처리방침 URL, 데이터 보안(Data safety), 광고 포함 여부, 콘텐츠 등급 등
  • 내부 테스트만 하더라도 이 항목들이 채워져 있어야 트랙 진행이 원활합니다.

7-3. 내부 테스트 트랙에 AAB 업로드

  • 테스트 → 내부 테스트(Internal testing) 트랙에 app-release.aab 업로드

7-4. 테스터 등록 & 옵트인 링크 공유

  • 테스터 이메일 그룹을 만들어 등록
  • 생성된 옵트인(opt-in) 링크를 테스터에게 공유

7-5. 테스터 설치

  • 테스터가 옵트인 링크 접속 → 테스트 참여 동의
  • 이후 제공되는 Play 스토어 링크로 앱 설치

이렇게 내부 테스트 트랙 배포까지 완료됩니다.

정리

  • npx expo prebuild --platform android로 android/ 생성
  • keytool로 release keystore 생성
    • 마지막 확인 프롬프트 기본값이 [아니오] → 예를 직접 입력
  • gradle.properties에 MYAPP_UPLOAD_* 4개 등록
  • app/build.gradle
    • signingConfigs.release에는 키 정보만 (여기서 signingConfig() 호출 시 에러 1)
    • buildTypes.release의 signingConfig를 debug → release로 변경 (안 하면 에러 2)
  • ./gradlew clean && ./gradlew app:bundleRelease
  • keytool -printcert -jarfile app-release.aab로 CN이 debug가 아닌지 확인
  • Play Console: 개발자 등록($25) → 앱 생성/앱 콘텐츠 → 내부 테스트 업로드 → 테스터 옵트인

두 에러 모두 release 서명 설정을 정의해두고 정작 release 빌드가 그것을 참조하지 않아 발생하는 문제입니다. 이 두 지점만 정확히 챙기면 EAS 없이도 로컬 빌드로 내부 테스트 배포를 완료할 수 있습니다.


다음글

GitHub Pages에 GitHub Action으로 React와 Vite 배포 자동화 (CI/CD)


관련 태그

  • expo
  • react-native
  • android
  • play-console
  • deploy