From 619c21f8165489182a31cfb381448de25e813caa Mon Sep 17 00:00:00 2001 From: Sadturtleman Date: Fri, 23 Oct 2026 16:38:00 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat(app):=20Meta=20=EC=95=B1=20=EC=9D=B4?= =?UTF-8?q?=EB=B2=A4=ED=8A=B8=EC=9A=A9=20facebook-core=20=EB=A5=BC=20?= =?UTF-8?q?=EB=B6=99=EC=9D=B8=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - facebook-core 19.0.0 추가. 로그인·공유 모듈은 쓰지 않아 키 해시는 등록하지 않는다. - FACEBOOK_APP_ID·FACEBOOK_CLIENT_TOKEN 을 local.properties 에서 읽어 resValue 문자열 리소스로 주입하고, 매니페스트 meta-data(com.facebook.sdk.ApplicationId·ClientToken)가 @string 으로 참조한다. placeholder 로 넣으면 숫자 앱 ID 가 숫자로 파싱되어 SDK 가 읽지 못한다. - 앱 이벤트 자동 로깅·광고 ID 수집은 기본값(켜짐) 그대로 둔다. 최종 매니페스트에 AD_ID 권한이 들어간다. - 키가 비면 SDK 자동 초기화가 실패를 로그로만 남기고 앱은 그대로 뜬다. Refs #631 Co-Authored-By: Claude Opus 5.5 (1M context) --- CLAUDE.md | 2 +- app/build.gradle.kts | 9 +++++++++ app/src/main/AndroidManifest.xml | 8 ++++++++ gradle/libs.versions.toml | 5 +++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 546a7896..f61b0d26 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -33,7 +33,7 @@ JDK 21. Gradle wrapper 사용(`./gradlew`). CI(`.github/workflows/`)는 `assembl ## 빌드에 필요한 로컬 설정 - `local.properties` 키 → `app/build.gradle.kts` 가 `BuildConfig`·manifestPlaceholder 로 주입한다: - `BASE_URL`(Retrofit base, `@BaseUrl`), `KAKAO_NATIVE_APP_KEY`, `KAKAO_REST_API_KEY`, `KAKAO_REDIRECT_URI`, `GOOGLE_CLIENT_ID`, `GOOGLE_REDIRECT_URI`(스킴 부분이 AppAuth redirect 로 쓰임), `AMPLITUDE_API_KEY`, `TTI_SHEET_URL`(TTI 를 받는 구글 시트 Apps Script 웹앱). + `BASE_URL`(Retrofit base, `@BaseUrl`), `KAKAO_NATIVE_APP_KEY`, `KAKAO_REST_API_KEY`, `KAKAO_REDIRECT_URI`, `GOOGLE_CLIENT_ID`, `GOOGLE_REDIRECT_URI`(스킴 부분이 AppAuth redirect 로 쓰임), `AMPLITUDE_API_KEY`, `TTI_SHEET_URL`(TTI 를 받는 구글 시트 Apps Script 웹앱), `FACEBOOK_APP_ID`·`FACEBOOK_CLIENT_TOKEN`(Meta SDK, `resValue` 문자열 리소스로 주입). 값이 비면 빈 문자열로 주입될 뿐 빌드는 통과한다 — 런타임에 조용히 죽으므로 증상이 나오면 여기부터 본다. - `app/google-services.json` 은 커밋하지 않는다. 파일이 **있을 때만** google-services·Crashlytics 플러그인이 적용된다(`app/build.gradle.kts` 상단 조건부 apply). CI 는 시크릿에서 복원한다. - 버전은 전부 `gradle/libs.versions.toml` 버전 카탈로그. 동적 버전(`1.+`)은 쓰지 않는다. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5048bb8c..848232e7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -28,6 +28,8 @@ val kakaoNativeAppKey: String = localProperties.getProperty("KAKAO_NATIVE_APP_KE val baseUrl: String = localProperties.getProperty("BASE_URL")?.trim().orEmpty() val amplitudeApiKey: String = localProperties.getProperty("AMPLITUDE_API_KEY")?.trim().orEmpty() val ttiSheetUrl: String = localProperties.getProperty("TTI_SHEET_URL")?.trim().orEmpty() +val facebookAppId: String = localProperties.getProperty("FACEBOOK_APP_ID")?.trim().orEmpty() +val facebookClientToken: String = localProperties.getProperty("FACEBOOK_CLIENT_TOKEN")?.trim().orEmpty() val appAuthRedirectScheme: String = localProperties .getProperty("GOOGLE_REDIRECT_URI") @@ -88,6 +90,9 @@ android { buildConfigField("String", "AMPLITUDE_API_KEY", "\"$amplitudeApiKey\"") // TTI 를 받는 구글 시트 Apps Script 웹앱 URL. 비면 보내지 않는다(#623) buildConfigField("String", "TTI_SHEET_URL", "\"$ttiSheetUrl\"") + // Meta SDK 는 숫자 앱 ID 를 meta-data 문자열 리소스로 읽어야 한다 — placeholder 로 넣으면 숫자로 파싱된다 + resValue("string", "facebook_app_id", facebookAppId) + resValue("string", "facebook_client_token", facebookClientToken) } signingConfigs { @@ -127,6 +132,7 @@ android { buildFeatures { compose = true buildConfig = true + resValues = true } } @@ -211,6 +217,9 @@ dependencies { implementation(libs.firebase.messaging) implementation(libs.firebase.perf) + // Meta 앱 이벤트(광고 성과 측정). 로그인·공유 모듈은 쓰지 않는다. + implementation(libs.facebook.core) + // 프레임 jank 측정(JankStats). implementation(libs.androidx.metrics.performance) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index de2fd175..17521da4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -122,6 +122,14 @@ android:value="androidx.startup" tools:node="remove" /> + + + + \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b8f650fa..41452380 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -72,6 +72,9 @@ zxing = "3.5.3" # Amplitude amplitudeAnalytics = "1.30.1" +# Meta 앱 이벤트 +facebookCore = "19.0.0" + # firebase googleservice = "4.4.4" firebaseCrashlyticsPlugin = "3.0.6" @@ -187,6 +190,8 @@ zxing-core = { module = "com.google.zxing:core", version.ref = "zxing" } # amplitude amplitude-analytics = { group = "com.amplitude", name = "analytics-android", version.ref = "amplitudeAnalytics" } +# Meta 앱 이벤트 +facebook-core = { group = "com.facebook.android", name = "facebook-core", version.ref = "facebookCore" } # firebase firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebaseBom" } From d5c1884b117709044078c8c1a54e45eafc0bf6c7 Mon Sep 17 00:00:00 2001 From: Sadturtleman Date: Fri, 23 Oct 2026 16:46:34 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat(app):=20debug=20=EB=B9=8C=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=8A=A4=ED=86=A0=EC=96=B4=20=EC=95=B1=EA=B3=BC=20?= =?UTF-8?q?=ED=95=9C=20=EA=B8=B0=EA=B8=B0=EC=97=90=20=EA=B0=99=EC=9D=B4=20?= =?UTF-8?q?=EC=84=A4=EC=B9=98=ED=95=A0=20=EC=88=98=20=EC=9E=88=EA=B2=8C=20?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - debug 빌드타입에 applicationIdSuffix ".debug" 를 붙여 패키지명을 com.ruleup.android_ruleup.debug 로 가른다. - debug 앱 이름을 「ruleup debug」로 바꿔 런처에서 구분한다(src/debug/res). - Firebase(ruleup-5e41e)에 debug 앱을 등록했다. google-services.json 은 커밋하지 않으므로 로컬·CI 시크릿 모두 두 패키지가 담긴 새 파일로 바꿔야 debug 빌드가 통과한다. Refs #632 Co-Authored-By: Claude Opus 5.5 (1M context) --- app/build.gradle.kts | 4 ++++ app/src/debug/res/values/strings.xml | 5 +++++ 2 files changed, 9 insertions(+) create mode 100644 app/src/debug/res/values/strings.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5048bb8c..82608889 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -102,6 +102,10 @@ android { } buildTypes { + // 스토어 앱과 한 기기에 같이 설치되도록 패키지명을 가른다 + debug { + applicationIdSuffix = ".debug" + } release { // 자격 증명이 없으면 null signingConfig = signingConfigs.findByName("release") diff --git a/app/src/debug/res/values/strings.xml b/app/src/debug/res/values/strings.xml new file mode 100644 index 00000000..9abfbb81 --- /dev/null +++ b/app/src/debug/res/values/strings.xml @@ -0,0 +1,5 @@ + + + + ruleup debug + From b155d40617b999d68fe4181885ca5f2293972f16 Mon Sep 17 00:00:00 2001 From: Sadturtleman Date: Fri, 23 Oct 2026 17:03:58 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat(app):=20debug=20=EB=B9=8C=EB=93=9C?= =?UTF-8?q?=EB=8A=94=20debug=20=ED=8C=A8=ED=82=A4=EC=A7=80=EA=B0=80=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=EB=90=9C=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=ED=8B=B0=EB=B8=8C=20=ED=82=A4=EB=A5=BC=20?= =?UTF-8?q?=EC=93=B4=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 카카오 콘솔은 네이티브 앱 키 하나에 Android 패키지명을 하나만 등록받는다. .debug 패키지용 키(Debug Native AppKey)를 따로 만들었으므로 debug 빌드는 KAKAO_NATIVE_APP_KEY_DEBUG 를 쓴다(app·onboarding:presentation 양쪽 — 매니페스트 스킴과 BuildConfig). 값이 비면 기존 키로 대체해 빌드는 깨지지 않는다. 키가 달라지면서 debug 앱의 카카오 redirect 스킴도 kakao{debug키} 로 갈려, 스토어 앱과 함께 설치돼도 카카오 계정 로그인 복귀가 엉키지 않는다. Refs #632 Co-Authored-By: Claude Opus 5.5 (1M context) --- CLAUDE.md | 2 +- app/build.gradle.kts | 9 +++++++++ onboarding/presentation/build.gradle.kts | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 546a7896..78242508 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -33,7 +33,7 @@ JDK 21. Gradle wrapper 사용(`./gradlew`). CI(`.github/workflows/`)는 `assembl ## 빌드에 필요한 로컬 설정 - `local.properties` 키 → `app/build.gradle.kts` 가 `BuildConfig`·manifestPlaceholder 로 주입한다: - `BASE_URL`(Retrofit base, `@BaseUrl`), `KAKAO_NATIVE_APP_KEY`, `KAKAO_REST_API_KEY`, `KAKAO_REDIRECT_URI`, `GOOGLE_CLIENT_ID`, `GOOGLE_REDIRECT_URI`(스킴 부분이 AppAuth redirect 로 쓰임), `AMPLITUDE_API_KEY`, `TTI_SHEET_URL`(TTI 를 받는 구글 시트 Apps Script 웹앱). + `BASE_URL`(Retrofit base, `@BaseUrl`), `KAKAO_NATIVE_APP_KEY`, `KAKAO_NATIVE_APP_KEY_DEBUG`(debug 빌드 전용, `.debug` 패키지가 등록된 키 — 비면 위 키로 대체), `KAKAO_REST_API_KEY`, `KAKAO_REDIRECT_URI`, `GOOGLE_CLIENT_ID`, `GOOGLE_REDIRECT_URI`(스킴 부분이 AppAuth redirect 로 쓰임), `AMPLITUDE_API_KEY`, `TTI_SHEET_URL`(TTI 를 받는 구글 시트 Apps Script 웹앱). 값이 비면 빈 문자열로 주입될 뿐 빌드는 통과한다 — 런타임에 조용히 죽으므로 증상이 나오면 여기부터 본다. - `app/google-services.json` 은 커밋하지 않는다. 파일이 **있을 때만** google-services·Crashlytics 플러그인이 적용된다(`app/build.gradle.kts` 상단 조건부 apply). CI 는 시크릿에서 복원한다. - 버전은 전부 `gradle/libs.versions.toml` 버전 카탈로그. 동적 버전(`1.+`)은 쓰지 않는다. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 82608889..34ebb7a6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -25,6 +25,13 @@ val localProperties = } val kakaoNativeAppKey: String = localProperties.getProperty("KAKAO_NATIVE_APP_KEY")?.trim().orEmpty() + +// 카카오는 네이티브 앱 키 하나에 패키지명 하나만 등록되므로 debug 패키지는 전용 키를 쓴다(#632) +val kakaoNativeAppKeyDebug: String = + localProperties + .getProperty("KAKAO_NATIVE_APP_KEY_DEBUG") + ?.trim() + ?.takeIf { it.isNotEmpty() } ?: kakaoNativeAppKey val baseUrl: String = localProperties.getProperty("BASE_URL")?.trim().orEmpty() val amplitudeApiKey: String = localProperties.getProperty("AMPLITUDE_API_KEY")?.trim().orEmpty() val ttiSheetUrl: String = localProperties.getProperty("TTI_SHEET_URL")?.trim().orEmpty() @@ -105,6 +112,8 @@ android { // 스토어 앱과 한 기기에 같이 설치되도록 패키지명을 가른다 debug { applicationIdSuffix = ".debug" + manifestPlaceholders["KAKAO_NATIVE_APP_KEY"] = kakaoNativeAppKeyDebug + buildConfigField("String", "KAKAO_NATIVE_APP_KEY", "\"$kakaoNativeAppKeyDebug\"") } release { // 자격 증명이 없으면 null diff --git a/onboarding/presentation/build.gradle.kts b/onboarding/presentation/build.gradle.kts index 90031e6e..fb3d9281 100644 --- a/onboarding/presentation/build.gradle.kts +++ b/onboarding/presentation/build.gradle.kts @@ -16,6 +16,13 @@ val localProperties = } val kakaoNativeAppKey: String = localProperties.getProperty("KAKAO_NATIVE_APP_KEY")?.trim().orEmpty() + +// 카카오는 네이티브 앱 키 하나에 패키지명 하나만 등록되므로 debug 패키지는 전용 키를 쓴다(#632) +val kakaoNativeAppKeyDebug: String = + localProperties + .getProperty("KAKAO_NATIVE_APP_KEY_DEBUG") + ?.trim() + ?.takeIf { it.isNotEmpty() } ?: kakaoNativeAppKey val googleClientId: String = localProperties.getProperty("GOOGLE_CLIENT_ID")?.trim().orEmpty() val googleRedirectUri: String = localProperties.getProperty("GOOGLE_REDIRECT_URI")?.trim().orEmpty() val kakaoRestApiKey: String = localProperties.getProperty("KAKAO_REST_API_KEY")?.trim().orEmpty() @@ -38,6 +45,13 @@ android { buildConfigField("String", "KAKAO_REDIRECT_URI", "\"$kakaoRedirectUri\"") } + buildTypes { + debug { + manifestPlaceholders["KAKAO_NATIVE_APP_KEY"] = kakaoNativeAppKeyDebug + buildConfigField("String", "KAKAO_NATIVE_APP_KEY", "\"$kakaoNativeAppKeyDebug\"") + } + } + compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11