Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Android Modularization Recipe

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Sungyong An Sungyong An
December 10, 2023

Android Modularization Recipe

2023년 12월 10일 (일) Devfest Songdo 2023 행사에서의 발표자료입니다.
https://festa.io/events/4246

Avatar for Sungyong An

Sungyong An

December 10, 2023

More Decks by Sungyong An

Other Decks in Programming

Transcript

  1. য়ט ߊ಴ח, ৢ೧ ׮ܲ ѐߊ ೯ࢎীࢲ੄ ߊ಴ղਊҗ োҙػ ղਊੑפ׮. 


    Dagger Hiltী ؀೧ࢲח ࢸݺೞ૑ ঋणפ׮. I/O Extended 2023 Seoul DroidKnights 2023
  2. A app data domain যڃ ഋక۽ জਸ ѐߊೞҊ ੓աਃ? B

    data app domain or app app common C domain app app data app app feature app app app or
  3. ҳӖীࢲ ӂ੢ೞח জ ইఃఫ୊ о੉٘ (ۨ੉য ܻ࠙, ੄ઓࢿ ઱ੑ, UDF

    ١) “ۨ੉যܳ যڌѱ ܻ࠙ೡ ࣻ ੓ਸө?” → interface, class ܻ࠙ 
 (੄ઓࢿ ઱ੑ) “ܻ࠙ܳ ъઁೞח ߑߨ?” → ݽٕച App Architecture Link: h tt ps://developer.android.com/topic/architecture#recommended-app-arch
  4. App Architecture — Modularization Modern App Architecture: • UI Layer

    • Domain Layer (Optional) • Data Layer → ࢲ۽ 1:1 ݒடغ૑ ঋח׮. Types of modules: • App Modules • Feature Modules • Data Modules • Common Modules • Test Modules
  5. → ੿׹ਸ тҳೞח ѐߊ੗ “੉ѱ ݏա…?” Layer Domain Data UI

    Feature Domain Data UI ੷݃׮ ׮ܲ ӝળਵ۽ ݽٕਸ ա׀׮ Layer + Feature Domain Data UI
  6. → ݽٕചী ױ ೞա੄ ੿׹਷ হ׮. “੸׼ೠ ӏݽ੄ জী ੸೤ೠ

    ೞա੄ ߑߨ” → ೞ૑݅ ؊ ੘਷/ழ׮ۆ ࢲ࠺झীࢲח যڌѱ…? Now in Android Link: h tt ps://github.com/android/nowinandroid/blob/main/docs/ModularizationLearningJourney.md
  7. Recipe “a set of instructions that describes how to prepare

    or make something.” 
 (ޖ঱оܳ ળ࠺ೞѢա ݅٘ח ߑߨਸ ࢸݺೞח ੌ۲੄ ૑ஜ) → উ٘۽੉٘ জਸ ױ҅੸ਵ۽ ݽٕചೞח ೞա੄ ߑߨਸ ࢸݺ೧ࠄ׮. Link: h tt ps://en.wikipedia.org/wiki/Recipe
  8. ݽٕച੄ ݾ੸ = “ѐߊ ࢤ࢑ࢿ” “যڃ ҃਋ী ݽٕചܳ Ҋ޹ೞѱ غחо?”

    • ѐߊ੗ ࣻо טযաݶࢲ, ࢲ۽ Ҁ஖ח ࠗ࠙੉ ࢤӟ׮. • ౱݃׮ ׮ܲ ߑधਵ۽, ੌࠗ࠙݅ ࢜۽਍ ӝࣿਸ ࢎਊೞৈ ѐߊೞҊ र׮. • জ੄ ӝמ੉ טযաݶࢲ, ࢲ۽ ࢚ҙ হח ࠗ࠙ীب औѱ ৔ೱਸ ઱Ҋ ߉ח׮. • ௏٘о ݆ইઉࢲ рױೠ ࣻ੿ীب ࠽٘दр੉ য়ې Ѧܽ׮. • ׮নೠ ಬ ಂఠܳ ૑ਗೞח ١ জ ݽٕ੉ ৈ۞ ѐо ػ׮. 
 → ݽٕച ૓೯ җ੿ ࣘীࢲب ࢤ࢑ࢿਸ ਬ૑ೞח Ѫਸ ୶ୌೠ׮.
  9. (1) Version Catalog ੸ਊೞӝ زੌೠ ۄ੉࠳۞ܻܳ ৈ۞ ݽٕীࢲ ࢎਊೞѱ ػ׮.

    (ex. Kotlin, Hilt) Version Catalogܳ ੉ਊೞৈ, ۄ੉࠳۞ܻ ߡ੹ਸ ೠ Ҕীࢲ ҙܻೡ ࣻ ੓׮. → ٘۽੉٘ա੉எ 2023 ߊ಴৔࢚ ୶ୌ “Gradle Version Catalog 적 용 하 기 ” Link: h tt ps://docs.gradle.org/current/userguide/pla tf orms.html
  10. // build.gradle dependencies { implementation 'androidx.core:core-ktx:1.9.0' } // gradle/libs.versions.toml [versions]

    androidx-core-ktx = "1.9.0" [libraries] androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-core-ktx" } // build.gradle dependencies { implementation libs.androidx.core.ktx } Link: h tt ps://developer.android.com/build/migrate-to-catalogs
  11. (2) Data ݽٕ ܻ࠙ೞӝ о੢ ݢ੷ ࢲߡ, ӝӝ ١ ৻ࠗ৬

    ాनೞח ࠗ࠙ਸ ܻ࠙ೞ੗. • data: API, DB, SharedPreferences ١ ؘ੉ఠܳ ୊ܻೞח ݽٕ ◦ Repository, DataSource, DTO, Entity ١ • model: ؘ੉ఠ ݽٕীࢲ ৻ࠗী ֢୹ೞח ݽ؛ ௿ېझܳ ઁҕೞח ݽٕ ◦ ݽ؛ ௿ېझী ࠛ೙ਃೠ ௏٘о ୶оغח Ѫਸ ߑ૑ೞ۰ח ݾ੸ (ex. DTO, Enity annotation) ◦ ࣽࣻೠ Java, Kotlin ݽٕب оמ :data :model :app Link: h tt ps://developer.android.com/topic/modularization/pa tt erns#data-modules
  12. // :data module interface ExampleRepository { suspend fun getExampleList(): List<Example>

    } internal class ExampleRepositoryImpl(...) : ExampleRepository { ... } internal interface ExampleRemoteDataSource { ... } 
 internal class ExampleRemoteDataSourceImpl(...) : ExampleRemoteDataSource { ... } 
 internal class ExampleResponse(val something: String) 
 internal interface ExampleLocalDataSource { ... } 
 internal class ExampleLocalDataSourceImpl(...) : ExampleLocalDataSource { ... } 
 internal class ExampleEntity(val something: String) 
 // :model module 
 class Example(val something: String) Repository৬ Model ௿ېझ ৻ীח, internel ఃਕ٘ܳ ੉ਊೞৈ ੽Ӕਸ ઁೠೠ׮.
  13. (2) Data ݽٕ ܻ࠙ೞӝ - Legacy DB, SharedPreferences ୊ۢ ӝӝ

    ۽ஸীࢲ ҙܻ೧ঠ ೞח ࠗ࠙਷ ೠߣী ੉زೞӝ য۵׮. interfaceܳ ੉ਊೞৈ पઁ۽ח app ݽٕ੄ ҳഅ୓۽ োѾ೧فҊ, 
 ੉റী оמೠ ࠗ࠙ࠗఠ ੼૓੸ਵ۽ data ݽٕ۽ ৤ӝח ߑߨب оמೞ׮. Link: h tt ps://developer.android.com/topic/modularization/pa tt erns#data-modules :app :data AppPreferences LegacyRemoteDataSource LegacyPreferences ExampleViewModel ExampleRepository ExampleApi ExamplePreferences ExamplePreferencesImpl ExampleRepositoryImpl internal LegacyLocalDataSource ExampleDatabase
  14. // :data module interface LegacyPreferences { var something: String }

    interface ExamplePreferences : LegacyPreferences { ... } internal class ExamplePreferencesImpl( context: Context, private val legacyPrefs: LegacyPreferences, ) : ExamplePreferences, LegacyPreferences by legacyPrefs { ... } // :app module object AppPreferences : LegacyPreferences { override var something: String = ... } inte rf aceܳ ੉ਊೞৈ, app ݽٕ੄ Singletonਸ data ݽٕী ઁҕೡ ࣻ ੓׮.
  15. // :app module @Module @InstallIn(SingletonComponent::class) object AppModule { @Provides fun

    providesLegacyPreferences() : LegacyPreferences { return AppPreferences } } Hiltܳ ੉ਊೞৈ, ੄ઓࢿਸ ࢜۽਍ inte rf ace۽ ઁҕೡ ࣻ ੓׮.
  16. // How to use - val something = AppPreferences.something +

    @Inject + lateinit var prefs: ExamplePreferences + + val something = prefs.something ੉ઁ ࢎਊೞ؍ ࠗ࠙ਸ ೞաঀ ੹ജೡ ࣻ ੓׮.
  17. (3) BuildConfigܳ ݽٕ۽ ܻ࠙ೞӝ উ٘۽੉٘ জ੄ ࠽٘ ੿ࠁܳ ನೣೞח ௿ېझ.

    • BuildConfig.DEBUG • BuildConfig.VERSION_NAME • BuildConfig.API_BASE_URL (custom)
  18. // :app module android { defaultConfig { buildConfigField "String", "VERSION_NAME",

    “String.valueOf(\"1.0.0\")" } flavorDimensions "default" productFlavors { dev { buildConfigField "String", "API_BASE_URL", "String.valueOf(\"https://dev...\")" } stage { buildConfigField "String", "API_BASE_URL", "String.valueOf(\"https://stage...\")" } real { buildConfigField "String", "API_BASE_URL", "String.valueOf(\"https://real...\")" } } } ࠁా fl avorী ٮۄ ч੉ ׳ۄ૑ח ࢎਊ੗ ੿੄ ೙٘ܳ ୶оೞৈ ࢎਊೠ׮. Link: h tt ps://developer.android.com/build/gradle-tips#share-custom- fi elds-and-resource-values-with-your-app-code
  19. (3) BuildConfigܳ ݽٕ۽ ܻ࠙ೞӝ উ٘۽੉٘ জ੄ ࠽٘ ੿ࠁܳ ನೣೞח ௿ېझ.

    • BuildConfig.DEBUG • BuildConfig.VERSION_NAME • BuildConfig.API_BASE_URL (custom) data ݽٕীࢲب BuildConfigܳ ࢎਊ೧ঠ ೠ׮ݶ: (1) app ݽٕ ௏٘ܳ Ӓ؀۽ ࠂࠢೠ׮.
  20. (3) BuildConfigܳ ݽٕ۽ ܻ࠙ೞӝ উ٘۽੉٘ জ੄ ࠽٘ ੿ࠁܳ ನೣೞח ௿ېझ.

    • BuildConfig.DEBUG • BuildConfig.VERSION_NAME • BuildConfig.API_BASE_URL (custom) data ݽٕীࢲب BuildConfigܳ ࢎਊ೧ঠ ೠ׮ݶ: (1) app ݽٕ ௏٘ܳ Ӓ؀۽ ࠂࠢೠ׮. (2) BuildConfigܳ ݽٕ۽ ܻ࠙ೠ׮.
  21. // :app module dependencies { implementation project(':buildconfig') } // :data

    module dependencies { implementation project(':buildconfig') } ೧஖ਛա…?
  22. // :buildconfig module android { namespace 'soup.movie.buildconfig' defaultConfig { buildConfigField

    "String", "VERSION_NAME", “String.valueOf(\"1.0.0\")" } buildFeatures { buildConfig true } flavorDimensions "default" productFlavors { dev { buildConfigField "String", "API_BASE_URL", "String.valueOf(\"https://dev...\")" } stage { buildConfigField "String", "API_BASE_URL", "String.valueOf(\"https://stage...\")" } real { buildConfigField "String", "API_BASE_URL", "String.valueOf(\"https://real...\")" } } } ੄ઓࢿਸ ыח ݽٚ ݽٕী fl avorо ੹౵غח ޙઁ੼.
  23. // :data module android { buildFeatures { buildConfig false }

    flavorDimensions "default" productFlavors { dev {} dev2 {} stage {} real {} } } ೧Ѿೡ ࣻ ੓ח ߑߨ੉ ੓ਸө…? // :app module android { buildFeatures { buildConfig false } flavorDimensions "default" productFlavors { dev {} dev2 {} stage {} real {} } }
  24. // :buildconfig-stub module android { namespace 'soup.movie.buildconfig' defaultConfig { buildConfigField

    "String", "VERSION_NAME", "String.valueOf(\"0\")" buildConfigField "String", "API_BASE_URL", "String.valueOf(\"\")" } buildFeatures { buildConfig true } // productFlavors X } (1) fl avorо হח, stub ݽٕਸ ୶оೠ׮.
  25. // :app module dependencies { implementation project(':buildconfig') } // :data

    module dependencies { compileOnly project(':buildconfig-stub') } (2) fl avorо ੓ח app ݽٕ ৻ীח stubਸ compileOnly۽ ࢶ঱ೠ׮.
  26. (3) BuildConfigܳ ݽٕ۽ ܻ࠙ೞӝ compileOnlyח ஹ౵ੌ द੼ী݅ ࢎਊغҊ, ࠽٘ Ѿҗޛীח

    ನೣغ૑ ঋח׮. ૊, ࠽٘ Ѿҗޛীח buildconfig-stub੉ ইצ, buildconfig۽ Ү୓غয ನೣػ׮. ੉ܳ ੉ਊೞৈ, ׮ܲ ݽٕী flavorо ੹౵غח Ѫਸ ݄ਸ ࣻ ੓׮. :data :app :buildcon fi g :buildcon fi g-stub compileOnly implementation = :others … Link: h tt ps://developer.android.com/build/dependencies#dependency_con fi gurations
  27. Milestone 1. :app :data :buildcon fi g :buildcon fi g-stub

    :model compileOnly ੉ߣীח app ݽٕীࢲ feature ݽٕਸ աׇࠁ੗.
  28. Feature Core ݽٕ ܻ࠙ೞӝ (?) feature ݽٕ݃׮ ҕా੸ਵ۽ ೙ਃೠ Ѫਸ

    ઁҕೞח ݽٕ. • ܻࣗझ: color, dimen, drawable, string, style, … • Base ௿ېझ: Activity, Fragment, Dialog, … • Widget, ഛ੢ೣࣻ, ੉޷૑۽٬, ۽Ӓੋ • …١١… → গݒೞݶ ކٶ core۽ ٜযр׮. 
 ژ ׮ܲ गಌ জ ݽٕਸ ݅٘ח ߑध੉ۄ ୶ୌೞ૑ ঋח׮. ӒܻҊ data ݽٕীࢲب ೙ਃೞ׮ݶ? :app :feature-core :data :feature:search :model api ?
  29. ৈ۞ ചݶীࢲ ੗઱ ࢎਊೞח ௏٘ܳ, ҙबࢎী ٮۄ ੸੺൤ ܻ࠙ೠ׮. •

    kotlin: Kotlin, Coroutines ҕా ௏٘ • logger: Log • designsystem: ٣੗ੋ दझమ • resources: ܻࣗझ • … (4) Common ݽٕ ܻ࠙ೞӝ Link: h tt ps://developer.android.com/topic/modularization/pa tt erns#common-modules :common :data :feature:search :kotlin :logger :resources :designsystem api …
  30. ӝઓীח ੄ઓೞח ݽٚ ݽٕ੄ ܻࣗझ IDо R ௿ېझী ನೣػ׮. non-transitive

    R ௿ېझܳ ࢎਊೞݶ, R ௿ېझ੄ ௼ӝо ઴যٚ׮. (࠽٘ࣘب ߂ জ ௼ӝ ѐࢶ) 
 ױ, ܻࣗझо ನೣغয ੓ח ੿ഛೠ R ௿ېझܳ import ೧ঠ ೠ׮. (4) Common ݽٕ ܻ࠙ೞӝ - resources Link: h tt ps://developer.android.com/build/optimize-your-build#use-non-transitive-r-classes com.myapp.library2.R welcome_text = Hi, Songdo com.myapp.library1.R welcome_text = Hi, Songdo goodbye_text = Bye :library2 module welcome_text = Hi, Songdo :library1 module goodbye_text = Bye com.myapp.library.R welcome_text = Hi, Songdo com.myapp.library1.R goodbye_text = Bye non-transitive R classes
  31. // gradle.properties android.nonTransitiveRClass=true // :library2 module import com.myapp.library2.R val bar

    = R.string.welcome_text // :library1 module import com.myapp.library1.R - val foo = R.string.welcome_text + val foo = com.myapp.library2.R.string.welcome_text val bar = R.string.goodbye drawable, string, color ١ ܻࣗझܳ ೞա੄ ݽٕী فݶ…? Link: h tt ps://medium.com/androiddevelopers/5-ways-to-prepare-your-app-build-for-android-studio- fl amingo-release-da34616bb946
  32. // gradle.properties android.nonTransitiveRClass=true // :library2 module - import com.myapp.library2.R +

    import com.myapp.resources.R val bar = R.string.welcome_text // :library1 module - import com.myapp.library1.R + import com.myapp.resources.R val foo = R.string.welcome_text val bar = R.string.goodbye impo r ܳ ҙܻೞӝ ಞೞ׮. Link: h tt ps://medium.com/androiddevelopers/5-ways-to-prepare-your-app-build-for-android-studio- fl amingo-release-da34616bb946
  33. ܻࣗझܳ ݽٕ۽ ܻ࠙ೡ ٸ, ܻࣗझ ੉ܴ੉ زੌೞݶ overrideغח ޙઁо ੓ਸ

    ࣻ ੓׮. যڃ ࣽࢲ۽ override غযঠ ೞח૑ জীࢲ Ѿ੿ೡ ࣻ হ׮. (4) Common ݽٕ ܻ࠙ೞӝ - resources Link: h tt ps://developer.android.com/studio/projects/android-library#Considerations com.myapp.library2.R welcome_text = Hi, Incheon com.myapp.library1.R welcome_text = Hi, Incheon :library2 module welcome_text = Hi, Songdo :library1 module welcome_text = Hi, Incheon
  34. // :library2 module android { resourcePrefix 'myapp_lib2_' } <string name="welcome_text">Hi,

    Songdo</string> // :library1 module android { resourcePrefix 'myapp_lib1_' } <string name="welcome_text">Hi, Incheon</string> // :app module val foo = R.string.myapp_lib2_welcome_text // Hi, Songdo val bar = R.string.myapp_lib1_welcome_text // Hi, Incheon (1) resourcePre fi xܳ ੉ਊೞח ߑߨ. ೞ૑݅ ৻ࠗ ۄ੉࠳۞ܻীࢲ Ҁ஘׮ݶ…? Link: h tt ps://developer.android.com/reference/tools/gradle-api/8.2/com/android/build/api/dsl/CommonExtension#resourcePre fi x()
  35. // 3rd party library <string name="app_name">3rd Party Library</string> // :common:resources

    module <string name="app_name">MyApp</string> // :app module android { sourceSets { main.res.srcDirs += '../common/resources/src/main/res' } } val foo = R.string.app_name // MyApp (2) জ ݽٕ੄ sourceSetsী ܻࣗझ ݽٕ੄ ಫ؊ܳ ୶оೞח ߑߨ. Link: h tt ps://developer.android.com/build/build-variants#con fi gure-sourcesets
  36. (5) Convention Plugins ࢎਊೞӝ ݽٕ рী ࠽٘ ۽૒ਸ ҕਬೞח ߑߨ.

    ݽٕਸ ੼੼ ؊ ݆੉ ٜ݅ѱ غחؘ, ݽٕਸ ࢤࢿೞח ࠗ׸ + पࣻܳ ઴ੌ ࣻ ੓׮. → ٘۽੉٘ա੉எ 2023 ߊ಴৔࢚ ୶ୌ “Gradle Kotlin ஶ߮࣌ ೒۞Ӓੋਵ۽ ബਯ੸ਵ۽ ݣ౭ ݽٕ ҙܻೞӝ” Link: h tt ps://docs.gradle.org/current/samples/sample_convention_plugins.html
  37. plugins { id 'com.android.library' id 'org.jetbrains.kotlin.android' } android { compileSdk

    34 defaultConfig { minSdk 21 targetSdk 34 } compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } kotlinOptions { jvmTarget = '11' } } plugins { id 'example.android.library' } ߈ࠂغח ௏٘ܳ ઴ੌ ࣻ ੓׮.
  38. plugins { id 'com.google.dagger.hilt.android' id 'org.jetbrains.kotlin.kapt' } dependencies { implementation

    libs.hilt.android kapt libs.hilt.compiler } plugins { id 'example.android.hilt' } ݽٕ݃׮ pluginਸ ٜ݅ӝࠁ׮ח, ੤ഝਊೡ ࣻ ੓ח ױਤ۽ ա־ח Ѫ੉ જ׮.
  39. // :feature:search module plugins { id 'example.android.library' id 'example.android.hilt' }

    dependencies { implementation project(':common:kotlin') implementation project(':common:logger') implementation project(':common:designsystem') implementation project(':common:resources') implementation project(':data') implementation project(':model') } // :feature:search module plugins { id 'example.android.feature' } ੸੺൤ ա־ݶ ݻ ઴݅ਵ۽ ୡӝചೡ ࣻ ੓Ҋ, ޘযࢲ ࢎਊೡ ࣻب ੓׮.
  40. ੌ߈੸ਵ۽ ౠ੿ दաܻয়, ӝמী োҙػ ചݶਸ ׸׼ೞח ݽٕ. • home:

    ക • detail: ࢚ࣁ • search: Ѩ࢝ • settings: ࢸ੿ • navigator: ചݶ ੉ز • … (6) Feature ݽٕ ܻ࠙ೞӝ Link: h tt ps://developer.android.com/topic/modularization/pa tt erns#feature-modules :feature :app :home :search :se tt ings :data :navigator :detail
  41. Feature ݽٕਸ ܻ࠙ೡ ٸ, ചݶ р ੉زೡ ࣻ ੓ח ߑߨ੉

    ೙ਃೞ׮. (6) Feature ݽٕ ܻ࠙ೞӝ - navigator Link: h tt ps://developer.android.com/topic/modularization/pa tt erns#feature-modules :feature :app :home :detail .DetailActivity .HomeActivity
  42. // :app module <manifest> <application> <activity android:name=".DetailActivity"/> </application> </manifest> //

    :others module startActivity(Intent(context, DetailActivity::class.java) э਷ ݽٕীࢲח Activityܳ ૒੽ ଵઑೡ ࣻ ੓૑݅, ׮ܲ ݽٕ੉ۄݶ…?
  43. // :feature:detail module <manifest> <application> <activity android:name=".DetailActivity" android:exported="true"> <intent-filter> ...

    <data android:scheme="..." android:host="detail" /> </intent-filter> </activity> </application> </manifest> // :feature:home module startActivity(Intent(ACTION_VIEW, Uri.parse("...://detail")) ٩݂௼ب оמೞ׮. ೞ૑݅ ৻ࠗীب Activityо ֢୹ػ׮.
  44. // :feature:detail module <manifest> <application> <activity android:name=".DetailActivity" android:exported="true"> <intent-filter> ...

    <data android:scheme="..." android:host="detail" /> </intent-filter> </activity> </application> </manifest> // :feature:home module startActivity(Intent(ACTION_VIEW, Uri.parse("...://detail?id=...")) ӒܻҊ ID э਷ чਸ ੹׳೧ঠ ೠ׮ݶ…?
  45. :app Feature ݽٕਸ ܻ࠙ೡ ٸ, ചݶ р ੉زೡ ࣻ ੓ח

    ߑߨ੉ ೙ਃೞ׮. (6) Feature ݽٕ ܻ࠙ೞӝ - navigator Link: h tt ps://developer.android.com/topic/modularization/pa tt erns#feature-modules :feature :home :detail .DetailActivity .HomeActivity :navigator Navigator NavigatorImpl
  46. // :feature:navigator module sealed interface Destination class Detail(val id: String)

    : Destination interface Navigator { fun createIntent(destination: Destination): Intent } // :app module class NavigatorImpl(private val context: Context) : Navigator { override fun createIntent(destination: Destination) { return when (destination) { is Detail -> Intent(context, DetailActivity::class.java) .putExtra(DetailActivity.EXTRA_ID, destination.id) ... } } } Activityী ੽Ӕೡ ࣻ ੓ח Ҕী ҳഅ୓ܳ ݅ٚ׮.
  47. // :feature:detail module <manifest> <application> <activity android:name=".DetailActivity" android:exported="false"/> </application> </manifest>

    // :feature:home module startActivity(navigator.createIntent(Detail(id = ...))) ৻ࠗী Activityܳ ֢୹ೞ૑ ঋҊ, ݽٕ р ചݶਸ ੉زೡ ࣻ ੓׮.
  48. Activity৬ ׳ܻ, Fragmentח ࢤࢿೡ ࣻ ੓ח ߑߨ੉ ೙ਃೞ׮. :app (6)

    Feature ݽٕ ܻ࠙ೞӝ - navigator :feature :home :detail .DetailFragment .HomeFragment :navigator FragmentFactory FragmentFactoryImpl Link: h tt ps://developer.android.com/guide/navigation/navigation-multi-module “Jetpack Navigation਷ 
 ೞױ੄ ݂௼ܳ ଵҊೞࣁਃ.”
  49. // :feature:navigator module sealed interface FragmentDestination class Detail(val id: String)

    : FragmentDestination interface FragmentFactory { fun createFragment(destination: FragmentDestination): Fragment } // :app module class FragmentFactoryImpl : FragmentFactory { override fun createFragment(destination: FragmentDestination): Fragment { return when (destination) { is Detail -> DetailFragment.newInstance(id = destination.id) ... } } } Fragmentী ੽Ӕೡ ࣻ ੓ח Ҕী ҳഅ୓ܳ ݅ٚ׮.
  50. // :feature:detail module class DetailFragment : Fragment() { ... companion

    object { fun newInstance(id: String): DetailFragment { ... } } } // :feature:home module fragmentManager.commit { val fragment = navigator.createFragment(Detail(id = ...)) add(R.id.fragment_view_container, fragment) } ݽٕ рী Fragmentܳ ҕਬೞৈ ࢎਊೡ ࣻ ੓׮.
  51. Milestone 2. :common :app :feature:navigator :data :common :designsystem :feature:search :logger

    :buildcon fi g :buildcon fi g-stub :resources :model compileOnly …
  52. ݽٕച ݾ੸ • ੄ઓࢿ Ѻܻ • ࠽٘दр ѐࢶ → ੜ

    غҊ ੓ਸө? Link: h tt ps://developer.android.com/topic/modularization :app :feature:se tt ings :feature:search :feature:navigator :data
  53. ੄ઓࢿ Ѻܻ ݽٕ ৻ࠗীࢲ ੽Ӕೡ ࣻ হب۾ 
 internal ఃਕ٘ܳ

    ୶оೞח ߑߨ਷ 
 → ѐߊ੗о ֬஖ӝ औ׮. (पࣻ ਬߊ) :feature:search :data interface SearchRepository internal class SearchRepositoryImpl( ... ) : SearchRepository { ... } @Module @InstallIn(SingletonComponent::class) internal interface DataModule { @Provids fun provideSearchRepository(...) : SearchRepository { ... } } @HiltViewModel class SearchViewModel @Inject constructor( private val repository: SearchRepository, ) : ViewModel() { ... } Link: h tt ps://kotlinlang.org/docs/visibility-modi fi ers.html#modules
  54. ੄ઓࢿ Ѻܻ Ӓېࢲ Domain Layerী ؀਽ೞח ݽٕਸ ୶оೞৈ, Data ݽٕ੄

    ੄ઓࢿਸ ܻ࠙ೡ ࣻب ੓׮. → ױࣽೠ ೣࣻ ഐ୹ীب UseCaseܳ ୶о೧ঠ ೠ׮. (࠺ബਯࢿ) UI Layer Domain Layer Data Layer Link: h tt ps://developer.android.com/topic/architecture/domain-layer#data-access-restriction
  55. // :ui module class ExampleViewModel @Inject constructor( private val usecase:

    ExampleUseCase, private val repository: ExampleRepository // X ) { ... } // :domain module class ExampleUseCase( private val repository: ExampleRepository ) { ... } // :data module interface ExampleRepository { ... } internal class ExampleRepositoryImpl(...) : ExampleRepository { ... } :ui :domain :data
  56. ੄ઓࢿ Ѻܻ Data ݽٕ੉ Domain ݽٕਸ ߄ۄࠁب۾ ߸҃ೞח ߑߨ਷? (DIP)

    → app ݽٕীࢲח ৈ੹൤ ੽Ӕೡ ࣻ ੓׮. (गಌ জ ݽٕ੉ۄݶ…) 
 ѾҴ impl ௿ېझܳ ऀӝ۰ݶ, internal ఃਕ٘ܳ ࢎਊ೧ঠ ೠ׮. Link: h tt ps://developer.android.com/topic/architecture/domain-layer#data-access-restriction UI Layer Domain Layer Data Layer App
  57. // :ui module class ExampleViewModel @Inject constructor( private val usecase:

    ExampleUseCase, private val repository: ExampleRepository // O ) { ... } // :domain module class ExampleUseCase @Inject constructor( private val repository: ExampleRepository ) { ... } interface ExampleRepository { ... } // :data module internal class ExampleRepositoryImpl(...) : ExampleRepository { ... } Domain ݽٕী Dataо ೣԋ ੓ח Ѫ੉ ݏਸө…? :ui :domain :data
  58. ੄ઓࢿ Ѻܻ ݽٕਸ -api, -impl۽ ܻ࠙ೞݶ, internal ఃਕ٘ হ੉ب ੽Ӕਸ

    ઁೠೡ ࣻ ੓׮. runtimeOnlyਸ ੉ਊೞৈ, ஹ౵ੌ द੼ীח -impl ݽٕী ੽Ӕೡ ࣻ হ૑݅ ࠽٘ Ѿҗޛীח ನೣغب۾ ೡ ࣻ ੓׮. :feature:search :data-api :data-impl runtimeOnly Link: h tt ps://developer.android.com/build/dependencies#dependency_con fi gurations
  59. // :feature:search module dependencies { implementation project(':data-api') runtimeOnly project(':data-impl') }

    // :data-impl module dependencies { implementation project(':data-api') } // :data-api module dependencies { } :feature:search :data-impl :data-api runtimeOnly
  60. ࣽജ ଵઑ ؊ աইо ݽٕਸ ܻ࠙ೞ׮ ࠁݶ, ݽٕ р ࣽജ

    ଵઑо ߊࢤೞח ҃਋о ੓׮. :feature :se tt ings :feature-core ࣽജ ଵઑ Link: h tt ps://en.wikipedia.org/wiki/Circular_dependency
  61. // :feature:core module abstract class BaseActivity : AppCompatActivity { @Inject

    lateinit var getCurrentLanguage: GetCurrentLanguageUseCase } // :feature:settings module interface GetCurrentLanguageUseCase { operator fun invoke(): Language } class LanguageSettingActivity : BaseActivity() { ... } :feature ৘ܳ ٜয, Feature ݽٕী UI৬ Domain ۨ੉যо ҕઓೞח ҃਋. :feature-core :se tt ings
  62. ࣽജ ଵઑ ੉ ҃਋ח Domain ݽٕਸ ݅٘ח Ѫب ೞա੄ ߑߨ੉׮.

    → ׮ܲ Feature ݽٕী UIܳ ઁҕೞҊ र׮ݶ? :feature :se tt ings :feature-core :domain
  63. ࣽജ ଵઑ ࢜۽਍ ݽٕਸ ୶оೞח ߑߨ…? → ੉ܴ ૙ӝо о੢

    য۵׮… 
 ഑दۄب ӝઓ ݽٕ ݺடਸ ߄Բݶ diffо ழ૓׮. (Conflict ઱੄!) :new-ui :feature :se tt ings :feature-core :domain
  64. ࣽജ ଵઑ ݽٕਸ -api, -impl۽ ܻ࠙ೞݶ, ࣽജ ଵઑܳ ࣚऔѱ ݄ਸ

    ࣻ ੓׮. Link: h tt ps://en.wikipedia.org/wiki/Circular_dependency :feature-core :feature :se tt ings-api :app :se tt ings-impl runtimeOnly
  65. // :feature-common module abstract class BaseActivity : AppCompatActivity { @Inject

    lateinit var getCurrentLanguage: GetCurrentLanguageUseCase } // :feature:settings-api module interface GetCurrentLanguageUseCase { operator fun invoke(): Language } // :feature:settings-impl module class GetCurrentLanguageUseCaseImpl : GetCurrentLanguageUseCase { ... } class LanguageSettingActivity : BaseActivity() { ... } :feature-core :feature :se tt ings-api :se tt ings-impl impl ݽٕ਷ api ݽٕਸ ଵઑೞҊ, ৉ਵ۽ח ೡ ࣻ হ׮.
  66. ࠽٘दр ѐࢶ ݽٕਸ ա־ݶ ࠽٘दр੉ ઴যٚ׮…? → ୊਺ ݽٕചೡ ٸ,

    ݃઱ೞӝ ए਍ ೣ੿. 
 ߽۳۽ ࠽٘ೞ૑ ঋਵݶ ઴যٜ૑ ঋח׮. :app :feature-core :data
  67. ࠽٘दр ѐࢶ ݽٕ р ੄ઓࢿ੉ হ׮ݶ, ߽۳۽ ࠽٘ೡ ࣻ ੓׮.

    ࣻ੿ࢎ೦੉ ੓ਸ ٸীب ߸҃ػ ݽٕਸ ଵઑೞח ݽٕٜ݅ ׮द ࠽٘ೠ׮. :app :feature:search :feature-core :feature:navigator :data
  68. ࠽٘दр ѐࢶ → അप੸ਵ۽ח ੄ઓࢿਸ ыӝ औ׮. ׼ো൤ ࠽٘दр਷ ઴যٜ૑

    ঋח׮. Link: h tt ps://github.com/android/nowinandroid/issues/707 :app :feature:search :feature-core :feature:navigator :data
  69. ࠽٘दр ѐࢶ ݽٕਸ -api, -impl۽ ܻ࠙ೞҊ -impl਷ app ݽٕীࢲ݅ ଵઑೞب۾

    ೞݶ, -impl ݽٕ р੄ ੄ઓࢿਸ Րযյ ࣻ ੓׮. :app :feature:search-impl :feature-core :feature:navigator-impl :data :feature:search-api :feature:navigator-api runtimeOnly runtimeOnly
  70. ࠽٘दр ѐࢶ → ৈӝࢲ data ݽٕী ߸҃ࢎ೦੉ ੓ਵݶ…? ކٶ ׮द

    ࠽٘೧ঠ ೠ׮. :app :feature:search-impl :feature-core :feature:navigator-impl :data :feature:search-api :feature:navigator-api runtimeOnly runtimeOnly
  71. ࠽٘दр ѐࢶ data ݽٕب -api, -impl۽ ܻ࠙ೞݶ ػ׮. → ୭Ӕ

    উ٘۽੉٘ ҕध ޙࢲীب ݽٕച о੉٘о সؘ੉౟غ঻׮. Link: h tt ps://developer.android.com/topic/modularization/pa tt erns#how_to_implement :data-impl :app :feature:search-impl :feature-core :feature:navigator-impl :data-api :feature:search-api :feature:navigator-api runtimeOnly runtimeOnly
  72. (7) Feature ݽٕ ܻ࠙ೞӝ ׮ܲ ݽٕীࢲ ೙ਃೠ Ѫਸ ୭ࣗೠ݅ ֢୹ೞח

    ഋక۽ ܻ࠙ೠ׮. -api: • UseCase interface • UI (Widget, ViewHolder ١) -impl: • UseCase class • UI (Activity, Fragment, ViewModel ١) :feature :app :search-impl :se tt ings-impl :se tt ings-api UseCase :search-api
  73. runtimeOnly۽ ੋ೧, জ ݽٕীࢲח ؊੉࢚ Activityী ੽Ӕೡ ࣻ হ׮. (7)

    Feature ݽٕ ܻ࠙ೞӝ - navigator :app :feature :home-impl :detail-impl .DetailActivity .HomeActivity :navigator Navigator NavigatorImpl
  74. Hiltܳ ੉ਊೞৈ, Activityо ੓ח пп੄ -impl ݽٕীࢲ -NavigatorImplਸ ઁҕೞݶ ػ׮.

    :feature :navigator-impl :home-impl :detail-impl DetailNavigatorImpl HomeNavigatorImpl :navigator-api Navigator NavigatorImpl (7) Feature ݽٕ ܻ࠙ೞӝ - navigator HomeNavigator DetailNavigator
  75. // :feature:navigator module sealed interface Destination class Detail(val id: String)

    : Destination // :app module class NavigatorImpl(private val context: Context) : Navigator { override fun createIntent(destination: Destination) { return when (destination) { is Detail -> Intent(context, DetailActivity::class.java) // X ... } } } জ ݽٕীࢲח -impl ݽٕ੄ Activityী ੽Ӕೡ ࣻ হ׮.
  76. // :feature:navigator-api module interface DetailNavigator { fun createIntent(destination: Detail): Intent

    } // :feature:detail-impl module class DetailNavigatorImpl(private val context: Context) : DetailNavigator { override fun createIntent(destination: Detail): Intent { return Intent(context, DetailActivity::class.java) // O } } // :feature:navigator-impl module class NavigatorImpl(private val detailNavigator: DetailNavigator) : Navigator { override fun createIntent(destination: Destination) { ... } } Activityо ੓ח -impl ݽٕীࢲ -NavigatorImplਸ ҳഅೞݶ ػ׮.
  77. (8) Data ݽٕ ࣁ࠙ചೞӝ ৈ۞ ࢎۈ੉ زदী ೞա੄ ݽٕਸ ࣻ੿ೠ׮.

    → ߽ݾ, Conflict оמࢿ ߽۳۽ ѐߊೞחؘ ߑ೧غח ࠗ࠙੉ ੓׮ݶ ઴ৈաо੗. :data :home-impl :detail-impl :search-impl :database-impl :network-impl model … :home-api :detail-api :search-api :network-api :database-api
  78. Milestone 3. :data :feature :navigator-impl :navigator-api :common :app :common :designsystem

    :logger :buildcon fi g :buildcon fi g-stub :resources compileOnly … :search-impl :search-api :detail-impl :detail-api :search-api :search-impl :detail-api :detail-impl …
  79. زदী ࣻ੿ೞݶ Git Merge Conflictо ߊࢤೠ׮. ౱ ӏݽо ழ૕ࣻ۾ ੉۠

    ٜࠗ࠙ਸ ୭ࣗചೞח Ѫ੉ જ׮. ৘ܳ ٜݶ, Applicationীࢲ ୡӝചೞח Ѫٜ. :app ߽ݾ ઴੉ӝ :feature :home HomeData MyApplication :search SearchData
  80. // :app module class MyApplication : Application() { override fun

    onCreate() { ... HomeData.preload() + SearchData.preload() ... } } ࢲ۽ ׮ܲ PRীࢲ ୡӝച ೣࣻܳ ୶оೞݶ, Con fl ict੉ ߊࢤೠ׮.
  81. Dagger Hiltܳ ੉ਊೞৈ app ݽٕীࢲ feature ݽٕী ૒੽ ੽Ӕೞח Ѫ੉

    ইצ, feature ݽٕ੉ app ݽٕী ઁҕೞب۾ ߸҃ೞݶ ػ׮. :app ߽ݾ ઴੉ӝ :feature :home-impl HomeInitializer :sta rt up-api Initializer Set<Initializer> :search-impl SearchInitializer
  82. // :feature:search-impl module @Module @InstallIn(SingletonComponent::class) interface SearchModule { @IntoSet @Binds

    fun bindsInitializer(impl: SearchInitializer): Initializer } class SearchInitializer @Inject constructor() : Initializer { override operator fun invoke() { SearchData.preload(...) } } // :app module @HiltAndroidApp class MyApplication : Application() { @Inject lateinit var initializerSet: Set<@JvmSuppressWildcards Initializer> } // :feature:startup-api module interface Initializer { operator fun invoke() }
  83. Link: h tt ps://developer.android.com/topic/modularization/pa tt erns#app-modules জ੄ ੌࠗ ӝמ݅ਸ ನೣೞח

    জ ݽٕ. ౠ൤ ߈ࠂ੸ਵ۽ ࠽٘೧ঠ ೞח ѐߊ ױ҅ীࢲ ࣗਃغח दрਸ ױ୷ೡ ࣻ ੓׮. (9) ࢠ೒ জ ݽٕ ୶оೞӝ … … … …
  84. Milestone 4. :data :feature :navigator-impl :navigator-api :common :app :common :designsystem

    :logger :buildcon fi g :buildcon fi g-stub :resources compileOnly … :search-impl :search-api :detail-impl :detail-api :search-api :search-impl :detail-api :detail-impl … :search-sample :detail-sample :designsystem-sample
  85. ੿ܻ • Data, Common, Feature ࣽਵ۽ ױ҅੸ਵ۽ ݽٕച ೡ ࣻ

    ੓׮. • ௏٘ܳ ҕాചೞৈ, ݽٕ ୡӝച ࠺ਊਸ ઴੉ח Ѫ੉ જ׮. ◦ Version Catalog, Convention Plugins ١ • compileOnly + stubਸ ੉ਊೞৈ, flavor ੹౵ܳ ݄ਸ ࣻ ੓׮. (ex. BuildConfig) • -api, -impl ݽٕ۽ ܻ࠙ೞৈ, ৈ۞о૑ ੉੼ਸ оઉৢ ࣻ ੓׮. ◦ ੄ઓࢿ Ѻܻ, ࣽജଵઑ, ࠽٘दр ١ • runtimeOnlyܳ ੉ਊೞৈ, app ݽٕীࢲ ߄ۄࠁח ੄ઓࢿਸ ઴ੌ ࣻ ੓׮. • ݽٕਸ ܻ࠙ೠ׮Ҋ ޖઑѤ ࢤ࢑ࢿ੉ ֫ই૑૑ ঋח׮. 
 ࢤ࢑ࢿਸ ֫ੌ ࣻ ੓ח ߑߨਸ Ҋ޹ೞݴ ݽٕച೧ঠ ೠ׮. ◦ ߽ݾ, Conflict ઴੉ӝ ١