Skip to content

[Refactor/#200] Gradle 설정 최신화 및 앱 버전 관리 아키텍처 개선#202

Merged
wjdrjs00 merged 7 commits intodevelopfrom
refactor/#200-gradle-modernization
Mar 25, 2026
Merged

[Refactor/#200] Gradle 설정 최신화 및 앱 버전 관리 아키텍처 개선#202
wjdrjs00 merged 7 commits intodevelopfrom
refactor/#200-gradle-modernization

Conversation

@wjdrjs00
Copy link
Member

@wjdrjs00 wjdrjs00 commented Mar 24, 2026

[ PR Content ]

Gradle 설정 최신화(8.10.1 → 9.1.0), Convention Plugin 구조 개선, 앱 버전 관리 아키텍처 개선을 진행했습니다..!

Related issue

Screenshot 📸

  • N/A

Work Description

Gradle 설정 최신화

  • compileSdk/targetSdk 35 → 36, AGP 8.10.1 → 9.1.0, Kotlin 2.1.20 → 2.3.0 등 버전 최신화

Convention Plugin 구조 개선

  • ApplicationId.kt 삭제 → Extensions.kt로 통합, namespace 자동 계산
  • KotlinSerializationPlugin, KotlinParcelizePlugin 분리
  • allprojects의 ktlint 적용 → 각 Plugin 내 명시적 적용으로 이전 (Configuration Cache 호환성 확보)
  • AppVersion: LibraryExtension 버전 BuildConfig 제거, ApplicationExtension 직접 전달

앱 버전 관리 아키텍처 개선

  • BuildConfig 접근을 app 모듈로 일원화
  • VersionNameProvider 구현체를 PackageManager 기반으로 교체 (app 모듈로 이동)
  • data, presentation 모듈에서 buildConfig = true 블록 제거

To Reviewers 📢

  • gradle 마이그레이션간 참고한 공식문서 자료입니다..!-> 공식문서, 공식문서2 궁금한사항이 있다면 리뷰나 질문 남겨주십쇼!

Summary by CodeRabbit

릴리스 노트

  • Chores
    • 빌드 툴·종속성 대규모 업데이트(Gradle, Kotlin, Hilt 등) 및 SDK target 36/그레이들 래퍼 업그레이드
    • 빌드/플러그인 구성 정리 및 새 플러그인(직렬화·Parcelize) 추가
  • Bug Fixes
    • 설치 위치를 내부 저장소 전용으로 고정하여 설치 동작 변경
    • Play 스토어 열기 로직을 런타임 패키지명으로 전환해 스토어 이동 신뢰성 개선
  • New Features
    • 앱 버전 정보 취득 방식 개선(런타임 기반 버전 제공)

- compileSdk/targetSdk 35 → 36
- AGP 8.10.1 → 9.1.0
- Kotlin 2.1.20 → 2.3.0, KSP 2.3.6
- Hilt 2.56.2 → 2.59.2
- Compose BOM 2025.06.00 → 2026.03.00
- 기타 AndroidX, Coroutines, Serialization 등 최신화
- ApplicationId.kt 삭제, Extensions.kt 추가하여 namespace 자동 계산 로직 통합
- KotlinSerializationPlugin, KotlinParcelizePlugin 신규 추가
- AppVersion: ApplicationExtension 파라미터 직접 전달 방식으로 변경,
  LibraryExtension의 불필요한 버전 BuildConfig 필드 제거
- ktlint를 allprojects 대신 각 convention plugin에서 적용하도록 이전
- 각 모듈 build.gradle.kts에서 namespace 명시 제거 (자동 계산으로 대체)
- AndroidApplicationVersionNameProvider 삭제 (BuildConfig 직접 참조 제거)
- PackageManagerVersionNameProvider 추가: PackageManager로 런타임에 버전명 조회
- AppVersionModule 추가: app BuildConfig의 버전 정수를 @nAmed로 제공
- VersionDataSourceImpl: BuildConfig 직접 참조 → @nAmed 주입 방식으로 변경
- PlayStoreUtils: BuildConfig.APPLICATION_ID → activity.packageName으로 변경
- data, presentation 모듈의 불필요한 buildConfig 블록 제거
androidx.hilt.navigation.compose.hiltViewModel →
androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
@wjdrjs00 wjdrjs00 requested a review from l5x5l March 24, 2026 11:04
@wjdrjs00 wjdrjs00 self-assigned this Mar 24, 2026
@wjdrjs00 wjdrjs00 added 🔨 Refactor 기존 기능 개선 🧤 대현 labels Mar 24, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5788bb39-5afe-46ad-93c0-d32682bee0a6

📥 Commits

Reviewing files that changed from the base of the PR and between 215b48e and 1f12e43.

📒 Files selected for processing (1)
  • app/src/main/AndroidManifest.xml
✅ Files skipped from review due to trivial changes (1)
  • app/src/main/AndroidManifest.xml

Walkthrough

앱 설치 위치를 internalOnly로 고정하고(매니페스트), 빌드툴·라이브러리 버전 업그레이드, Convention 플러그인 구조 재정비, 앱 모듈로 버전 정보 집중 및 DI 전환, hiltViewModel import 경로 통일 등의 빌드·DI 리팩터링이 적용되었습니다. (50 words)

Changes

Cohort / File(s) Summary
Manifest
app/src/main/AndroidManifest.xml
루트 <manifest>android:installLocation="internalOnly" 추가.
App DI / Version providers
app/src/main/java/com/threegap/bitnagil/di/data/AppVersionModule.kt, app/src/main/java/com/threegap/bitnagil/util/version/PackageManagerVersionNameProvider.kt, presentation/src/main/java/com/threegap/bitnagil/presentation/util/version/AndroidApplicationVersionNameProvider.kt (삭제), data/src/main/java/.../VersionDataSourceImpl.kt
앱 모듈에 AppVersionModule 추가하여 @Named으로 versionMajor/minor/patch 제공. 기존 BuildConfig 직접 참조(및 AndroidApplicationVersionNameProvider) 제거, 런타임 PackageManager 기반 VersionNameProvider 추가, 하위 모듈은 주입된 정수 사용하도록 변경.
Play Store utils
presentation/src/main/java/com/threegap/bitnagil/presentation/util/playstore/PlayStoreUtils.kt
BuildConfig.APPLICATION_ID 제거. 런타임 activity.packageName으로 패키지명 획득하고 인텐트 생성/호출에 전달하도록 변경.
hiltViewModel import 변경 (Compose screens & NavHost)
app/src/main/java/com/threegap/bitnagil/MainNavHost.kt, presentation/src/main/java/com/threegap/bitnagil/presentation/screen/*
androidx.hilt.navigation.compose.hiltViewModelandroidx.hilt.lifecycle.viewmodel.compose.hiltViewModel로 import 경로 일괄 변경(사용부는 동일).
Gradle 버전·라이브러리 업데이트
gradle/libs.versions.toml, gradle/wrapper/gradle-wrapper.properties
compileSdk/targetSdk 36, AGP 9.1.0, Gradle wrapper 9.4.1, Kotlin/KSP/Hilt/Compose 등 주요 버전 및 라이브러리 업그레이드; applicationId 및 새 플러그인 항목 추가.
Convention 플러그인 구조 변경
build-logic/convention/build.gradle.kts, build-logic/convention/src/main/java/com/threegap/bitnagil/convention/...Plugin.kt
ktlint 적용방식 변경(Convention 내 적용), 플러그인 내부 imports/호출 정리 및 일부 설정(예: applicationId/versionCode 위임) 위치 조정.
새로운 Convention 플러그인
build-logic/convention/src/main/java/com/threegap/bitnagil/convention/KotlinSerializationPlugin.kt, .../KotlinParcelizePlugin.kt, build-logic/convention/build.gradle.kts
Kotlin Serialization 및 Parcelize 전용 convention 플러그인 추가 및 플러그인 등록.
Convention 확장/유틸 변경
build-logic/convention/src/main/java/com/threegap/bitnagil/convention/extension/Extensions.kt, .../AppVersion.kt, .../ComposeAndroid.kt, .../KotlinAndroid.kt, .../KotlinCoroutine.kt, ApplicationId.kt (삭제)
Extensions.ktlibs/basePackage/namespace 유틸 추가. AppVersion/Compose/Kotlin 등 설정 함수 시그니처 및 로직 간소화(라이브러리 전용 처리, LibraryExtension 관련 제거 등).ApplicationId.kt 삭제.
모듈별 build.gradle.kts 정리
app/build.gradle.kts, data/build.gradle.kts, presentation/build.gradle.kts, core/*/build.gradle.kts
각 모듈의 android.namespace 선언 제거; 일부 모듈의 kotlin.serialization/parcelize 플러그인 좌표를 libs.plugins.bitnagil...로 전환; 중복된 serialization 의존성 일부 제거.
최상위 빌드스크립트 정리
build.gradle.kts
allprojects 블록에서 ktlint 적용 제거 및 상단 플러그인 블록 정리.

Sequence Diagram(s)

sequenceDiagram
    participant AppModule as 앱 모듈 (BuildConfig)
    participant HiltModule as AppVersionModule (Hilt)
    participant DataSource as VersionDataSourceImpl
    participant VersionSvc as VersionService

    AppModule->>HiltModule: BuildConfig.VERSION_MAJOR/MINOR/PATCH 읽음
    HiltModule->>DataSource: `@Named` 주입 (versionMajor/minor/patch)
    DataSource->>VersionSvc: checkVersion(major, minor, patch)
    VersionSvc-->>DataSource: 결과 반환
Loading
sequenceDiagram
    participant Activity as Activity
    participant PlayStoreUtils as PlayStoreUtils
    participant IntentMgr as Intent/PackageManager

    Activity->>PlayStoreUtils: openAppInPlayStore()
    PlayStoreUtils->>Activity: activity.packageName 조회
    PlayStoreUtils->>IntentMgr: createPlayStoreIntent(packageName) / createWebIntent(packageName)
    IntentMgr->>Activity: Play Store 또는 웹으로 인텐트 실행 시도
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 앱 버전은 앱이 주고, 토끼가 가져와,
플러그인 정리하니 빌드가 가벼워져.
패키지명은 런타임에 묻고, DI는 값 전해,
깡총깡총 점프하며 리팩터 축하해! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경 사항인 Gradle 설정 최신화와 앱 버전 관리 아키텍처 개선을 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명이 템플릿의 주요 섹션(Related issue, Work Description, To Reviewers)을 포함하고 있으며 변경 사항이 상세하게 기술되어 있습니다.
Linked Issues check ✅ Passed PR의 모든 변경 사항이 #200과 #201 이슈의 요구사항을 충족합니다. Gradle 버전 최신화, Convention Plugin 구조 개선, 버전 관리 아키텍처 개선이 모두 구현되어 있습니다.
Out of Scope Changes check ✅ Passed 모든 코드 변경이 #200과 #201의 범위 내에 있습니다. hiltViewModel import 경로 수정, AndroidManifest installLocation 변경 등 모두 명시된 작업에 포함됩니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/#200-gradle-modernization

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
build-logic/convention/src/main/java/com/threegap/bitnagil/convention/extension/Extensions.kt (1)

14-15: namespace 계산은 전체 Gradle path를 반영하는 편이 더 안전합니다.

지금 식이면 :core:datastorecom.threegap.bitnagil.datastore로 평탄화되어 중간 경로 정보가 사라집니다. 현재 settings.gradle.kts에 이미 :core:* 구조가 있으니, 전체 path를 점 표기 형태로 바꿔 계산하면 namespace drift와 향후 충돌 가능성을 줄일 수 있습니다.

♻️ 제안 수정
 internal val Project.namespace: String
-    get() = if (path == ":app") basePackage else "$basePackage.${name.replace("-", "_")}"
+    get() = if (path == ":app") {
+        basePackage
+    } else {
+        "$basePackage.${path.removePrefix(":").replace(":", ".").replace("-", "_")}"
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@build-logic/convention/src/main/java/com/threegap/bitnagil/convention/extension/Extensions.kt`
around lines 14 - 15, The current Project.namespace getter flattens multi-module
paths by using name and loses intermediate path segments; change it to compute
namespace from the full Gradle path (Project.path) by removing the leading ":"
and replacing ":" with "." and hyphens with underscores, then prefix with
basePackage (while preserving the special-case for ":app" to return
basePackage); update the getter for the Project.namespace property (refer to
path, basePackage, name) to build namespace =
"$basePackage.${sanitizedFullPath}" where sanitizedFullPath is path without
leading ":" with ":"→"." and "-"→"_" transformations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/com/threegap/bitnagil/MainNavHost.kt`:
- Line 5: The new import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
is from the separate artifact (androidx.hilt:hilt-lifecycle-viewmodel-compose)
which isn't declared in gradle/libs.versions.toml and so causes compile errors
in files using hiltViewModel (e.g., MainNavHost.kt and the listed presentation
screens); add the artifact entry to gradle/libs.versions.toml and then add the
dependency to modules that use hiltViewModel (or update
build-logic/HiltPlugin.kt or AndroidComposePlugin.kt to inject it) so each
affected module's build.gradle.kts includes
implementation(libs.compose.hilt.lifecycle.viewmodel) to satisfy the import.

In
`@build-logic/convention/src/main/java/com/threegap/bitnagil/convention/AndroidApplicationPlugin.kt`:
- Around line 15-19: The build fails because the Kotlin Android plugin is not
applied: update the plugin application block in AndroidApplicationPlugin (and
mirror the same change in AndroidLibraryPlugin) to also apply
"org.jetbrains.kotlin.android" so that configureKotlinAndroid() can locate the
KotlinAndroidProjectExtension; ensure the apply sequence includes
"org.jetbrains.kotlin.android" alongside "com.android.application" and
"org.jetbrains.kotlin.plugin.compose" before calling configureKotlinAndroid().

In
`@build-logic/convention/src/main/java/com/threegap/bitnagil/convention/AndroidLibraryPlugin.kt`:
- Around line 12-15: The convention plugin applies the external ktlint plugin
but doesn't add it to the convention classpath; update the convention module's
dependencies block to include ktlint as a compileOnly dependency (e.g., add
libs.ktlint) so the external plugin is available at runtime, and make the same
change for the other convention plugin modules that apply ktlint:
KotlinJvmPlugin and AndroidApplicationPlugin; locate the pluginManager.apply {
apply("org.jlleitschuh.gradle.ktlint") } usage inside AndroidLibraryPlugin,
KotlinJvmPlugin, and AndroidApplicationPlugin and ensure each corresponding
build-logic convention build.gradle.kts adds compileOnly(libs.ktlint) in its
dependencies.

In
`@presentation/src/main/java/com/threegap/bitnagil/presentation/screen/terms/TermsAgreementScreen.kt`:
- Line 16: The import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel is
unresolved because the artifact
androidx.hilt:hilt-lifecycle-viewmodel-compose:1.3.0 is not declared; add the
artifact entry to your dependency catalog (gradle/libs.versions.toml) with
version 1.3.0, then add a dependency on that catalog coordinate in the
presentation module's build.gradle.kts so TermsAgreementScreen.kt (and the other
16 files) can resolve hiltViewModel; note this is the Hilt-specific artifact
(not androidx.lifecycle:lifecycle-viewmodel-compose).

In
`@presentation/src/main/java/com/threegap/bitnagil/presentation/util/playstore/PlayStoreUtils.kt`:
- Around line 51-57: The current tryOpenWebBrowser function swallows all
Exceptions which hides real issues; change its error handling to only catch
ActivityNotFoundException (so fallback returns false when no browser/activity
exists) and let other exceptions (e.g., SecurityException, malformed Intent from
createWebIntent) surface or be logged; specifically update
tryOpenWebBrowser(ComponentActivity, packageName) to catch
ActivityNotFoundException and return false, and for any other thrown exception
either rethrow or log it via the existing logging mechanism so failures are
visible for debugging.

---

Nitpick comments:
In
`@build-logic/convention/src/main/java/com/threegap/bitnagil/convention/extension/Extensions.kt`:
- Around line 14-15: The current Project.namespace getter flattens multi-module
paths by using name and loses intermediate path segments; change it to compute
namespace from the full Gradle path (Project.path) by removing the leading ":"
and replacing ":" with "." and hyphens with underscores, then prefix with
basePackage (while preserving the special-case for ":app" to return
basePackage); update the getter for the Project.namespace property (refer to
path, basePackage, name) to build namespace =
"$basePackage.${sanitizedFullPath}" where sanitizedFullPath is path without
leading ":" with ":"→"." and "-"→"_" transformations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6038c818-d680-4639-a523-8217d5361684

📥 Commits

Reviewing files that changed from the base of the PR and between 4ae9e13 and e6ac347.

📒 Files selected for processing (47)
  • app/src/main/AndroidManifest.xml
  • app/src/main/java/com/threegap/bitnagil/MainNavHost.kt
  • app/src/main/java/com/threegap/bitnagil/di/data/AppVersionModule.kt
  • app/src/main/java/com/threegap/bitnagil/di/presentation/VersionNameProviderModule.kt
  • app/src/main/java/com/threegap/bitnagil/util/version/PackageManagerVersionNameProvider.kt
  • build-logic/convention/build.gradle.kts
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/AndroidApplicationPlugin.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/AndroidComposePlugin.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/AndroidLibraryPlugin.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/HiltPlugin.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/KotlinJvmPlugin.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/KotlinParcelizePlugin.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/KotlinSerializationPlugin.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/extension/AppVersion.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/extension/ApplicationId.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/extension/ComposeAndroid.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/extension/Extensions.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/extension/KotlinAndroid.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/extension/KotlinCoroutine.kt
  • build.gradle.kts
  • core/datastore/build.gradle.kts
  • core/designsystem/build.gradle.kts
  • core/network/build.gradle.kts
  • core/security/build.gradle.kts
  • data/build.gradle.kts
  • data/src/main/java/com/threegap/bitnagil/data/version/datasourceImpl/VersionDataSourceImpl.kt
  • domain/build.gradle.kts
  • gradle/libs.versions.toml
  • gradle/wrapper/gradle-wrapper.properties
  • presentation/build.gradle.kts
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/emotion/EmotionScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/guide/GuideScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/home/HomeScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/login/LoginScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/mypage/MyPageScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/onboarding/OnBoardingScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/recommendroutine/RecommendRoutineScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/reporthistory/ReportHistoryScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/reportwrite/ReportWriteScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/routinelist/RoutineListScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/routinewrite/RoutineWriteScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/setting/SettingScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/splash/SplashScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/terms/TermsAgreementScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/withdrawal/WithdrawalScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/util/playstore/PlayStoreUtils.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/util/version/AndroidApplicationVersionNameProvider.kt
💤 Files with no reviewable changes (6)
  • core/datastore/build.gradle.kts
  • build.gradle.kts
  • core/network/build.gradle.kts
  • core/security/build.gradle.kts
  • presentation/src/main/java/com/threegap/bitnagil/presentation/util/version/AndroidApplicationVersionNameProvider.kt
  • build-logic/convention/src/main/java/com/threegap/bitnagil/convention/extension/ApplicationId.kt

Copy link
Contributor

@l5x5l l5x5l left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다 👍

@wjdrjs00 wjdrjs00 merged commit f5574cc into develop Mar 25, 2026
2 checks passed
@wjdrjs00 wjdrjs00 deleted the refactor/#200-gradle-modernization branch March 25, 2026 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 Refactor 기존 기능 개선 🧤 대현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[REFACTOR] 앱 버전 관리를 app 모듈로 이전 [REFACTOR] Gradle 설정 최신화 및 Convention Plugin 구조 개선

2 participants