From 9dd051afd55c883f3a72eab11037cb124b487ad4 Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Thu, 18 Dec 2025 15:59:06 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F=20=EB=A9=80=ED=8B=B0?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=95=84=ED=82=A4=ED=85=8D=EC=B2=98=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Convention Plugin 기반 빌드 로직 구성 (build-logic) - Feature 레이어: login 모듈 - Domain 레이어: 비즈니스 로직 모듈 - Data 레이어: 데이터 소스 모듈 - Core 레이어: 공통 모듈 - ui: State/SideEffect 기반 UI 구조 - util: 유틸리티 - navigation: 네비게이션 - design-system: 디자인 시스템 - network: 네트워크 - TYPESAFE_PROJECT_ACCESSORS 활성화 - Ktlint 14.0.1 전역 적용 🤖 Generated with [Firebender](https://firebender.com) Co-Authored-By: Firebender --- .editorconfig | 7 +++ app/build.gradle.kts | 33 ++++------- build-logic/convention/build.gradle.kts | 55 +++++++++++++++++++ .../AndroidApplicationConventionPlugin.kt | 22 ++++++++ .../AndroidComposeConventionPlugin.kt | 21 +++++++ .../AndroidLibraryConventionPlugin.kt | 25 +++++++++ .../convention/BuildLogicConventionPlugin.kt | 10 ++++ .../twix/convention/DataConventionPlugin.kt | 16 ++++++ .../convention/FeatureConventionPlugin.kt | 20 +++++++ .../convention/JvmLibraryConventionPlugin.kt | 32 +++++++++++ .../twix/convention/KoinConventionPlugin.kt | 11 ++++ .../com/twix/convention/extension/Android.kt | 29 ++++++++++ .../com/twix/convention/extension/Compose.kt | 25 +++++++++ .../DependencyHandlerScopeExtension.kt | 25 +++++++++ .../convention/extension/ProjectExtension.kt | 13 +++++ .../extension/VersionCatalogExtension.kt | 24 ++++++++ build-logic/settings.gradle.kts | 22 ++++++++ core/design-system/build.gradle.kts | 8 +++ .../main/java/com/twix/designsystem/.gitkeep | 1 + core/navigation/build.gradle.kts | 7 +++ .../main/java/com/twix/navigation/.gitkeep | 1 + core/network/build.gradle.kts | 17 ++++++ .../src/main/java/com/twix/network/.gitkeep | 1 + core/ui/build.gradle.kts | 12 ++++ .../main/java/com/twix/ui/base/SideEffect.kt | 3 + .../java/com/twix/ui/base/SideEffectHolder.kt | 13 +++++ .../src/main/java/com/twix/ui/base/State.kt | 3 + .../main/java/com/twix/ui/base/StateHolder.kt | 20 +++++++ core/util/build.gradle.kts | 7 +++ .../util/src/main/java/com/twix/util/.gitkeep | 1 + data/build.gradle.kts | 12 ++++ data/src/main/java/com/twix/data/.gitkeep | 1 + domain/build.gradle.kts | 3 + domain/src/main/java/com/twix/domain/.gitkeep | 1 + feature/login/build.gradle.kts | 7 +++ .../androidTest/java/com/twix/login/.gitkeep | 0 feature/login/src/main/AndroidManifest.xml | 12 ++++ .../main/java/com/twix/login/LoginActivity.kt | 10 ++++ .../src/test/java/com/twix/login/.gitkeep | 0 settings.gradle.kts | 11 ++++ 40 files changed, 518 insertions(+), 23 deletions(-) create mode 100644 .editorconfig create mode 100644 build-logic/convention/build.gradle.kts create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/AndroidApplicationConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/BuildLogicConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/JvmLibraryConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/KoinConventionPlugin.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/extension/Android.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/extension/Compose.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/extension/DependencyHandlerScopeExtension.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/extension/ProjectExtension.kt create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/extension/VersionCatalogExtension.kt create mode 100644 build-logic/settings.gradle.kts create mode 100644 core/design-system/build.gradle.kts create mode 100644 core/design-system/src/main/java/com/twix/designsystem/.gitkeep create mode 100644 core/navigation/build.gradle.kts create mode 100644 core/navigation/src/main/java/com/twix/navigation/.gitkeep create mode 100644 core/network/build.gradle.kts create mode 100644 core/network/src/main/java/com/twix/network/.gitkeep create mode 100644 core/ui/build.gradle.kts create mode 100644 core/ui/src/main/java/com/twix/ui/base/SideEffect.kt create mode 100644 core/ui/src/main/java/com/twix/ui/base/SideEffectHolder.kt create mode 100644 core/ui/src/main/java/com/twix/ui/base/State.kt create mode 100644 core/ui/src/main/java/com/twix/ui/base/StateHolder.kt create mode 100644 core/util/build.gradle.kts create mode 100644 core/util/src/main/java/com/twix/util/.gitkeep create mode 100644 data/build.gradle.kts create mode 100644 data/src/main/java/com/twix/data/.gitkeep create mode 100644 domain/build.gradle.kts create mode 100644 domain/src/main/java/com/twix/domain/.gitkeep create mode 100644 feature/login/build.gradle.kts create mode 100644 feature/login/src/androidTest/java/com/twix/login/.gitkeep create mode 100644 feature/login/src/main/AndroidManifest.xml create mode 100644 feature/login/src/main/java/com/twix/login/LoginActivity.kt create mode 100644 feature/login/src/test/java/com/twix/login/.gitkeep diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7acb6f3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*] +ktlint_function_naming_ignore_when_annotated_with = Composable + +[{*.kt,*.kts}] +ktlint_standard_package-name = disabled \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index bbcae36..c1b6468 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,20 +1,15 @@ plugins { - alias(libs.plugins.android.application) - alias(libs.plugins.kotlin.android) + alias(libs.plugins.twix.android.application) + alias(libs.plugins.twix.koin) } android { namespace = "com.yapp.twix" - compileSdk = 35 defaultConfig { applicationId = "com.yapp.twix" - minSdk = 28 - targetSdk = 35 versionCode = 1 versionName = "1.0" - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildTypes { @@ -26,23 +21,15 @@ android { ) } } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = "17" - } } dependencies { - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.appcompat) - implementation(libs.material) - - testImplementation(libs.junit) - androidTestImplementation(libs.androidx.junit) - androidTestImplementation(libs.androidx.espresso.core) + implementation(projects.core.designSystem) + implementation(projects.core.network) + implementation(projects.core.navigation) + implementation(projects.core.ui) + implementation(projects.core.util) + implementation(projects.data) + implementation(projects.domain) + implementation(projects.feature.login) } diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts new file mode 100644 index 0000000..289fe7d --- /dev/null +++ b/build-logic/convention/build.gradle.kts @@ -0,0 +1,55 @@ +plugins { + `kotlin-dsl` +} + +group = "com.twix.convention" + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +kotlin { + jvmToolchain(17) +} + +dependencies { + compileOnly(libs.android.gradle.plugin) + compileOnly(libs.kotlin.gradle.plugin) + compileOnly(libs.compose.gradle.plugin) + compileOnly(libs.ksp.gradle.plugin) + compileOnly(libs.android.junit5.gradle.plugin) +} + +gradlePlugin { + plugins { + register("androidApplication"){ + id = "twix.android.application" + implementationClass = "com.twix.convention.AndroidApplicationConventionPlugin" + } + register("androidLibrary") { + id = "twix.android.library" + implementationClass = "com.twix.convention.AndroidLibraryConventionPlugin" + } + register("androidCompose"){ + id = "twix.android.compose" + implementationClass = "com.twix.convention.AndroidComposeConventionPlugin" + } + register("feature"){ + id = "twix.feature" + implementationClass = "com.twix.convention.FeatureConventionPlugin" + } + register("koin"){ + id = "twix.koin" + implementationClass = "com.twix.convention.KoinConventionPlugin" + } + register("javaLibrary"){ + id = "twix.java.library" + implementationClass = "com.twix.convention.JvmLibraryConventionPlugin" + } + register("data"){ + id = "twix.data" + implementationClass = "com.twix.convention.DataConventionPlugin" + } + } +} diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidApplicationConventionPlugin.kt new file mode 100644 index 0000000..b130889 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidApplicationConventionPlugin.kt @@ -0,0 +1,22 @@ +package com.twix.convention + +import com.android.build.api.dsl.ApplicationExtension +import com.twix.convention.extension.applyPlugins +import com.twix.convention.extension.configureAndroid +import com.twix.convention.extension.implementation +import com.twix.convention.extension.library +import com.twix.convention.extension.libs +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies + +class AndroidApplicationConventionPlugin : BuildLogicConventionPlugin({ + applyPlugins("com.android.application", "org.jetbrains.kotlin.android") + + extensions.configure { + configureAndroid(this) + } + + dependencies { + implementation(libs.library("kotlinx-serialization-json")) + } +}) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt new file mode 100644 index 0000000..337b91e --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt @@ -0,0 +1,21 @@ +package com.twix.convention + +import com.android.build.api.dsl.LibraryExtension +import com.twix.convention.extension.* +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies + +class AndroidComposeConventionPlugin : BuildLogicConventionPlugin({ + applyPlugins("org.jetbrains.kotlin.plugin.compose") + + extensions.configure { + configureCompose(this) + } + + dependencies { + val bom = platform(libs.library("compose-bom")) + implementation(bom) + implementation(libs.bundle("compose")) + debugImplementation(libs.bundle("compose-debug")) + } +}) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt new file mode 100644 index 0000000..6920738 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt @@ -0,0 +1,25 @@ +package com.twix.convention + +import com.android.build.api.dsl.LibraryExtension +import com.twix.convention.extension.* +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies + +class AndroidLibraryConventionPlugin : BuildLogicConventionPlugin({ + applyPlugins( + "com.android.library", + "org.jetbrains.kotlin.android", + "de.mannodermaus.android-junit5" + ) + + extensions.configure { + configureAndroid(this) + defaultConfig.testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + dependencies { + implementation(libs.library("kotlinx-coroutines-core")) + testImplementation(libs.bundle("test-unit")) + androidTestImplementation(libs.library("androidx-test-ext-junit")) + } +}) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/BuildLogicConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/BuildLogicConventionPlugin.kt new file mode 100644 index 0000000..4929313 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/BuildLogicConventionPlugin.kt @@ -0,0 +1,10 @@ +package com.twix.convention + +import org.gradle.api.Plugin +import org.gradle.api.Project + +abstract class BuildLogicConventionPlugin(private val block: Project.() -> Unit) : Plugin { + final override fun apply(target: Project) { + with(target, block = block) + } +} diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt new file mode 100644 index 0000000..014078d --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt @@ -0,0 +1,16 @@ +package com.twix.convention + +import com.twix.convention.extension.* +import org.gradle.kotlin.dsl.dependencies + +class DataConventionPlugin : BuildLogicConventionPlugin({ + applyPlugins( + "twix.android.library", + "org.jetbrains.kotlin.plugin.serialization", + "twix.koin" + ) + + dependencies { + implementation(libs.library("kotlinx-coroutines-core")) + } +}) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt new file mode 100644 index 0000000..4769500 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt @@ -0,0 +1,20 @@ +package com.twix.convention + +import com.twix.convention.extension.applyPlugins +import com.twix.convention.extension.implementation +import org.gradle.kotlin.dsl.dependencies + +class FeatureConventionPlugin : BuildLogicConventionPlugin({ + applyPlugins( + "twix.android.library", + "twix.android.compose", + "twix.koin", + ) + + dependencies { + implementation(project(":core:design-system")) + implementation(project(":core:navigation")) + implementation(project(":core:ui")) + implementation(project(":domain")) + } +}) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/JvmLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/JvmLibraryConventionPlugin.kt new file mode 100644 index 0000000..ce04586 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/JvmLibraryConventionPlugin.kt @@ -0,0 +1,32 @@ +package com.twix.convention + +import com.twix.convention.extension.* +import org.gradle.api.JavaVersion +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.tasks.testing.Test +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension + +class JvmLibraryConventionPlugin : BuildLogicConventionPlugin({ + applyPlugins("org.jetbrains.kotlin.jvm") + + extensions.configure { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + extensions.configure { + jvmToolchain(libs.version("java").requiredVersion.toInt()) + } + + tasks.withType { + useJUnitPlatform() + } + + dependencies { + implementation(libs.library("kotlinx-coroutines-core-jvm")) + testImplementation(libs.bundle("test-unit")) + } +}) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/KoinConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/KoinConventionPlugin.kt new file mode 100644 index 0000000..d4b3877 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/KoinConventionPlugin.kt @@ -0,0 +1,11 @@ +package com.twix.convention + +import com.twix.convention.extension.* +import org.gradle.kotlin.dsl.dependencies + +class KoinConventionPlugin : BuildLogicConventionPlugin({ + dependencies { + implementation(platform(libs.library("koin-bom"))) + implementation(libs.bundle("koin")) + } +}) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/extension/Android.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/Android.kt new file mode 100644 index 0000000..a2539cd --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/Android.kt @@ -0,0 +1,29 @@ +package com.twix.convention.extension + +import com.android.build.api.dsl.CommonExtension +import org.gradle.api.JavaVersion +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension + +internal fun Project.configureAndroid(extension: CommonExtension<*, *, *, *, *, *>) { + val javaVersionInt = libs.version("java").requiredVersion.toInt() + val javaVersion = JavaVersion.toVersion(javaVersionInt) + + extension.apply { + compileSdk = libs.version("compileSdk").requiredVersion.toInt() + + defaultConfig { + minSdk = libs.version("minSdk").requiredVersion.toInt() + } + + compileOptions { + sourceCompatibility = javaVersion + targetCompatibility = javaVersion + } + + extensions.configure { + jvmToolchain(javaVersionInt) + } + } +} diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/extension/Compose.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/Compose.kt new file mode 100644 index 0000000..7a7a1ed --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/Compose.kt @@ -0,0 +1,25 @@ +package com.twix.convention.extension + +import com.android.build.api.dsl.CommonExtension +import org.gradle.api.Project +import org.gradle.kotlin.dsl.dependencies + +internal fun Project.configureCompose(extension: CommonExtension<*, *, *, *, *, *>) { + extension.apply { + buildFeatures { + compose = true + } + + dependencies { + val composeBom = libs.library("compose-bom") + implementation(platform(composeBom)) + implementation(libs.bundle("compose")) + + androidTestImplementation(platform(composeBom)) + androidTestImplementation(libs.library("compose-ui-test-junit4")) + debugImplementation(libs.bundle("compose-debug")) + + implementation(libs.library("material")) + } + } +} diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/extension/DependencyHandlerScopeExtension.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/DependencyHandlerScopeExtension.kt new file mode 100644 index 0000000..fe7303f --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/DependencyHandlerScopeExtension.kt @@ -0,0 +1,25 @@ +package com.twix.convention.extension + +import org.gradle.api.Project +import org.gradle.api.provider.Provider +import org.gradle.kotlin.dsl.DependencyHandlerScope + +fun DependencyHandlerScope.implementation(project: Project) { + "implementation"(project) +} + +fun DependencyHandlerScope.implementation(provider: Provider<*>) { + "implementation"(provider) +} + +fun DependencyHandlerScope.debugImplementation(provider: Provider<*>) { + "debugImplementation"(provider) +} + +fun DependencyHandlerScope.androidTestImplementation(provider: Provider<*>) { + "androidTestImplementation"(provider) +} + +fun DependencyHandlerScope.testImplementation(provider: Provider<*>) { + "testImplementation"(provider) +} diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/extension/ProjectExtension.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/ProjectExtension.kt new file mode 100644 index 0000000..98b75c9 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/ProjectExtension.kt @@ -0,0 +1,13 @@ +package com.twix.convention.extension + +import org.gradle.api.Project +import org.gradle.api.artifacts.VersionCatalog +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.kotlin.dsl.getByType + +internal val Project.libs: VersionCatalog + get() = extensions.getByType().named("libs") + +internal fun Project.applyPlugins(vararg plugins: String) { + plugins.forEach(pluginManager::apply) +} diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/extension/VersionCatalogExtension.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/VersionCatalogExtension.kt new file mode 100644 index 0000000..2cda310 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/VersionCatalogExtension.kt @@ -0,0 +1,24 @@ +package com.twix.convention.extension + +import org.gradle.api.artifacts.ExternalModuleDependencyBundle +import org.gradle.api.artifacts.MinimalExternalModuleDependency +import org.gradle.api.artifacts.VersionCatalog +import org.gradle.api.artifacts.VersionConstraint +import org.gradle.api.provider.Provider + +internal fun VersionCatalog.bundle(bundleName: String): Provider { + return findBundle(bundleName).orElseThrow { + NoSuchElementException("Bundle with name $bundleName not found in the catalog") + } +} + +internal fun VersionCatalog.library(libraryName: String): Provider { + return findLibrary(libraryName).orElseThrow { + NoSuchElementException("Library with name $libraryName not found in the catalog") + } +} + +internal fun VersionCatalog.version(versionName: String): VersionConstraint = + findVersion(versionName).orElseThrow { + NoSuchElementException("Version with name $versionName not found in the catalog") + } diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 0000000..143331a --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,22 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + } + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} + +rootProject.name = "build-logic" +include(":convention") diff --git a/core/design-system/build.gradle.kts b/core/design-system/build.gradle.kts new file mode 100644 index 0000000..c491b43 --- /dev/null +++ b/core/design-system/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + alias(libs.plugins.twix.android.library) + alias(libs.plugins.twix.android.compose) +} + +android { + namespace = "com.twix.designsystem" +} diff --git a/core/design-system/src/main/java/com/twix/designsystem/.gitkeep b/core/design-system/src/main/java/com/twix/designsystem/.gitkeep new file mode 100644 index 0000000..379ad9b --- /dev/null +++ b/core/design-system/src/main/java/com/twix/designsystem/.gitkeep @@ -0,0 +1 @@ +# This file ensures the directory is tracked by git diff --git a/core/navigation/build.gradle.kts b/core/navigation/build.gradle.kts new file mode 100644 index 0000000..7c7289f --- /dev/null +++ b/core/navigation/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + alias(libs.plugins.twix.android.library) +} + +android { + namespace = "com.twix.navigation" +} diff --git a/core/navigation/src/main/java/com/twix/navigation/.gitkeep b/core/navigation/src/main/java/com/twix/navigation/.gitkeep new file mode 100644 index 0000000..379ad9b --- /dev/null +++ b/core/navigation/src/main/java/com/twix/navigation/.gitkeep @@ -0,0 +1 @@ +# This file ensures the directory is tracked by git diff --git a/core/network/build.gradle.kts b/core/network/build.gradle.kts new file mode 100644 index 0000000..a1ab0c1 --- /dev/null +++ b/core/network/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + alias(libs.plugins.twix.android.library) + alias(libs.plugins.twix.koin) + alias(libs.plugins.serialization) +} + +android { + namespace = "com.twix.network" + + buildFeatures { + buildConfig = true + } +} + +dependencies { + implementation(libs.bundles.network) +} diff --git a/core/network/src/main/java/com/twix/network/.gitkeep b/core/network/src/main/java/com/twix/network/.gitkeep new file mode 100644 index 0000000..379ad9b --- /dev/null +++ b/core/network/src/main/java/com/twix/network/.gitkeep @@ -0,0 +1 @@ +# This file ensures the directory is tracked by git diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts new file mode 100644 index 0000000..2f73a37 --- /dev/null +++ b/core/ui/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + alias(libs.plugins.twix.android.library) + alias(libs.plugins.twix.android.compose) +} + +android { + namespace = "com.twix.ui" +} + +dependencies { + implementation(projects.core.designSystem) +} diff --git a/core/ui/src/main/java/com/twix/ui/base/SideEffect.kt b/core/ui/src/main/java/com/twix/ui/base/SideEffect.kt new file mode 100644 index 0000000..9d381bf --- /dev/null +++ b/core/ui/src/main/java/com/twix/ui/base/SideEffect.kt @@ -0,0 +1,3 @@ +package com.twix.ui.base + +interface SideEffect diff --git a/core/ui/src/main/java/com/twix/ui/base/SideEffectHolder.kt b/core/ui/src/main/java/com/twix/ui/base/SideEffectHolder.kt new file mode 100644 index 0000000..83d0944 --- /dev/null +++ b/core/ui/src/main/java/com/twix/ui/base/SideEffectHolder.kt @@ -0,0 +1,13 @@ +package com.twix.ui.base + +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.receiveAsFlow + +class SideEffectHolder { + private val channel = Channel(Channel.BUFFERED) + val flow = channel.receiveAsFlow() + + suspend fun emit(effect: S) { + channel.send(effect) + } +} diff --git a/core/ui/src/main/java/com/twix/ui/base/State.kt b/core/ui/src/main/java/com/twix/ui/base/State.kt new file mode 100644 index 0000000..6849029 --- /dev/null +++ b/core/ui/src/main/java/com/twix/ui/base/State.kt @@ -0,0 +1,3 @@ +package com.twix.ui.base + +interface State diff --git a/core/ui/src/main/java/com/twix/ui/base/StateHolder.kt b/core/ui/src/main/java/com/twix/ui/base/StateHolder.kt new file mode 100644 index 0000000..647aeae --- /dev/null +++ b/core/ui/src/main/java/com/twix/ui/base/StateHolder.kt @@ -0,0 +1,20 @@ +package com.twix.ui.base + +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update + +class StateHolder( + initialState: S, +) { + private val _state = MutableStateFlow(initialState) + val state: StateFlow = _state.asStateFlow() + + val current: S + get() = _state.value + + fun reduce(reducer: S.() -> S) { + _state.update { it.reducer() } + } +} diff --git a/core/util/build.gradle.kts b/core/util/build.gradle.kts new file mode 100644 index 0000000..03c8518 --- /dev/null +++ b/core/util/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + alias(libs.plugins.twix.android.library) +} + +android { + namespace = "com.twix.util" +} diff --git a/core/util/src/main/java/com/twix/util/.gitkeep b/core/util/src/main/java/com/twix/util/.gitkeep new file mode 100644 index 0000000..379ad9b --- /dev/null +++ b/core/util/src/main/java/com/twix/util/.gitkeep @@ -0,0 +1 @@ +# This file ensures the directory is tracked by git diff --git a/data/build.gradle.kts b/data/build.gradle.kts new file mode 100644 index 0000000..5c16cee --- /dev/null +++ b/data/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + alias(libs.plugins.twix.data) +} + +android { + namespace = "com.twix.data" +} + +dependencies { + implementation(projects.domain) + implementation(projects.core.network) +} diff --git a/data/src/main/java/com/twix/data/.gitkeep b/data/src/main/java/com/twix/data/.gitkeep new file mode 100644 index 0000000..379ad9b --- /dev/null +++ b/data/src/main/java/com/twix/data/.gitkeep @@ -0,0 +1 @@ +# This file ensures the directory is tracked by git diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts new file mode 100644 index 0000000..ba7b83c --- /dev/null +++ b/domain/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + alias(libs.plugins.twix.java.library) +} diff --git a/domain/src/main/java/com/twix/domain/.gitkeep b/domain/src/main/java/com/twix/domain/.gitkeep new file mode 100644 index 0000000..379ad9b --- /dev/null +++ b/domain/src/main/java/com/twix/domain/.gitkeep @@ -0,0 +1 @@ +# This file ensures the directory is tracked by git diff --git a/feature/login/build.gradle.kts b/feature/login/build.gradle.kts new file mode 100644 index 0000000..87722a6 --- /dev/null +++ b/feature/login/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + alias(libs.plugins.twix.feature) +} + +android { + namespace = "com.twix.login" +} diff --git a/feature/login/src/androidTest/java/com/twix/login/.gitkeep b/feature/login/src/androidTest/java/com/twix/login/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/feature/login/src/main/AndroidManifest.xml b/feature/login/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9d89216 --- /dev/null +++ b/feature/login/src/main/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/feature/login/src/main/java/com/twix/login/LoginActivity.kt b/feature/login/src/main/java/com/twix/login/LoginActivity.kt new file mode 100644 index 0000000..18a386f --- /dev/null +++ b/feature/login/src/main/java/com/twix/login/LoginActivity.kt @@ -0,0 +1,10 @@ +package com.twix.login + +import android.os.Bundle +import androidx.activity.ComponentActivity + +class LoginActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + } +} diff --git a/feature/login/src/test/java/com/twix/login/.gitkeep b/feature/login/src/test/java/com/twix/login/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/settings.gradle.kts b/settings.gradle.kts index 6ff22cd..9cc7038 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,4 +1,5 @@ pluginManagement { + includeBuild("build-logic") repositories { google { content { @@ -22,4 +23,14 @@ dependencyResolutionManagement { rootProject.name = "Twix" +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + include(":app") +include(":domain") +include(":data") +include(":feature:login") +include(":core:util") +include(":core:ui") +include(":core:navigation") +include(":core:design-system") +include(":core:network") From 5535aa5be9ccd303eec563f9dd77b5c08104b446 Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Sat, 20 Dec 2025 17:43:27 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=E2=9E=95=20navigation=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=EC=97=90=20Compose=20=ED=94=8C=EB=9F=AC=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/navigation/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/core/navigation/build.gradle.kts b/core/navigation/build.gradle.kts index 7c7289f..3217406 100644 --- a/core/navigation/build.gradle.kts +++ b/core/navigation/build.gradle.kts @@ -1,5 +1,6 @@ plugins { alias(libs.plugins.twix.android.library) + alias(libs.plugins.twix.android.compose) } android { From 0ec91a4ceb548783a6fdc958c6b0c0eed9bf4421 Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Sat, 20 Dec 2025 18:32:05 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20data=20convention=20pl?= =?UTF-8?q?ugin=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Data 모듈의 의존성을 DataConventionPlugin으로 이동하고, FeatureConventionPlugin의 플러그인 적용 방식을 개선하여 빌드 로직을 더욱 체계적으로 관리 --- .../kotlin/com/twix/convention/DataConventionPlugin.kt | 2 ++ .../com/twix/convention/FeatureConventionPlugin.kt | 10 ++++------ data/build.gradle.kts | 5 ----- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt index 014078d..4d20378 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt @@ -12,5 +12,7 @@ class DataConventionPlugin : BuildLogicConventionPlugin({ dependencies { implementation(libs.library("kotlinx-coroutines-core")) + implementation(project(":domain")) + implementation(project(":core:network")) } }) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt index 4769500..1f56f4c 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt @@ -1,15 +1,13 @@ package com.twix.convention -import com.twix.convention.extension.applyPlugins import com.twix.convention.extension.implementation +import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.dependencies class FeatureConventionPlugin : BuildLogicConventionPlugin({ - applyPlugins( - "twix.android.library", - "twix.android.compose", - "twix.koin", - ) + apply() + apply() + apply() dependencies { implementation(project(":core:design-system")) diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 5c16cee..f61fa0e 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -5,8 +5,3 @@ plugins { android { namespace = "com.twix.data" } - -dependencies { - implementation(projects.domain) - implementation(projects.core.network) -} From 6e5955925b71a3060cd693ae0b4244fe961a06b0 Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Sat, 20 Dec 2025 18:33:23 +0900 Subject: [PATCH 4/6] =?UTF-8?q?=E2=9E=96=20DataConventionPlugin=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20coroutines?= =?UTF-8?q?=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/com/twix/convention/DataConventionPlugin.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt index 4d20378..ea060e3 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt @@ -11,7 +11,6 @@ class DataConventionPlugin : BuildLogicConventionPlugin({ ) dependencies { - implementation(libs.library("kotlinx-coroutines-core")) implementation(project(":domain")) implementation(project(":core:network")) } From 5323bd06093745f2f8952f75b5e6dfafbfd9cbba Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Sat, 20 Dec 2025 18:35:54 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20JvmLibraryConventionPl?= =?UTF-8?q?ugin=20Java=20=EB=B2=84=EC=A0=84=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/twix/convention/JvmLibraryConventionPlugin.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/JvmLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/JvmLibraryConventionPlugin.kt index ce04586..ae4b07b 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/JvmLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/JvmLibraryConventionPlugin.kt @@ -12,13 +12,16 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension class JvmLibraryConventionPlugin : BuildLogicConventionPlugin({ applyPlugins("org.jetbrains.kotlin.jvm") + val javaVersionInt = libs.version("java").requiredVersion.toInt() + val javaVersion = JavaVersion.toVersion(javaVersionInt) + extensions.configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = javaVersion + targetCompatibility = javaVersion } extensions.configure { - jvmToolchain(libs.version("java").requiredVersion.toInt()) + jvmToolchain(javaVersionInt) } tasks.withType { From 71d95d2c1de451db2e05753c19cfc98d4ae71c07 Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Sat, 20 Dec 2025 18:55:08 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=E2=9C=A8=20AndroidComposeConventionPlugin?= =?UTF-8?q?=EC=97=90=20application=20=EB=AA=A8=EB=93=88=20=EC=A7=80?= =?UTF-8?q?=EC=9B=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../convention/AndroidComposeConventionPlugin.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt index 337b91e..b0a7a90 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt @@ -1,5 +1,6 @@ package com.twix.convention +import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.dsl.LibraryExtension import com.twix.convention.extension.* import org.gradle.kotlin.dsl.configure @@ -8,8 +9,16 @@ import org.gradle.kotlin.dsl.dependencies class AndroidComposeConventionPlugin : BuildLogicConventionPlugin({ applyPlugins("org.jetbrains.kotlin.plugin.compose") - extensions.configure { - configureCompose(this) + pluginManager.withPlugin("com.android.application") { + extensions.configure { + configureCompose(this) + } + } + + pluginManager.withPlugin("com.android.library") { + extensions.configure { + configureCompose(this) + } } dependencies {