Today's

길을 나서지 않으면 그 길에서 만날 수 있는 사람을 만날 수 없다

모바일 앱(안드로이드)

🦾 Android | 하단 바 + Navigation Compose + 보안 키 주입(ResValue) 적용기

Billcorea 2025. 11. 23. 15:47
반응형

🦾 Android | 하단 바 + Navigation Compose + 보안 키 주입(ResValue) 적용기

하단바 만들기 예제

개요 (Intro)

  • 오늘의 목표 / 배경: 앱에 하단 바를 도입하고 Compose Navigation으로 홈/설정/광고 탭을 구성. 외부 API 키를 local.properties에서 안전하게 읽어 리소스로 주입.
  • 어떤 문제를 해결하려 했는지: Gradle Kotlin DSL에서 local.properties 로딩 시 IDE 경고/오류, 네비게이션 구성 시 일부 import 누락 및 경고.
  • 사용한 기술 스택: Kotlin, Jetpack Compose, Navigation-Compose, Hilt, Gradle Kotlin DSL
📅 날짜: 2025.11.23
🎯 목표: 바텀 네비게이션 3탭(홈/설정/광고) + 키 주입(resValue) + Gradle DSL 정리
🧰 기술: Kotlin, Compose, Navigation, Hilt, Gradle Kotlin DSL

문제 정의 (Problem / Motivation)

  • local.properties 값을 build.gradle.kts에서 java.util.Properties로 직접 로딩 시 IDE가 Unresolved reference: util, load 등 오탐 경고를 표시.
  • Compose 네비게이션 구현 중, Modifier.padding(innerPadding) 관련 import 누락으로 Unresolved reference 'padding' 오류.
  • 하단 바와 NavHost를 연결하는 구조에서 패키지 경로, 아이콘 import, 경고(예: hiltViewModel deprecate 알림) 확인 필요.
// (이슈 예시) build.gradle.kts에서 직접 Properties 로딩 시 IDE 경고 발생 가능
val localProps = java.util.Properties().apply {
    val file = rootProject.file("local.properties")
    if (file.exists()) file.inputStream().use { load(it) } // load 참조 경고/오류 표기 사례
}
val cupangAccessKey = localProps.getProperty("cupangAccessKey") ?: ""

해결 과정 (How I Solved It)

  • local.properties 로딩은 Gradle의 providers.gradleProperty API로 대체하여 IDE/Gradle 모두에서 안정적으로 동작하도록 변경.
  • 앱 모듈의 defaultConfig에서 resValue로 문자열 리소스로 주입.
  • 하단 바 + NavHost 구조를 분리 파일로 구성하고, 필요한 Compose import를 명시하여 컴파일 오류 제거.
// app/build.gradle.kts (발췌) — Gradle providers API 사용
val cupangAccessKey: String = providers.gradleProperty("cupangAccessKey").orNull ?: ""
val cupangSecretKey: String = providers.gradleProperty("cupangSecretKey").orNull ?: ""

android {
    defaultConfig {
        resValue("string", "cupang_access_key", cupangAccessKey)
        resValue("string", "cupang_secret_key", cupangSecretKey)
    }
}
// 하단 바 + 네비게이션 (발췌)
sealed class AppScreen(val route: String, val label: String, val icon: ImageVector) {
    data object Home: AppScreen("home", "홈", Icons.Filled.Home)
    data object Settings: AppScreen("settings", "설정", Icons.Filled.Settings)
    data object Ads: AppScreen("ads", "광고", Icons.Filled.Campaign)
}

@Composable
fun AppNavHost(navController: NavHostController, viewModel: HealthConnectViewModel = hiltViewModel()) {
    NavHost(navController = navController, startDestination = AppScreen.Home.route) {
        composable(AppScreen.Home.route) { MainScreen(viewModel) }
        composable(AppScreen.Settings.route) { SettingsScreen() }
        composable(AppScreen.Ads.route) { AdsScreen() }
    }
}

@Composable
fun AppScaffoldWithBottomBar() {
    val navController = rememberNavController()
    Scaffold(bottomBar = { BottomBar(navController) }) { innerPadding ->
        Box(modifier = Modifier.padding(innerPadding)) { AppNavHost(navController) }
    }
}

결과 (Result)

  • 하단 바 3탭(홈/설정/광고) + NavHost 라우팅이 정상 작동.
  • local.propertiescupangAccessKey/cupangSecretKeyR.string으로 노출, 화면/Compose에서 getString으로 참조 가능.
  • Gradle Kotlin DSL의 IDE 경고를 줄이고, 스크립트 단순화로 유지보수성 개선.
✅ 바텀 네비게이션 안정화 및 화면 전환 확인
🔐 키 주입(resValue) 동작 확인, 보안 노출 리스크는 추후 서버 프록시로 추가 보완 예정
🧹 Gradle DSL 경고 제거로 개발 경험 개선

느낀 점 / 회고 (Reflection)

  • Gradle 스크립트에서 표준 API를 직접 다루기보다는 Gradle 제공 API를 활용하는 편이 IDE/빌드 모두에 일관적.
  • 네비게이션은 파일 분리(화면/바/호스트)로 가독성이 크게 좋아짐.
  • 민감 키는 최종적으로 서버 서명/프록시로 이동하는 게 안전. 일단은 resValue로 편의 제공.

참고자료 (References)

반응형