Conversation
Walkthrough이번 변경에서는 Android 프로젝트의 debug와 release 빌드 환경을 명확히 분리하도록 빌드 스크립트와 관련 리소스, 설정 파일이 수정되었습니다. keystore 관리, 앱 이름 및 패키지명, 서명 설정, 문자열 리소스가 빌드 타입에 따라 분리 적용되도록 구성되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Developer
participant Gradle
participant Keystore
participant Manifest
participant Resources
Developer->>Gradle: 빌드 실행 (debug/release)
Gradle->>Keystore: keystore.properties 로드 (release 시)
Gradle->>Manifest: appName 플레이스홀더 설정 (debug: app_name_dev, release: app_name)
Gradle->>Resources: strings.xml에서 해당 앱 이름 리소스 적용
Manifest->>Gradle: 앱 라벨에 적용
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes(해당 변경사항 내에서 linked issue(#106)와 무관한 기능적 코드 변경은 발견되지 않았습니다.) Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
app/src/main/res/values/strings.xml (1)
1-4:translatable="false"속성 누락앱 이름은 현 시점에서 다국어 번역 대상이 아니므로 번들 크기를 줄이고 번역 파일 노이즈를 방지하기 위해
translatable="false"를 명시해두는 것을 권장합니다.- <string name="app_name">Reed</string> - <string name="app_name_dev">Reed.dev</string> + <string name="app_name" translatable="false">Reed</string> + <string name="app_name_dev" translatable="false">Reed.dev</string>app/build.gradle.kts (2)
28-35:debug빌드 설정 중복 표시
isDebuggable = true는 이미 Gradle 기본값입니다. 필요 없는 설정은 제거하여 스크립트 가독성을 높일 수 있습니다.
102-104: API Key 로딩 함수, 공백·줄바꿈 처리 확인 필요
gradleLocalProperties에서 읽은 값이 개행이나 공백을 포함할 경우 런타임 오류가 발생할 수 있습니다.trim()추가 여부를 검토해주세요.
(현재manifestPlaceholders에서는trim('"')처리로 안전하지만buildConfigField에는 그대로 전달됩니다.)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
.gitignore(1 hunks)app/build.gradle.kts(2 hunks)app/src/main/AndroidManifest.xml(1 hunks)app/src/main/res/values/strings.xml(1 hunks)core/designsystem/src/main/res/values/strings.xml(0 hunks)
💤 Files with no reviewable changes (1)
- core/designsystem/src/main/res/values/strings.xml
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: easyhooon
PR: YAPP-Github/Reed-Android#88
File: core/model/src/main/kotlin/com/ninecraft/booket/core/model/EmotionModel.kt:11-18
Timestamp: 2025-07-31T16:58:59.404Z
Learning: Reed-Android 프로젝트는 현재 다국어 지원 계획이 없어서 모델에 한글 문자열을 직접 포함하는 것이 허용된다.
📚 Learning: reed-android 프로젝트는 현재 다국어 지원 계획이 없어서 모델에 한글 문자열을 직접 포함하는 것이 허용된다....
Learnt from: easyhooon
PR: YAPP-Github/Reed-Android#88
File: core/model/src/main/kotlin/com/ninecraft/booket/core/model/EmotionModel.kt:11-18
Timestamp: 2025-07-31T16:58:59.404Z
Learning: Reed-Android 프로젝트는 현재 다국어 지원 계획이 없어서 모델에 한글 문자열을 직접 포함하는 것이 허용된다.
Applied to files:
app/src/main/res/values/strings.xml
📚 Learning: reed-android 프로젝트에서 core:model 모듈은 순수 kotlin 모듈이므로 android 리소스(r.string 등)에 접근할 수 없다....
Learnt from: easyhooon
PR: YAPP-Github/Reed-Android#88
File: core/model/src/main/kotlin/com/ninecraft/booket/core/model/EmotionModel.kt:11-18
Timestamp: 2025-07-31T16:58:59.404Z
Learning: Reed-Android 프로젝트에서 core:model 모듈은 순수 Kotlin 모듈이므로 Android 리소스(R.string 등)에 접근할 수 없다.
Applied to files:
app/src/main/res/values/strings.xml
📚 Learning: reed-android 프로젝트에서는 api가 준비되지 않은 상황에서 ui를 먼저 구현하고, api 연동 시점에 하드코딩된 데이터를 실제 데이터로 교체하는 개발 방식을 사용한다. ...
Learnt from: easyhooon
PR: YAPP-Github/Reed-Android#88
File: feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt:29-37
Timestamp: 2025-07-31T23:17:40.054Z
Learning: Reed-Android 프로젝트에서는 API가 준비되지 않은 상황에서 UI를 먼저 구현하고, API 연동 시점에 하드코딩된 데이터를 실제 데이터로 교체하는 개발 방식을 사용한다. RecordItem 컴포넌트의 emotionTags 매개변수도 API 연동 시점에 `text = emotionTags.joinToString(separator = "·") { "#$it" }`로 적용될 예정이다.
Applied to files:
app/src/main/res/values/strings.xml
📚 Learning: reed android 프로젝트에서 타이포그래피 사용 규칙: 톱 앱바(top app bar)에서는 `headline2semibold`를 사용하고, 바텀시트(bottom sheet)...
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#45
File: core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/component/appbar/ReedTopAppBar.kt:65-65
Timestamp: 2025-07-12T01:33:57.101Z
Learning: Reed Android 프로젝트에서 타이포그래피 사용 규칙: 톱 앱바(Top App Bar)에서는 `headline2SemiBold`를 사용하고, 바텀시트(Bottom Sheet)에서는 `heading2SemiBold`를 사용한다. 이는 의도적인 디자인 시스템 차별화이다.
Applied to files:
app/src/main/res/values/strings.xml
📚 Learning: reed android 프로젝트에서는 다크모드/라이트모드 대응 계획이 없고 기본 테마 값만 사용할 예정이다....
Learnt from: seoyoon513
PR: YAPP-Github/Reed-Android#32
File: core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Theme.kt:15-21
Timestamp: 2025-07-08T03:21:24.693Z
Learning: Reed Android 프로젝트에서는 다크모드/라이트모드 대응 계획이 없고 기본 테마 값만 사용할 예정이다.
Applied to files:
app/src/main/res/values/strings.xml
📚 Learning: reed-android 프로젝트에서는 `booket.android.feature` convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 p...
Learnt from: easyhooon
PR: YAPP-Github/Reed-Android#61
File: feature/webview/build.gradle.kts:17-21
Timestamp: 2025-07-20T12:34:23.786Z
Learning: Reed-Android 프로젝트에서는 `booket.android.feature` convention plugin을 사용하여 feature 모듈들의 공통 의존성을 관리한다. 이 plugin은 Circuit, Compose, 그리고 core 모듈들의 의존성을 자동으로 포함하므로, 각 feature 모듈의 build.gradle.kts에서는 특별한 의존성(예: libs.logger, libs.kakao.auth)만 별도로 선언하면 된다.
Applied to files:
app/build.gradle.kts
📚 Learning: the project uses kotlinx serialization with json configuration that includes `ignoreunknownkeys = tr...
Learnt from: easyhooon
PR: YAPP-Github/Reed-Android#46
File: core/network/src/main/kotlin/com/ninecraft/booket/core/network/response/BookSearchResponse.kt:33-44
Timestamp: 2025-07-14T00:51:38.952Z
Learning: The project uses Kotlinx Serialization with JSON configuration that includes `ignoreUnknownKeys = true`, `encodeDefaults = true`, `isLenient = true`, and `prettyPrint = true` to handle API response parsing robustly, making additional null safety measures less critical if the API consistently provides all expected fields.
Applied to files:
app/build.gradle.kts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: ci-build
🔇 Additional comments (3)
.gitignore (1)
30-33:keystore.propertiesignore 추가 👍릴리스 서명 정보가 담긴
keystore.properties를 VCS 추적 대상에서 제외한 결정은 보안·컴플라이언스 측면에서 적절합니다.
더 이상 조치할 사항 없습니다.app/src/main/AndroidManifest.xml (1)
18-18: 빌드 타입별 앱 이름 플레이스홀더 적용 확인 완료
${appName}플레이스홀더 도입으로 Debug/Release 환경 분리가 잘 반영되었습니다. 빌드 스크립트에서도 두 타입 모두에 매핑이 정의돼 있어 누락 위험이 없습니다.app/build.gradle.kts (1)
36-44:manifestPlaceholders +=사용 시 초기화 순서 주의현재는 정상 동작하지만, 빌드 스크립트의 다른 플러그인(예: Firebase Crashlytics)이
manifestPlaceholders에 쓰기 전에 실행될 경우 덮어쓰기 위험이 있습니다. 명확성을 위해manifestPlaceholders = mapOf(...)로 지정하거나putAll호출을 권장합니다.
| signingConfigs { | ||
| create("release") { | ||
| val propertiesFile = rootProject.file("keystore.properties") | ||
| val properties = Properties() | ||
| properties.load(propertiesFile.inputStream()) | ||
| storeFile = rootProject.file(properties["STORE_FILE"] as String) | ||
| storePassword = properties["STORE_PASSWORD"] as String | ||
| keyAlias = properties["KEY_ALIAS"] as String | ||
| keyPassword = properties["KEY_PASSWORD"] as String | ||
| } | ||
| } |
There was a problem hiding this comment.
keystore.properties 존재 여부 미검사 → CI 빌드 실패 가능성
rootProject.file("keystore.properties")가 존재하지 않는 환경(예: PR CI, 외부 컨트리뷰터)에서 inputStream() 호출 시 FileNotFoundException으로 빌드가 즉시 실패합니다.
파일 부재 시 디버그·스냅샷 빌드는 서명 없이 통과하도록 가드 로직을 넣어주세요.
-val propertiesFile = rootProject.file("keystore.properties")
-val properties = Properties()
-properties.load(propertiesFile.inputStream())
+val propertiesFile = rootProject.file("keystore.properties")
+if (!propertiesFile.exists()) {
+ logger.warn("⚠️ keystore.properties not found – skipping release signing config.")
+ return@create // signingConfig.release 생성 중단
+}
+val properties = Properties().apply {
+ propertiesFile.inputStream().use { load(it) }
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| signingConfigs { | |
| create("release") { | |
| val propertiesFile = rootProject.file("keystore.properties") | |
| val properties = Properties() | |
| properties.load(propertiesFile.inputStream()) | |
| storeFile = rootProject.file(properties["STORE_FILE"] as String) | |
| storePassword = properties["STORE_PASSWORD"] as String | |
| keyAlias = properties["KEY_ALIAS"] as String | |
| keyPassword = properties["KEY_PASSWORD"] as String | |
| } | |
| } | |
| signingConfigs { | |
| create("release") { | |
| val propertiesFile = rootProject.file("keystore.properties") | |
| if (!propertiesFile.exists()) { | |
| logger.warn("⚠️ keystore.properties not found – skipping release signing config.") | |
| return@create | |
| } | |
| val properties = Properties().apply { | |
| propertiesFile.inputStream().use { load(it) } | |
| } | |
| storeFile = rootProject.file(properties["STORE_FILE"] as String) | |
| storePassword = properties["STORE_PASSWORD"] as String | |
| keyAlias = properties["KEY_ALIAS"] as String | |
| keyPassword = properties["KEY_PASSWORD"] as String | |
| } | |
| } |
🤖 Prompt for AI Agents
In app/build.gradle.kts around lines 15 to 25, the code assumes the
keystore.properties file always exists, causing a build failure if it is
missing. Add a check to verify if the keystore.properties file exists before
loading it. If the file is absent, skip the signing configuration to allow debug
and snapshot builds to proceed without signing, preventing CI build failures in
environments without the file.
| storeFile = rootProject.file(properties["STORE_FILE"] as String) | ||
| storePassword = properties["STORE_PASSWORD"] as String | ||
| keyAlias = properties["KEY_ALIAS"] as String | ||
| keyPassword = properties["KEY_PASSWORD"] as String | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
NPE 위험: 프로퍼티 강제 캐스팅
properties["STORE_FILE"] as String 식은 키 누락 시 NullPointerException을 유발합니다. 안전한 프로퍼티 조회로 변경해 주세요.
-storeFile = rootProject.file(properties["STORE_FILE"] as String)
-storePassword = properties["STORE_PASSWORD"] as String
-keyAlias = properties["KEY_ALIAS"] as String
-keyPassword = properties["KEY_PASSWORD"] as String
+storeFile = rootProject.file(requireNotNull(properties["STORE_FILE"]) { "STORE_FILE missing" } as String)
+storePassword = requireNotNull(properties["STORE_PASSWORD"]) { "STORE_PASSWORD missing" } as String
+keyAlias = requireNotNull(properties["KEY_ALIAS"]) { "KEY_ALIAS missing" } as String
+keyPassword = requireNotNull(properties["KEY_PASSWORD"]) { "KEY_PASSWORD missing" } as String📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| storeFile = rootProject.file(properties["STORE_FILE"] as String) | |
| storePassword = properties["STORE_PASSWORD"] as String | |
| keyAlias = properties["KEY_ALIAS"] as String | |
| keyPassword = properties["KEY_PASSWORD"] as String | |
| } | |
| storeFile = rootProject.file(requireNotNull(properties["STORE_FILE"]) { "STORE_FILE missing" } as String) | |
| storePassword = requireNotNull(properties["STORE_PASSWORD"]) { "STORE_PASSWORD missing" } as String | |
| keyAlias = requireNotNull(properties["KEY_ALIAS"]) { "KEY_ALIAS missing" } as String | |
| keyPassword = requireNotNull(properties["KEY_PASSWORD"]) { "KEY_PASSWORD missing" } as String |
🤖 Prompt for AI Agents
In app/build.gradle.kts around lines 20 to 24, the code uses forced casting like
properties["STORE_FILE"] as String, which can cause a NullPointerException if
the key is missing. Change these to safely retrieve the properties by using safe
calls or providing default values, for example by using
properties.get("STORE_FILE")?.toString() or checking for null before assignment
to avoid runtime exceptions.
요건 노션 어느 페이지에서 확인할 수 있나요?? |
방금 올렸어염 |
# Conflicts: # .github/workflows/android-ci.yml
|
@seoyoon513 dev, release 앱을 분리하면서 google-services.json 도 업데이트 되었슴다.(.dev android_client_info 추가) 노션에 업데이트해두었으니 프로젝트 app 모듈에 있는 파일 업데이트 부탁함다 |
🔗 관련 이슈
📙 작업 설명
🧪 테스트 내역 (선택)
📸 스크린샷 또는 시연 영상 (선택)
💬 추가 설명 or 리뷰 포인트 (선택)
Summary by CodeRabbit
새로운 기능
버그 수정
문서화