Skip to content

MLSAppFeature를 구체화 합니다.#338

Merged
dongglehada merged 5 commits into
devfrom
fix/#337-MLSAppFeature
Jun 9, 2026
Merged

MLSAppFeature를 구체화 합니다.#338
dongglehada merged 5 commits into
devfrom
fix/#337-MLSAppFeature

Conversation

@pinocchio22

Copy link
Copy Markdown
Contributor

📌 이슈

  • #이슈번호

✅ 작업 사항

  • Delegate 관련 코드 AppFeature로 이전
  • AppCoordinator를 AppFeature로 이전
  • AppFeature에서 모든 Feature 조립
  • 도감 <-> 북마크 분리 이전 임시 코드 제거
  • 기능 테스트
  • 기존 모듈 일괄 제거

👀 ETC (추후 개발해야 할 것, 참고자료 등) ->

  • 화면이동할때 탭바숨김 처리
  • 추천 기능 연결
  • 파일 위치 논의 필요 (AuthInterceptor / EmptyResponseDTO / APIDefaultResponseDTO)

MLSAppFeature 모듈에서 앱 조립 -> 본 앱에서는 lauch와 외부 SDK 호출 정도만 담당
+ 기존 모듈제거와 화면 이동(탭바 히든처리) 필요
@pinocchio22 pinocchio22 requested a review from dongglehada June 9, 2026 12:24
@pinocchio22 pinocchio22 self-assigned this Jun 9, 2026
@pinocchio22 pinocchio22 added fix 버그 수정, 잔잔바리 수정, 병합 시 충돌 해결 refactor 프로덕션 코드 리팩토링, 파일 삭제, 네이밍 수정 및 폴더링 remove 파일 삭제 labels Jun 9, 2026

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

Copy link
Copy Markdown

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 modularizes the project by migrating monolithic code into separate Swift packages and setting up modular dependency injection assemblies. While the refactoring improves the architecture, several critical issues were identified: a circular dependency and redundant target declarations in Package.swift, missing server-side FCM token updates in TokenLauncher, and compiler ambiguity errors due to duplicate UserDefaultsRepository definitions across imported interfaces. Additionally, wrapping the AppCoordinator registration in MainActor.assumeIsolated is recommended to avoid strict concurrency compilation errors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +37 to +49
if case .success(let accessToken) =
tokenRepository.fetchToken(type: .accessToken),
!accessToken.isEmpty {
_ = tokenRepository.saveToken(
type: .fcmToken,
value: token
)

os_log("Request to update FCM token on server")
} else {
os_log("Not logged in yet, skipping FCM update to server")
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

로그인된 상태일 때 FCM 토큰을 서버에 업데이트하는 로직이 누락되었습니다. 기존 AppDelegate에서는 putFCMTokenUseCase.execute(fcmToken: fcmToken)를 호출하여 서버에 토큰을 업데이트했으나, 리팩토링된 TokenLauncher에서는 로컬 저장소에 토큰을 중복 저장(tokenRepository.saveToken)하고만 있습니다. 서버에 FCM 토큰을 등록하는 API 호출(예: AuthAPIRepository 또는 관련 UseCase 호출)을 수행하도록 수정해야 합니다.

Comment on lines +26 to +35
dependencies: [
.package(path: "../MLSAppFeature"),
.package(path: "../MLSAuthFeature"),
.package(path: "../MLSBookmarkFeature"),
.package(path: "../MLSCore"),
.package(path: "../MLSDictionaryFeature"),
.package(path: "../MLSMyPageFeature"),
.package(path: "../MLSRecommendationFeature"),
.package(url: "https://github.com/ReactiveX/RxSwift.git", from: "6.7.0")
],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

정의 중인 패키지(MLSAppFeature)가 자기 자신(../MLSAppFeature)을 의존성으로 추가하고 있습니다. 이는 순환 참조 및 SPM 로드 에러를 유발합니다. 이를 제거해야 합니다.

    dependencies: [
        .package(path: "../MLSAuthFeature"),
        .package(path: "../MLSBookmarkFeature"),
        .package(path: "../MLSCore"),
        .package(path: "../MLSDictionaryFeature"),
        .package(path: "../MLSMyPageFeature"),
        .package(path: "../MLSRecommendationFeature"),
        .package(url: "https://github.com/ReactiveX/RxSwift.git", from: "6.7.0"),
    ],

Comment on lines +45 to +60
dependencies: [
"MLSAppFeatureInterface",
.product(name: "MLSAuthFeature", package: "MLSAuthFeature"),
.product(name: "MLSAppFeatureInterface", package: "MLSAppFeature"),
.product(name: "MLSAuthFeatureInterface", package: "MLSAuthFeature"),
.product(name: "MLSBookmarkFeature", package: "MLSBookmarkFeature"),
.product(name: "MLSBookmarkFeatureInterface", package: "MLSBookmarkFeature"),
.product(name: "MLSCore", package: "MLSCore"),
.product(name: "MLSDictionaryFeature", package: "MLSDictionaryFeature"),
.product(name: "MLSDictionaryFeatureInterface", package: "MLSDictionaryFeature"),
.product(name: "MLSMyPageFeature", package: "MLSMyPageFeature"),
.product(name: "MLSMyPageFeatureInterface", package: "MLSMyPageFeature"),
.product(name: "MLSRecommendationFeature", package: "MLSRecommendationFeature"),
.product(name: "MLSRecommendationFeatureInterface", package: "MLSRecommendationFeature"),
.product(name: "RxSwift", package: "RxSwift")
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

타겟 의존성에서 동일 패키지 내의 타겟인 MLSAppFeatureInterface를 외부 프로덕트 형식(.product(name: "MLSAppFeatureInterface", package: "MLSAppFeature"))으로 중복 추가하고 있습니다. 이를 제거하고 내부 타겟 이름만 지정하도록 수정해야 합니다.

            dependencies: [
                "MLSAppFeatureInterface",
                .product(name: "MLSAuthFeature", package: "MLSAuthFeature"),
                .product(name: "MLSAuthFeatureInterface", package: "MLSAuthFeature"),
                .product(name: "MLSBookmarkFeature", package: "MLSBookmarkFeature"),
                .product(name: "MLSBookmarkFeatureInterface", package: "MLSBookmarkFeature"),
                .product(name: "MLSCore", package: "MLSCore"),
                .product(name: "MLSDictionaryFeature", package: "MLSDictionaryFeature"),
                .product(name: "MLSDictionaryFeatureInterface", package: "MLSDictionaryFeature"),
                .product(name: "MLSMyPageFeature", package: "MLSMyPageFeature"),
                .product(name: "MLSMyPageFeatureInterface", package: "MLSMyPageFeature"),
                .product(name: "MLSRecommendationFeature", package: "MLSRecommendationFeature"),
                .product(name: "MLSRecommendationFeatureInterface", package: "MLSRecommendationFeature"),
                .product(name: "RxSwift", package: "RxSwift"),
            ]

Comment on lines +25 to +27
userDefaultsRepository: DIContainer.resolve(
type: UserDefaultsRepository.self, name: "authUserDefaultsRepository"
)

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

현재 파일에서 MLSAuthFeatureInterfaceMLSDictionaryFeatureInterface를 모두 임포트하고 있습니다. 두 인터페이스 모듈 모두 UserDefaultsRepository 프로토콜을 정의하고 있기 때문에, 모듈 명시 없이 UserDefaultsRepository.self를 사용하면 컴파일러가 모호성(Ambiguity) 에러를 발생시킵니다. 이를 방지하기 위해 MLSAuthFeatureInterface.UserDefaultsRepository.self와 같이 명시적으로 타입을 지정해 주어야 합니다.

Suggested change
userDefaultsRepository: DIContainer.resolve(
type: UserDefaultsRepository.self, name: "authUserDefaultsRepository"
)
userDefaultsRepository: DIContainer.resolve(
type: MLSAuthFeatureInterface.UserDefaultsRepository.self, name: "authUserDefaultsRepository"
)

Comment on lines +72 to +74
DIContainer.register(type: FetchVisitDictionaryDetailUseCase.self) {
FetchVisitDictionaryDetailUseCaseImpl(repository: DIContainer.resolve(type: UserDefaultsRepository.self, name: "dictionaryUserDefaultsRepository"))
}

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

현재 파일에서 MLSAuthFeatureInterfaceMLSDictionaryFeatureInterface를 모두 임포트하고 있습니다. 두 인터페이스 모듈 모두 UserDefaultsRepository 프로토콜을 정의하고 있기 때문에, 모듈 명시 없이 UserDefaultsRepository.self를 사용하면 컴파일러가 모호성(Ambiguity) 에러를 발생시킵니다. 이를 방지하기 위해 MLSDictionaryFeatureInterface.UserDefaultsRepository.self와 같이 명시적으로 타입을 지정해 주어야 합니다.

Suggested change
DIContainer.register(type: FetchVisitDictionaryDetailUseCase.self) {
FetchVisitDictionaryDetailUseCaseImpl(repository: DIContainer.resolve(type: UserDefaultsRepository.self, name: "dictionaryUserDefaultsRepository"))
}
DIContainer.register(type: FetchVisitDictionaryDetailUseCase.self) {
FetchVisitDictionaryDetailUseCaseImpl(repository: DIContainer.resolve(type: MLSDictionaryFeatureInterface.UserDefaultsRepository.self, name: "dictionaryUserDefaultsRepository"))
}

Comment on lines +81 to +83
userDefaultsRepository: DIContainer
.resolve(type: UserDefaultsRepository.self, name: "authUserDefaultsRepository")
)

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

현재 파일에서 MLSAuthFeatureInterfaceMLSDictionaryFeatureInterface를 모두 임포트하고 있습니다. 두 인터페이스 모듈 모두 UserDefaultsRepository 프로토콜을 정의하고 있기 때문에, 모듈 명시 없이 UserDefaultsRepository.self를 사용하면 컴파일러가 모호성(Ambiguity) 에러를 발생시킵니다. 이를 방지하기 위해 MLSAuthFeatureInterface.UserDefaultsRepository.self와 같이 명시적으로 타입을 지정해 주어야 합니다.

Suggested change
userDefaultsRepository: DIContainer
.resolve(type: UserDefaultsRepository.self, name: "authUserDefaultsRepository")
)
userDefaultsRepository: DIContainer
.resolve(type: MLSAuthFeatureInterface.UserDefaultsRepository.self, name: "authUserDefaultsRepository")
)

Comment on lines +59 to +61
userDefaultsRepository: DIContainer.resolve(
type: UserDefaultsRepository.self, name: "authUserDefaultsRepository"
)

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

현재 파일에서 MLSAuthFeatureInterfaceMLSDictionaryFeatureInterface를 모두 임포트하고 있습니다. 두 인터페이스 모듈 모두 UserDefaultsRepository 프로토콜을 정의하고 있기 때문에, 모듈 명시 없이 UserDefaultsRepository.self를 사용하면 컴파일러가 모호성(Ambiguity) 에러를 발생시킵니다. 이를 방지하기 위해 MLSAuthFeatureInterface.UserDefaultsRepository.self와 같이 명시적으로 타입을 지정해 주어야 합니다.

Suggested change
userDefaultsRepository: DIContainer.resolve(
type: UserDefaultsRepository.self, name: "authUserDefaultsRepository"
)
userDefaultsRepository: DIContainer.resolve(
type: MLSAuthFeatureInterface.UserDefaultsRepository.self, name: "authUserDefaultsRepository"
)

Comment on lines +21 to +38
DIContainer.register(type: AppCoordinatorProtocol.self) {
AppCoordinator(
window: window,
recommendationMainFactory: DIContainer.resolve(
type: RecommendationMainFactory.self
),
dictionaryMainViewFactory: DIContainer.resolve(
type: DictionaryMainViewFactory.self
),
bookmarkMainFactory: DIContainer.resolve(
type: BookmarkMainFactory.self
),
myPageMainFactory: DIContainer.resolve(
type: MyPageMainFactory.self
),
loginFactory: DIContainer.resolve(type: LoginFactory.self)
)
}

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

AppCoordinator@MainActor로 격리된 클래스이지만, DIContainer.register에 전달되는 클로저는 비격리(Non-isolated) 컨텍스트입니다. Swift 5.10/6의 엄격한 동시성 검사(Strict Concurrency) 환경에서는 비격리 컨텍스트에서 메인 액터 격리 객체를 직접 초기화할 때 컴파일 에러가 발생할 수 있습니다. 이 등록 클로저는 항상 메인 스레드에서 실행되므로, MainActor.assumeIsolated를 사용하여 안전하게 초기화하도록 감싸는 것을 권장합니다.

        DIContainer.register(type: AppCoordinatorProtocol.self) {
            MainActor.assumeIsolated {
                AppCoordinator(
                    window: window,
                    recommendationMainFactory: DIContainer.resolve(
                        type: RecommendationMainFactory.self
                    ),
                    dictionaryMainViewFactory: DIContainer.resolve(
                        type: DictionaryMainViewFactory.self
                    ),
                    bookmarkMainFactory: DIContainer.resolve(
                        type: BookmarkMainFactory.self
                    ),
                    myPageMainFactory: DIContainer.resolve(
                        type: MyPageMainFactory.self
                    ),
                    loginFactory: DIContainer.resolve(type: LoginFactory.self)
                )
            }
        }

@dongglehada dongglehada merged commit a509a47 into dev Jun 9, 2026
@dongglehada dongglehada deleted the fix/#337-MLSAppFeature branch June 9, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix 버그 수정, 잔잔바리 수정, 병합 시 충돌 해결 refactor 프로덕션 코드 리팩토링, 파일 삭제, 네이밍 수정 및 폴더링 remove 파일 삭제

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants