diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b9d20378a9..aa19a5f5ab 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -207,7 +207,7 @@ dependencies { implementation(projects.core.network) implementation(projects.core.ui) implementation(projects.core.model) - implementation(projects.core.di) + implementation(projects.core.data) implementation(projects.core.domain) // Feature — presentation diff --git a/app/src/androidTest/java/com/afternote/afternote_fe/test/TestHiltModules.kt b/app/src/androidTest/java/com/afternote/afternote_fe/test/TestHiltModules.kt index e53c4d7c54..f4ac30b43b 100644 --- a/app/src/androidTest/java/com/afternote/afternote_fe/test/TestHiltModules.kt +++ b/app/src/androidTest/java/com/afternote/afternote_fe/test/TestHiltModules.kt @@ -2,16 +2,9 @@ package com.afternote.afternote_fe.test import com.afternote.afternote_fe.reporting.ErrorReportingModule import com.afternote.core.common.reporting.ErrorReporter -import com.afternote.core.data.repoimpl.PhotoUploadRepositoryImpl -import com.afternote.core.data.repoimpl.UserProfileRepositoryImpl -import com.afternote.core.data.repoimpl.VideoUploadRepositoryImpl -import com.afternote.core.data.repoimpl.account.AccountRepositoryImpl -import com.afternote.core.di.CoreRepositoryModule -import com.afternote.core.domain.repository.PhotoUploadRepository +import com.afternote.core.data.di.CoreUserRepositoryModule import com.afternote.core.domain.repository.UserProfileRepository import com.afternote.core.domain.repository.UserRepository -import com.afternote.core.domain.repository.VideoUploadRepository -import com.afternote.core.domain.repository.account.AccountRepository import com.afternote.core.domain.repository.auth.AuthRepository import com.afternote.feature.mindrecord.data.di.MindRecordRepositoryModule import com.afternote.feature.mindrecord.data.repositoryimpl.MindRecordReceiverRepositoryImpl @@ -29,9 +22,9 @@ import javax.inject.Singleton @Module @TestInstallIn( components = [SingletonComponent::class], - replaces = [CoreRepositoryModule::class], + replaces = [CoreUserRepositoryModule::class], ) -object TestCoreRepositoryModule { +object TestCoreUserRepositoryModule { @Provides @Singleton fun provideAuthRepository(): AuthRepository = FakeAuthRepository(loggedIn = false) @@ -43,18 +36,6 @@ object TestCoreRepositoryModule { @Provides @Singleton fun provideUserProfileRepository(): UserProfileRepository = FakeUserProfileRepository() - - @Provides - @Singleton - fun provideAccountRepository(impl: AccountRepositoryImpl): AccountRepository = impl - - @Provides - @Singleton - fun providePhotoUploadRepository(impl: PhotoUploadRepositoryImpl): PhotoUploadRepository = impl - - @Provides - @Singleton - fun provideVideoUploadRepository(impl: VideoUploadRepositoryImpl): VideoUploadRepository = impl } @Module diff --git a/core/di/src/main/java/com/afternote/core/di/DispatcherModule.kt b/core/common/src/main/kotlin/com/afternote/core/common/di/DispatcherModule.kt similarity index 82% rename from core/di/src/main/java/com/afternote/core/di/DispatcherModule.kt rename to core/common/src/main/kotlin/com/afternote/core/common/di/DispatcherModule.kt index eb3dd661d2..8a543d85c9 100644 --- a/core/di/src/main/java/com/afternote/core/di/DispatcherModule.kt +++ b/core/common/src/main/kotlin/com/afternote/core/common/di/DispatcherModule.kt @@ -1,6 +1,5 @@ -package com.afternote.core.di +package com.afternote.core.common.di -import com.afternote.core.common.di.IoDispatcher import dagger.Module import dagger.Provides import dagger.hilt.InstallIn diff --git a/core/data/src/main/java/com/afternote/core/data/di/CoreAccountRepositoryModule.kt b/core/data/src/main/java/com/afternote/core/data/di/CoreAccountRepositoryModule.kt new file mode 100644 index 0000000000..0a54f8388f --- /dev/null +++ b/core/data/src/main/java/com/afternote/core/data/di/CoreAccountRepositoryModule.kt @@ -0,0 +1,18 @@ +package com.afternote.core.data.di + +import com.afternote.core.data.repoimpl.account.AccountRepositoryImpl +import com.afternote.core.domain.repository.account.AccountRepository +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +/** 구현체와 같은 모듈에 있으므로 `internal` 로 닫는다 — 바깥에서 impl 을 만질 수 없다. */ +@InstallIn(SingletonComponent::class) +@Module +internal interface CoreAccountRepositoryModule { + @Binds + @Singleton + fun bindAccountRepository(impl: AccountRepositoryImpl): AccountRepository +} diff --git a/core/data/src/main/java/com/afternote/core/data/di/CoreUploadRepositoryModule.kt b/core/data/src/main/java/com/afternote/core/data/di/CoreUploadRepositoryModule.kt new file mode 100644 index 0000000000..8eb3dd20a2 --- /dev/null +++ b/core/data/src/main/java/com/afternote/core/data/di/CoreUploadRepositoryModule.kt @@ -0,0 +1,24 @@ +package com.afternote.core.data.di + +import com.afternote.core.data.repoimpl.PhotoUploadRepositoryImpl +import com.afternote.core.data.repoimpl.VideoUploadRepositoryImpl +import com.afternote.core.domain.repository.PhotoUploadRepository +import com.afternote.core.domain.repository.VideoUploadRepository +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +/** 구현체와 같은 모듈에 있으므로 `internal` 로 닫는다 — 바깥에서 impl 을 만질 수 없다. */ +@InstallIn(SingletonComponent::class) +@Module +internal interface CoreUploadRepositoryModule { + @Binds + @Singleton + fun bindPhotoUploadRepository(impl: PhotoUploadRepositoryImpl): PhotoUploadRepository + + @Binds + @Singleton + fun bindVideoUploadRepository(impl: VideoUploadRepositoryImpl): VideoUploadRepository +} diff --git a/core/data/src/main/java/com/afternote/core/data/di/CoreUserRepositoryModule.kt b/core/data/src/main/java/com/afternote/core/data/di/CoreUserRepositoryModule.kt new file mode 100644 index 0000000000..4c9880b589 --- /dev/null +++ b/core/data/src/main/java/com/afternote/core/data/di/CoreUserRepositoryModule.kt @@ -0,0 +1,40 @@ +package com.afternote.core.data.di + +import com.afternote.core.data.repoimpl.UserProfileRepositoryImpl +import com.afternote.core.data.repoimpl.UserRepositoryImpl +import com.afternote.core.data.repoimpl.auth.AuthRepositoryImpl +import com.afternote.core.domain.repository.UserProfileRepository +import com.afternote.core.domain.repository.UserRepository +import com.afternote.core.domain.repository.auth.AuthRepository +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +/** + * 세션·사용자 저장소 바인딩. + * + * 이 모듈만 `public` 인 이유 — `app` 의 androidTest 가 + * `@TestInstallIn(replaces = [CoreUserRepositoryModule::class])` 로 이 셋을 페이크로 갈아끼운다. + * `replaces` 는 모듈 클래스를 참조하므로 `internal` 로 닫을 수 없다. + * + * 그래서 형제 모듈들과 달리 `interface` 가 아니라 `abstract class` 다. 바인딩 메서드가 `public` 이면 + * `'public' function exposes its 'internal' parameter type` 으로 컴파일되지 않는데, interface 멤버에는 + * 가시성을 줄 수 없다. abstract class 라야 클래스는 열어 두고 메서드만 `internal` 로 닫는다. + */ +@InstallIn(SingletonComponent::class) +@Module +abstract class CoreUserRepositoryModule { + @Binds + @Singleton + internal abstract fun bindAuthRepository(impl: AuthRepositoryImpl): AuthRepository + + @Binds + @Singleton + internal abstract fun bindUserRepository(impl: UserRepositoryImpl): UserRepository + + @Binds + @Singleton + internal abstract fun bindUserProfileRepository(impl: UserProfileRepositoryImpl): UserProfileRepository +} diff --git a/core/data/src/main/java/com/afternote/core/data/repoimpl/PhotoUploadRepositoryImpl.kt b/core/data/src/main/java/com/afternote/core/data/repoimpl/PhotoUploadRepositoryImpl.kt index 6afc24a6a2..ed643ef980 100644 --- a/core/data/src/main/java/com/afternote/core/data/repoimpl/PhotoUploadRepositoryImpl.kt +++ b/core/data/src/main/java/com/afternote/core/data/repoimpl/PhotoUploadRepositoryImpl.kt @@ -62,7 +62,7 @@ private fun resolveExtension(mime: String?): String { return resolved?.takeIf { it in ALLOWED_EXTENSIONS } ?: DEFAULT_EXTENSION } -class PhotoUploadRepositoryImpl +internal class PhotoUploadRepositoryImpl @Inject constructor( @param:ApplicationContext private val context: Context, diff --git a/core/data/src/main/java/com/afternote/core/data/repoimpl/UserProfileRepositoryImpl.kt b/core/data/src/main/java/com/afternote/core/data/repoimpl/UserProfileRepositoryImpl.kt index 71c474a575..4a6b0a2373 100644 --- a/core/data/src/main/java/com/afternote/core/data/repoimpl/UserProfileRepositoryImpl.kt +++ b/core/data/src/main/java/com/afternote/core/data/repoimpl/UserProfileRepositoryImpl.kt @@ -5,7 +5,7 @@ import com.afternote.core.domain.repository.UserProfileRepository import kotlinx.coroutines.flow.Flow import javax.inject.Inject -class UserProfileRepositoryImpl +internal class UserProfileRepositoryImpl @Inject constructor( private val dataSource: UserProfileDataSource, diff --git a/core/data/src/main/java/com/afternote/core/data/repoimpl/UserRepositoryImpl.kt b/core/data/src/main/java/com/afternote/core/data/repoimpl/UserRepositoryImpl.kt index 2f56b0d9eb..8c797f04d4 100644 --- a/core/data/src/main/java/com/afternote/core/data/repoimpl/UserRepositoryImpl.kt +++ b/core/data/src/main/java/com/afternote/core/data/repoimpl/UserRepositoryImpl.kt @@ -30,6 +30,8 @@ import kotlinx.coroutines.flow.update import javax.inject.Inject import com.afternote.core.data.mapper.delivery.toDomain as toDeliveryConditionsDomain +// `app` 의 androidTest(SettingCompletionAndroidTest)가 Hilt 를 우회해 이 구현을 직접 조립하므로 +// 형제 구현체들과 달리 `internal` 로 닫지 못한다. 닫으려면 그 테스트의 페이크 기반 개조가 선행돼야 한다 (#930). class UserRepositoryImpl @Inject constructor( diff --git a/core/data/src/main/java/com/afternote/core/data/repoimpl/VideoUploadRepositoryImpl.kt b/core/data/src/main/java/com/afternote/core/data/repoimpl/VideoUploadRepositoryImpl.kt index a51283c9d4..94a0f32c4a 100644 --- a/core/data/src/main/java/com/afternote/core/data/repoimpl/VideoUploadRepositoryImpl.kt +++ b/core/data/src/main/java/com/afternote/core/data/repoimpl/VideoUploadRepositoryImpl.kt @@ -23,7 +23,7 @@ import javax.inject.Named /** MIME 타입에서 확장자를 못 뽑았을 때 폴백. 대부분의 안드로이드 영상이 mp4 라 합리적 디폴트. */ private const val DEFAULT_VIDEO_EXTENSION = "mp4" -class VideoUploadRepositoryImpl +internal class VideoUploadRepositoryImpl @Inject constructor( @param:ApplicationContext private val context: Context, diff --git a/core/data/src/main/java/com/afternote/core/data/repoimpl/account/AccountRepositoryImpl.kt b/core/data/src/main/java/com/afternote/core/data/repoimpl/account/AccountRepositoryImpl.kt index 2ec06529fc..c7a4fe4c27 100644 --- a/core/data/src/main/java/com/afternote/core/data/repoimpl/account/AccountRepositoryImpl.kt +++ b/core/data/src/main/java/com/afternote/core/data/repoimpl/account/AccountRepositoryImpl.kt @@ -16,7 +16,7 @@ import com.afternote.core.network.model.requireStatus import com.afternote.core.network.service.AccountApiService import javax.inject.Inject -class AccountRepositoryImpl +internal class AccountRepositoryImpl @Inject constructor( private val accountApiService: AccountApiService, diff --git a/core/data/src/main/java/com/afternote/core/data/repoimpl/auth/AuthRepositoryImpl.kt b/core/data/src/main/java/com/afternote/core/data/repoimpl/auth/AuthRepositoryImpl.kt index d34b0d9c37..c083076f02 100644 --- a/core/data/src/main/java/com/afternote/core/data/repoimpl/auth/AuthRepositoryImpl.kt +++ b/core/data/src/main/java/com/afternote/core/data/repoimpl/auth/AuthRepositoryImpl.kt @@ -24,7 +24,7 @@ import kotlinx.coroutines.flow.Flow import java.io.IOException import javax.inject.Inject -class AuthRepositoryImpl +internal class AuthRepositoryImpl @Inject constructor( private val tokenDataSource: TokenDataSource, diff --git a/core/di/.gitignore b/core/di/.gitignore deleted file mode 100644 index 42afabfd2a..0000000000 --- a/core/di/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/core/di/build.gradle.kts b/core/di/build.gradle.kts deleted file mode 100644 index b1b575e6d9..0000000000 --- a/core/di/build.gradle.kts +++ /dev/null @@ -1,16 +0,0 @@ -plugins { - id("afternote.android.library") - id("afternote.android.hilt") -} - -android { - namespace = "com.afternote.core.di" -} - -dependencies { - implementation(libs.androidx.work.runtime.ktx) - implementation(projects.core.common) - implementation(projects.core.data) - implementation(projects.core.domain) - implementation(libs.kakao.sdk.auth) -} diff --git a/core/di/consumer-rules.pro b/core/di/consumer-rules.pro deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/core/di/proguard-rules.pro b/core/di/proguard-rules.pro deleted file mode 100644 index 481bb43481..0000000000 --- a/core/di/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/core/di/src/main/AndroidManifest.xml b/core/di/src/main/AndroidManifest.xml deleted file mode 100644 index 44008a4332..0000000000 --- a/core/di/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/core/di/src/main/java/com/afternote/core/di/CoreRepositoryModule.kt b/core/di/src/main/java/com/afternote/core/di/CoreRepositoryModule.kt deleted file mode 100644 index 997b34dfb1..0000000000 --- a/core/di/src/main/java/com/afternote/core/di/CoreRepositoryModule.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.afternote.core.di - -import com.afternote.core.data.repoimpl.PhotoUploadRepositoryImpl -import com.afternote.core.data.repoimpl.UserProfileRepositoryImpl -import com.afternote.core.data.repoimpl.UserRepositoryImpl -import com.afternote.core.data.repoimpl.VideoUploadRepositoryImpl -import com.afternote.core.data.repoimpl.account.AccountRepositoryImpl -import com.afternote.core.data.repoimpl.auth.AuthRepositoryImpl -import com.afternote.core.domain.repository.PhotoUploadRepository -import com.afternote.core.domain.repository.UserProfileRepository -import com.afternote.core.domain.repository.UserRepository -import com.afternote.core.domain.repository.VideoUploadRepository -import com.afternote.core.domain.repository.account.AccountRepository -import com.afternote.core.domain.repository.auth.AuthRepository -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@InstallIn(SingletonComponent::class) -@Module -interface CoreRepositoryModule { - @Binds - @Singleton - fun bindAccountRepository(impl: AccountRepositoryImpl): AccountRepository - - @Binds - @Singleton - fun bindPhotoUploadRepository(impl: PhotoUploadRepositoryImpl): PhotoUploadRepository - - @Binds - @Singleton - fun bindVideoUploadRepository(impl: VideoUploadRepositoryImpl): VideoUploadRepository - - @Binds - @Singleton - fun bindAuthRepository(impl: AuthRepositoryImpl): AuthRepository - - @Binds - @Singleton - fun bindUserRepository(impl: UserRepositoryImpl): UserRepository - - @Binds - @Singleton - fun bindUserProfileRepository(impl: UserProfileRepositoryImpl): UserProfileRepository -} diff --git a/settings.gradle.kts b/settings.gradle.kts index c6b9973749..e7e234aafc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -33,7 +33,6 @@ include(":app") include(":core:common") include(":core:data") include(":core:datastore") -include(":core:di") include(":core:domain") include(":core:model") include(":core:network")