Skip to content

refactor(core): core:di 모듈 삭제 — 바인딩을 구현 옆으로 옮기고 repository impl 을 internal 로 (closes 930) [base: develop] - #969

Merged
OnlyReadOneBook merged 3 commits into
developfrom
refactor/930
Aug 24, 2026
Merged

OnlyReadOneBook merged 3 commits into
developfrom
refactor/930

Conversation

@OnlyReadOneBook

Copy link
Copy Markdown
Collaborator

Closes #930

파일 2개짜리 core:di 가 존재하는 탓에 core:data 의 repository 구현 6개가 전부 public 으로 열려 있었다. internal 은 모듈 스코프인데 바인딩이 다른 모듈에 있으니 닫을 방법이 없었다. 바인딩을 구현 옆으로 옮기고 모듈을 삭제한다.

변경

1. CoreRepositoryModule → core:data 로 이동하면서 3개로 분할

모듈 선언 바인딩 왜
CoreUserRepositoryModule abstract class + internal abstract @Binds Auth · User · UserProfile androidTest 가 @TestInstallIn(replaces = …) 로 대체하는 대상
CoreAccountRepositoryModule internal interface Account 대체 대상 아님 → 통째로 닫음
CoreUploadRepositoryModule internal interface Photo · Video 위와 동일

분할한 이유는 replaces 가 전부 아니면 전무이기 때문이다. 통짜 모듈이면 androidTest 가 실물로 쓰는 3종(Account·Photo·Video)을 테스트 쪽에서 다시 바인딩해야 하고, 그 인자 타입으로 구현체가 노출돼 internal 화가 원천 봉쇄된다. 쪼개면 페이크로 갈아끼울 모듈만 replaces 하면 되고 나머지는 손댈 일이 없다.

CoreUserRepositoryModule 만 interface 가 아닌 이유 — replaces 는 모듈 클래스를 참조하므로 이 모듈은 public 이어야 한다. 그런데 바인딩 메서드가 public 이면 'public' function exposes its 'internal' parameter type 으로 컴파일되지 않고, interface 멤버에는 가시성을 줄 수 없다. abstract class 라야 클래스는 열어 두고 메서드만 internal 로 닫는다. KDoc 에 근거를 남겨 뒀다.

2. 구현체 5개를 internal 로 전환

UserRepositoryImpl 만 public 으로 남겼다 — SettingCompletionAndroidTest 가 Hilt 를 우회해 UserRepositoryImpl(userApi, authRepository) 를 직접 조립한다. 코드에 사유 주석을 달았고, 닫으려면 그 테스트의 페이크 기반 개조가 선행돼야 한다(이슈 본문에 선택지 3개 정리).

3. 나머지 정리

  • DispatcherModule → core:common (IoDispatcher 한정자가 이미 거기 있다)
  • app 의 core:di 의존을 core:data 로 교체, settings.gradle.kts include 제거, core/di 디렉터리 삭제
  • 삭제된 core/di/build.gradle.kts 가 선언하던 kakao.sdk.auth·work.runtime.ktx 는 두 소스 어디서도 쓰지 않았다. 전자는 app 이, 후자는 core:common·core:startup 이 각각 직접 선언하고 있어 영향 없다.

검증

태스크 결과
:core:data:testDebugUnitTest ✅ 통과 — internal 구현체를 같은 모듈 test 소스셋이 정상 접근
:app:compileDebugUnitTestKotlin ✅ 통과
:app:assembleRelease ✅ BUILD SUCCESSFUL
:core:data:kspDebug/ReleaseKotlin · :app:kspDebug/ReleaseKotlin ✅ 실제 재실행 — Dagger 가 internal abstract @Binds 를 정상 처리, Hilt 그래프 생성 통과
ktlintFormat --rerun ✅ 포맷 변경 0

시각 검증은 해당 없음 — DI 배선과 가시성 변경뿐이고 Compose 본문·디자인 토큰·리소스 변경이 0건이라 screenshotTest 커버를 지나지 않는다.

리뷰어에게

:app:compileDebugAndroidTestKotlin 은 이 브랜치에서 red 인데, develop 이 원래 그렇다. #949 가 고치는 도메인 API 드리프트 44건이 그대로 남아 있다. 제 변경 탓이 아님을 다음과 같이 확인했다.

  • origin/develop 을 별도 워크트리로 띄워 같은 태스크를 돌리고 에러 집합을 diff → 완전히 동일(추가 0 · 제거 0)
  • 그 44건을 내는 파일 5개를 임시로 치우고 컴파일 → BUILD SUCCESSFUL. 이 PR 이 건드린 TestHiltModules.kt 와, UserRepositoryImpl 을 public 으로 남긴 판단이 함께 검증된다

#949 가 먼저 develop 에 들어가면 이 브랜치는 리베이스만으로 해당 게이트가 green 이 된다. 두 변경은 서로를 필요로 하지 않아 스택으로 묶지 않았다 — 파일이 겹치는 SettingCompletionAndroidTest.kt 는 이 PR 이 수정하지 않는다.

#949 머지 후에도 그 파일은 UserRepositoryImpl 을 직접 조립하므로, 위의 public 유지 판단은 그대로 유효하다.

중간 계층이었던 `core:di` 모듈을 제거하고, 의존성 주입 설정을 해당 코드가 속한 모듈(`core:data`, `core:common`)로 이동시킨다. 이를 통해 불필요한 모듈 파편화를 줄이고, 구현체 가시성을 제어하여 캡슐화를 강화한다.

- **모듈 정리**: `core:di` 모듈을 삭제하고 `app` 모듈의 의존성을 `core:data`로 변경한다. `settings.gradle.kts`와 빌드 스크립트에서 더 이상 사용하지 않는 `:core:di` 참조를 제거한다.
- **가시성 제어 및 캡슐화**: `core:data` 내부의 저장소 구현체(`RepositoryImpl`)들을 `internal`로 전환한다. DI 모듈이 구현체와 같은 모듈에 위치하게 됨에 따라, 외부 모듈에서 인터페이스가 아닌 상세 구현에 직접 접근하는 것을 방지한다.
- **DI 모듈 재배치**:
    - `DispatcherModule`을 공통 유틸리티 성격에 맞춰 `core:common`으로 이동한다.
    - 기존 `CoreRepositoryModule`을 `core:data` 내의 기능별 모듈(`Account`, `Upload`, `User`)로 세분화하여 분리한다.
- **테스트 지원**: `app` 모듈의 `androidTest`에서 페이크 객체 교체가 필요한 `CoreUserRepositoryModule`은 예외적으로 `public` 가시성을 유지한다. 다만, 내부 바인딩 메서드는 `internal`로 닫기 위해 `interface` 대신 `abstract class` 구조를 채택한다.
@OnlyReadOneBook OnlyReadOneBook changed the title refactor(core): core:di 모듈 삭제 — 바인딩을 구현 옆으로 옮기고 repository impl 을 internal 로 refactor(core): core:di 모듈 삭제 — 바인딩을 구현 옆으로 옮기고 repository impl 을 internal 로 (closes 930) [base: develop] Aug 23, 2026
OnlyReadOneBook added a commit that referenced this pull request Aug 24, 2026
…tate

AppNavigation.kt import 충돌 1건과, develop 통합으로 드러난 :app 모듈 의존
누락 1건을 해결했다.

1. AppNavigation.kt (충돌)

양쪽이 인접한 import 줄을 각각 늘려 부딪혔다. 다섯 심볼 모두 본문에서 쓰이므로
합집합이 맞되, 이 브랜치 쪽 receiver import 2줄은 #919 이전 경로다
(feature.afternote.presentation.receiver.*). #919 가 옮긴 정본이 이미 같은
파일 아래에 있어 낡은 2줄은 버린다.

2. :app 이 feature.afternote.domain 에 접근 못 함 (충돌 아님)

AppNavigationActions 가 b16efb7 부터 에디터 종류를 AfternoteType 으로 받는데
app/build.gradle.kts 에는 androidTestImplementation 만 있었다. presentation 은
줄곧 implementation 이라 domain 을 전이 노출하지 않으므로, 그동안은 다른 경로로
classpath 에 들어와 있었던 셈이다. develop 통합(#969 의 core:di 삭제 등)으로 그
경로가 사라져 8건이 한꺼번에 드러났다.

app 이 AfternoteType 을 직접 쓰므로 전이 의존에 기대지 않고 직접 선언한다.
konsist 레이어 가드도 통과한다.

검증(CI 와 같은 stub 설정으로):
:app:compileDebugUnitTestKotlin · :konsist:test ·
afternote·receiver presentation compileDebugUnitTestKotlin · ktlintCheck
— BUILD SUCCESSFUL, 컴파일 에러 0.
#968(core:startup 삭제)이 먼저 develop 에 들어가면서 app/build.gradle.kts 의
Core 의존 블록이 충돌했다. 이 브랜치는 core:di 를 없애고 core:data 를 직접
붙이는 쪽이고, develop 은 core:startup 을 지운 쪽이라 양쪽 삭제를 합쳐
core:data 한 줄만 남긴다.

:app:compileDebugUnitTestKotlin 통과. :app:compileDebugAndroidTestKotlin 은
develop 자체가 이미 깨져 있고(오류 21건), 이 병합 결과의 오류 집합이
develop 과 완전히 동일해 병합으로 새로 생긴 오류는 없다.
@OnlyReadOneBook
OnlyReadOneBook merged commit 2fc4a61 into develop Aug 24, 2026
12 of 13 checks passed
@OnlyReadOneBook
OnlyReadOneBook deleted the refactor/930 branch August 24, 2026 09:35
@github-actions

Copy link
Copy Markdown
Contributor

🚀 QA 배포 권장

QA 포인트

이 판단은 배포를 자동 실행하지 않습니다. deploy일 때 Release Distribution을 수동 실행하세요.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

core:di 모듈 삭제 — 바인딩을 구현 옆으로 옮기고 repository impl 을 internal 로

2 participants