Skip to content

Feature/mfa step2 usecase split#69

Merged
gomminjae merged 6 commits intodevelopfrom
feature/mfa-step2-usecase-split
Mar 27, 2026
Merged

Feature/mfa step2 usecase split#69
gomminjae merged 6 commits intodevelopfrom
feature/mfa-step2-usecase-split

Conversation

@gomminjae
Copy link
Copy Markdown
Owner

No description provided.

gomminjae and others added 3 commits March 26, 2026 23:01
- 6개 Feature(Bookmark, Detail, Search, Subscribe, MyPage, Launch)에서 미사용 Core 의존성 제거
- SDWebImageSwiftUI, ComposableArchitecture 외부 의존성 완전 제거
- SwipeBackHandler를 Shared → DesignSystem으로 이동 (UI 유틸리티 적절한 레이어 배치)
- AppFlowCoordinatorView에 import DesignSystem 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 9개 Feature에 Interface 모듈 추가 (Factory protocol 정의)
- 각 Feature에 ViewFactoryImpl 구현체 추가
- AppCoordinator가 구현체 대신 Interface(protocol)만 의존하도록 전환
- NewDokTabView를 Factory 기반으로 리팩토링
- AppDIContainer에서 Feature import 제거 (Domain/Data/Core만 유지)
- App 모듈에 CompositionRoot 추가 (Factory 조립 담당)
- Feature 변경 시 AppCoordinator 재컴파일 불필요

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Feature-specific UseCase 구현체 7개를 Domain → Feature로 이동
  - DefaultHomeBusinessUseCase, FetchHomeDataUseCaseImpl → Home
  - LoginUseCaseImpl, SignupUseCaseImpl → Auth
  - ArticleDetailUseCaseImpl → Detail
  - ProfileUseCaseImpl → MyPage
  - SearchUseCaseImpl → Search
- UseCase Protocol은 Domain에 유지 (공유 계약)
- AppDIContainer에서 feature-specific UseCase DI 등록 제거
- CompositionRoot에서 UseCase를 직접 생성하도록 변경

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request undertakes a significant architectural refactoring aimed at enhancing modularity, testability, and maintainability of the application. It establishes a robust dependency injection pattern using Swinject and a factory-based approach for creating views and view models. By defining clear interfaces for features and centralizing dependency resolution, the changes effectively decouple the AppCoordinator from concrete feature implementations, resulting in a more flexible and extensible system.

Highlights

  • Architectural Refactoring: Introduced a new CompositionRoot for centralized dependency resolution and view factory creation, significantly restructuring how dependencies are managed across the application.
  • Dependency Inversion and Modularization: Refactored AppCoordinator and NewdokApp to depend on feature interfaces and view factories, promoting dependency inversion and decoupling the core application flow from concrete feature implementations. This involved creating *Interface targets and *ViewFactoryImpl for each feature (Auth, Home, Explore, etc.).
  • Dependency Injection Framework Update: Replaced ComposableArchitecture with Swinject for dependency injection, streamlining the process of managing and providing dependencies.
  • UseCase Relocation: Migrated use case implementations from the Domain module to their respective feature modules, aligning them closer to their functional areas.
  • Dependency Cleanup: Removed the SDWebImage external dependency from the project.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the application's dependency injection and module structure. It introduces a new CompositionRoot for centralizing view model and use case creation using Swinject, and defines *ViewFactory protocols and implementations for each feature to decouple the AppCoordinator from concrete view implementations. The AppCoordinator now receives these factories as dependencies. Dependencies on ComposableArchitecture and SDWebImage were removed. Review comments highlight that force unwrapping of resolved dependencies in CompositionRoot.swift could lead to runtime crashes and suggest using safe unwrapping. Additionally, it is recommended that the makeTabView function in AppCoordinator should return AnyView for consistency with other factory methods and for type erasure.

},
loginViewModelProvider: {
let userUseCase = container.resolve(UserUseCase.self)!
let loginUseCase = LoginUseCaseImpl(userUseCase: userUseCase)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Force unwrapping (!) resolved dependencies can lead to runtime crashes if the dependency is not registered in the Swinject container. Consider using guard let or if let to safely unwrap, or provide a default value/error handling mechanism.

Suggested change
let loginUseCase = LoginUseCaseImpl(userUseCase: userUseCase)
let userUseCase = container.resolve(UserUseCase.self)!

loginViewModelProvider: {
let userUseCase = container.resolve(UserUseCase.self)!
let loginUseCase = LoginUseCaseImpl(userUseCase: userUseCase)
return LoginViewModel(loginUseCase: loginUseCase)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Force unwrapping (!) resolved dependencies can lead to runtime crashes if the dependency is not registered in the Swinject container. Consider using guard let or if let to safely unwrap, or provide a default value/error handling mechanism.

Suggested change
return LoginViewModel(loginUseCase: loginUseCase)
let loginUseCase = LoginUseCaseImpl(userUseCase: userUseCase)

Comment on lines +74 to 85
@MainActor func makeTabView(selectedTab: NewDokTab? = nil, exploreDay: Int? = nil, exploreSelectedTab: Int? = nil) -> some View {
NewDokTabView(
homeFactory: homeFactory,
exploreFactory: exploreFactory,
subscribeFactory: subscribeFactory,
bookmarkFactory: bookmarkFactory,
mypageFactory: mypageFactory,
exploreIntent: exploreIntent,
selectedTab: selectedTab,
exploreDay: exploreDay,
exploreSelectedTab: exploreSelectedTab
).environmentObject(router)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The makeTabView function returns some View, while other factory methods in AppCoordinator return AnyView. For consistency and to ensure type erasure if needed, consider making makeTabView also return AnyView.

Suggested change
@MainActor func makeTabView(selectedTab: NewDokTab? = nil, exploreDay: Int? = nil, exploreSelectedTab: Int? = nil) -> some View {
NewDokTabView(
homeFactory: homeFactory,
exploreFactory: exploreFactory,
subscribeFactory: subscribeFactory,
bookmarkFactory: bookmarkFactory,
mypageFactory: mypageFactory,
exploreIntent: exploreIntent,
selectedTab: selectedTab,
exploreDay: exploreDay,
exploreSelectedTab: exploreSelectedTab
).environmentObject(router)
@MainActor func makeTabView(selectedTab: NewDokTab? = nil, exploreDay: Int? = nil, exploreSelectedTab: Int? = nil) -> AnyView {
let tabView = NewDokTabView(
homeFactory: homeFactory,
exploreFactory: exploreFactory,
subscribeFactory: subscribeFactory,
bookmarkFactory: bookmarkFactory,
mypageFactory: mypageFactory,
exploreIntent: exploreIntent,
selectedTab: selectedTab,
exploreDay: exploreDay,
exploreSelectedTab: exploreSelectedTab
).environmentObject(router)
return AnyView(tabView)
}

gomminjae and others added 3 commits March 27, 2026 00:03
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SwipeBackHandler: interactiveContentPopGestureRecognizer를 #if compiler(>=6.2)로 감싸 Xcode 16 CI에서도 빌드되도록 수정
- FetchHomeDataUseCaseImpl: final class + @unchecked Sendable로 actor 전달 시 data race 경고 해결

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gomminjae gomminjae merged commit e0e203d into develop Mar 27, 2026
2 checks passed
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.

1 participant