-
Notifications
You must be signed in to change notification settings - Fork 0
feat: RemoteConfig를 통한 강제 업데이트 처리 분기 #264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughFirebase Remote Config를 도입해 원격 앱 버전 정보를 조회하는 리포지토리, 유스케이스, 엔티티 및 DI 바인딩을 추가하고, 앱 시작 시 AppCoordinator에서 강제/선택적 업데이트 로직을 통합합니다. (원격값 fetch 및 버전 비교 기반 분기) Changes
Sequence Diagram(s)sequenceDiagram
participant App as 앱 시작
participant SC as SceneDelegate
participant AC as AppCoordinator
participant UC as FetchRemoteAppVersionUseCase
participant Repo as RemoteConfigRepository
participant Firebase as FirebaseRemoteConfig
participant UI as 업데이트 다이얼로그
App->>SC: startScene()
SC->>AC: init(fetchRemoteAppVersionUseCase)
AC->>UC: execute()
UC->>Repo: fetchRemoteAppVersions()
Repo->>Firebase: fetchAndActivate()
Firebase-->>Repo: 활성화 성공 + 설정값
Repo->>Repo: latestVersion, minimumRequiredVersion 읽음
Repo-->>UC: RemoteAppVersion 발행
UC-->>AC: RemoteAppVersion 전달
rect rgb(240,250,240)
note right of AC: 버전 비교
AC->>AC: currentVersion 비교
alt current < minimum
AC->>UI: presentUpdateSheet(isForced: true)
note right of UI: 강제 업데이트(종료/업데이트 유도)
else current < latest
AC->>UI: presentUpdateSheet(isForced: false)
note right of UI: 선택적 업데이트(나중에 하기 허용)
else
AC->>App: 정상 흐름 진행
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes 검토 시 주의 필요 영역:
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧠 Learnings (4)📓 Common learnings📚 Learning: 2025-07-11T12:12:48.911ZApplied to files:
📚 Learning: 2025-08-06T08:53:16.909ZApplied to files:
📚 Learning: 2025-07-30T11:32:20.533ZApplied to files:
🧬 Code graph analysis (1)src/Projects/BKPresentation/Sources/AppCoordinator.swift (2)
🪛 SwiftLint (0.57.0)src/Projects/BKPresentation/Sources/AppCoordinator.swift[Warning] 231-231: TODOs should be resolved ((dyk) : 디자인 파트와 논의 후 subtitle ...) (todo) ⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (5)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
src/Projects/BKData/Project.swift(1 hunks)src/Projects/BKData/Sources/DataAssembly.swift(2 hunks)src/Projects/BKData/Sources/Repository/DefaultRemoteConfigRepository.swift(1 hunks)src/Projects/BKDomain/Sources/DomainAssembly.swift(1 hunks)src/Projects/BKDomain/Sources/Entity/RemoteAppVersion.swift(1 hunks)src/Projects/BKDomain/Sources/Interface/Repository/RemoteConfigRepository.swift(1 hunks)src/Projects/BKDomain/Sources/Interface/Usecase/FetchRemoteAppVersionUseCase.swift(1 hunks)src/Projects/BKDomain/Sources/UseCase/DefaultFetchRemoteAppVersionUseCase.swift(1 hunks)src/Projects/BKPresentation/Sources/AppCoordinator.swift(4 hunks)src/Projects/Booket/Project.swift(2 hunks)src/Projects/Booket/Sources/SceneDelegate.swift(2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 157
File: src/Projects/BKPresentation/Sources/MainFlow/Home/View/HomeViewController.swift:19-24
Timestamp: 2025-08-08T01:38:59.656Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 접근성(accessibility) 관련 개선사항은 현재 작업 중인 PR에서 즉시 처리하지 않고, 접근성 전용 PR이나 이슈를 별도로 만들어 한번에 처리하는 것을 선호한다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 68
File: src/Projects/BKDesign/PreviewApp/Sources/View/BKButtonTestViewController.swift:124-133
Timestamp: 2025-07-10T08:21:49.399Z
Learning: doyeonk429는 테스트 전용으로만 사용되는 extension이나 코드는 해당 테스트 파일에 그대로 두는 것을 선호합니다. 실제 프로덕션 코드에서 사용되지 않는 테스트 전용 코드는 별도 파일로 분리하지 않고 테스트 파일 내에 유지하는 것이 그들의 코드 구성 방식입니다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 138
File: src/Projects/BKDesign/Resources/Assets.xcassets/icons/home.imageset/Contents.json:4-14
Timestamp: 2025-08-04T15:20:43.982Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 에셋 파일명이 영어가 아닌 경우(한글, 일본어 등)에는 경고를 받고 싶어하지만, 영어 파일명의 네이밍 컨벤션(예: home.png vs home1.png)은 기능적으로 문제없다면 신경쓰지 않는 것을 선호한다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 157
File: src/Projects/BKPresentation/Sources/AuthFlow/View/LoginView.swift:43-45
Timestamp: 2025-08-08T01:39:15.620Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 접근성 개선 작업을 별도의 전용 PR이나 이슈에서 일괄 처리하는 것을 선호한다. 개별 기능 구현 PR에서는 접근성 관련 제안을 하지 않고, 접근성 전담 작업에서 한번에 처리하는 방식을 원한다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 98
File: src/Projects/BKPresentation/Sources/AuthFlow/View/TermsView.swift:78-85
Timestamp: 2025-07-22T05:37:28.756Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 더미 데이터나 테스트 데이터의 구체적인 내용(예: URL 주소)에 대해서는 리뷰 시 지적하지 않기를 선호한다. 더미 데이터는 임시적이며 실제 기능 구현 시 교체될 예정이므로 URL의 구체적인 주소는 중요하지 않다고 본다.
📚 Learning: 2025-07-11T12:12:48.911Z
Learnt from: clxxrlove
Repo: YAPP-Github/Reed-iOS PR: 79
File: src/Projects/BKPresentation/Sources/MainFlow/Setting/ViewModel/SettingViewModel.swift:78-85
Timestamp: 2025-07-11T12:12:48.911Z
Learning: AppVersionUseCase.execute() returns AnyPublisher<String, Never> where the Failure type is Never, making error handling unnecessary. The app version is retrieved from the main bundle which is always available, and the implementation already handles missing version by defaulting to "-".
Applied to files:
src/Projects/BKDomain/Sources/DomainAssembly.swiftsrc/Projects/BKDomain/Sources/Interface/Repository/RemoteConfigRepository.swiftsrc/Projects/BKDomain/Sources/Interface/Usecase/FetchRemoteAppVersionUseCase.swiftsrc/Projects/BKDomain/Sources/UseCase/DefaultFetchRemoteAppVersionUseCase.swiftsrc/Projects/BKDomain/Sources/Entity/RemoteAppVersion.swiftsrc/Projects/BKData/Sources/Repository/DefaultRemoteConfigRepository.swiftsrc/Projects/Booket/Sources/SceneDelegate.swiftsrc/Projects/BKPresentation/Sources/AppCoordinator.swift
📚 Learning: 2025-07-30T11:32:20.533Z
Learnt from: clxxrlove
Repo: YAPP-Github/Reed-iOS PR: 120
File: src/Projects/BKPresentation/Sources/AppCoordinator.swift:31-41
Timestamp: 2025-07-30T11:32:20.533Z
Learning: Reed-iOS 프로젝트의 OnboardingCheckUseCase.execute() 메서드는 AnyPublisher<Bool, Never>를 반환하므로 실패할 수 없도록 설계되었다. Never 타입은 에러가 발생하지 않음을 보장하므로 에러 처리 로직이 불필요하다.
Applied to files:
src/Projects/BKDomain/Sources/Interface/Usecase/FetchRemoteAppVersionUseCase.swiftsrc/Projects/BKPresentation/Sources/AppCoordinator.swift
🧬 Code graph analysis (8)
src/Projects/Booket/Project.swift (1)
src/Tuist/ProjectDescriptionHelpers/TargetDependency+External.swift (1)
external(33-35)
src/Projects/BKDomain/Sources/DomainAssembly.swift (1)
src/Projects/BKCore/Sources/DiContainer/DIContainer.swift (1)
register(25-46)
src/Projects/BKDomain/Sources/Interface/Repository/RemoteConfigRepository.swift (1)
src/Projects/BKData/Sources/Repository/DefaultRemoteConfigRepository.swift (1)
fetchRemoteAppVersions(22-50)
src/Projects/BKDomain/Sources/Interface/Usecase/FetchRemoteAppVersionUseCase.swift (1)
src/Projects/BKDomain/Sources/UseCase/DefaultFetchRemoteAppVersionUseCase.swift (1)
execute(14-16)
src/Projects/BKDomain/Sources/UseCase/DefaultFetchRemoteAppVersionUseCase.swift (1)
src/Projects/BKData/Sources/Repository/DefaultRemoteConfigRepository.swift (1)
fetchRemoteAppVersions(22-50)
src/Projects/BKData/Project.swift (1)
src/Tuist/ProjectDescriptionHelpers/TargetDependency+External.swift (1)
external(33-35)
src/Projects/BKData/Sources/DataAssembly.swift (1)
src/Projects/BKCore/Sources/DiContainer/DIContainer.swift (1)
register(25-46)
src/Projects/BKPresentation/Sources/AppCoordinator.swift (2)
src/Projects/BKCore/Sources/Logger/AppLogger.swift (1)
debug(31-42)src/Projects/BKPresentation/Sources/Common/Constant/AppStoreLinker.swift (1)
openAppStore(9-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (9)
src/Projects/BKData/Project.swift (1)
20-21: LGTM!FirebaseRemoteConfig 의존성이 올바르게 추가되었습니다.
src/Projects/BKDomain/Sources/Entity/RemoteAppVersion.swift (1)
5-12: LGTM!Remote Config에서 가져올 앱 버전 정보를 담는 데이터 컨테이너가 명확하게 정의되었습니다. 불변 프로퍼티를 사용한 설계가 적절합니다.
src/Projects/Booket/Sources/SceneDelegate.swift (2)
62-62: LGTM!fetchRemoteAppVersionUseCase 의존성 주입이 올바르게 추가되었습니다.
71-71: LGTM!AppCoordinator에 fetchRemoteAppVersionUseCase가 올바르게 전달되고 있습니다.
src/Projects/Booket/Project.swift (2)
34-35: LGTM!Debug 타겟에 FirebaseRemoteConfig 의존성이 올바르게 추가되었습니다.
80-81: LGTM!Release 타겟에도 FirebaseRemoteConfig 의존성이 일관되게 추가되었습니다.
src/Projects/BKDomain/Sources/DomainAssembly.swift (1)
73-78: LGTM!FetchRemoteAppVersionUseCase의 DI 등록이 올바르게 구현되었습니다. RemoteConfigRepository 의존성이 적절하게 주입되고 있습니다.
src/Projects/BKDomain/Sources/Interface/Usecase/FetchRemoteAppVersionUseCase.swift (1)
7-8: LGTM!Remote Config 조회는 네트워크 오류 등으로 실패할 수 있으므로
Error타입을 사용한 것이 적절합니다. 기존AppVersionUseCase가 번들에서 읽어오는 것과 달리, 원격 데이터 조회는 실패 가능성을 고려한 설계가 올바릅니다.src/Projects/BKDomain/Sources/Interface/Repository/RemoteConfigRepository.swift (1)
6-7: LGTM!RemoteConfigRepository 프로토콜이 명확하게 정의되었습니다. Use case와 일관된 반환 타입을 사용하고 있습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/Projects/BKPresentation/Sources/AppCoordinator.swift (2)
218-254: 다이얼로그 생성 코드 중복 고려강제/권장 업데이트 분기 처리가 올바르게 구현되었고, 특히 권장 업데이트 시 dismiss completion에서 플로우를 진행하도록 수정한 것이 좋습니다.
다만 Line 222-229와 231-245의 다이얼로그 생성 코드에서 title, subtitle이 동일하게 반복됩니다. 공통 부분을 추출하면 유지보수성이 향상될 수 있어요:
private func presentUpdateSheet(isForced: Bool = true) { - var dialog: BKDialog? + let config: BKDialog.Configuration if isForced { - dialog = BKDialog( - title: "최신 버전이 출시되었습니다", - subtitle: "최적의 사용 환경을 위해 업데이트해주세요.", - config: .init( - leftButtonTitle: "업데이트 하기", - leftButtonAction: AppStoreLinker.openAppStore - ) + config = .init( + leftButtonTitle: "업데이트 하기", + leftButtonAction: AppStoreLinker.openAppStore ) } else { - dialog = BKDialog( - title: "최신 버전이 출시되었습니다", - subtitle: "최적의 사용 환경을 위해 업데이트해주세요.", - config: .init( - leftButtonTitle: "업데이트 하기", - leftButtonAction: AppStoreLinker.openAppStore, - rightButtonTitle: "나중에 하기", - rightButtonAction: { [weak self] in - guard let self else { return } - self.navigationController.dismiss(animated: true) { - self.proceedWithAppFlow() - } - } - ) + config = .init( + leftButtonTitle: "업데이트 하기", + leftButtonAction: AppStoreLinker.openAppStore, + rightButtonTitle: "나중에 하기", + rightButtonAction: { [weak self] in + guard let self else { return } + self.navigationController.dismiss(animated: true) { + self.proceedWithAppFlow() + } + } ) } - guard let dialog else { return } + let dialog = BKDialog( + title: "최신 버전이 출시되었습니다", + subtitle: "최적의 사용 환경을 위해 업데이트해주세요.", + config: config + ) + let dialogViewController = BKDialogViewController(dialog: dialog) dialogViewController.isModalInPresentation = true DispatchQueue.main.async { self.navigationController.present(dialogViewController, animated: true) } }
251-253: 중복 메인 큐 디스패치 확인Line 75에서 이미
.receive(on: DispatchQueue.main)으로 메인 스레드에서 실행되고 있는데, Line 251에서 다시DispatchQueue.main.async를 사용하고 있습니다. 이 추가 디스패치가 의도적인 안전장치가 아니라면 제거해도 될 것 같아요.let dialogViewController = BKDialogViewController(dialog: dialog) dialogViewController.isModalInPresentation = true - DispatchQueue.main.async { - self.navigationController.present(dialogViewController, animated: true) - } + self.navigationController.present(dialogViewController, animated: true)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/Projects/BKPresentation/Sources/AppCoordinator.swift(4 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 157
File: src/Projects/BKPresentation/Sources/MainFlow/Home/View/HomeViewController.swift:19-24
Timestamp: 2025-08-08T01:38:59.656Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 접근성(accessibility) 관련 개선사항은 현재 작업 중인 PR에서 즉시 처리하지 않고, 접근성 전용 PR이나 이슈를 별도로 만들어 한번에 처리하는 것을 선호한다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 68
File: src/Projects/BKDesign/PreviewApp/Sources/View/BKButtonTestViewController.swift:124-133
Timestamp: 2025-07-10T08:21:49.399Z
Learning: doyeonk429는 테스트 전용으로만 사용되는 extension이나 코드는 해당 테스트 파일에 그대로 두는 것을 선호합니다. 실제 프로덕션 코드에서 사용되지 않는 테스트 전용 코드는 별도 파일로 분리하지 않고 테스트 파일 내에 유지하는 것이 그들의 코드 구성 방식입니다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 138
File: src/Projects/BKDesign/Resources/Assets.xcassets/icons/home.imageset/Contents.json:4-14
Timestamp: 2025-08-04T15:20:43.982Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 에셋 파일명이 영어가 아닌 경우(한글, 일본어 등)에는 경고를 받고 싶어하지만, 영어 파일명의 네이밍 컨벤션(예: home.png vs home1.png)은 기능적으로 문제없다면 신경쓰지 않는 것을 선호한다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 157
File: src/Projects/BKPresentation/Sources/AuthFlow/View/LoginView.swift:43-45
Timestamp: 2025-08-08T01:39:15.620Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 접근성 개선 작업을 별도의 전용 PR이나 이슈에서 일괄 처리하는 것을 선호한다. 개별 기능 구현 PR에서는 접근성 관련 제안을 하지 않고, 접근성 전담 작업에서 한번에 처리하는 방식을 원한다.
Learnt from: doyeonk429
Repo: YAPP-Github/Reed-iOS PR: 98
File: src/Projects/BKPresentation/Sources/AuthFlow/View/TermsView.swift:78-85
Timestamp: 2025-07-22T05:37:28.756Z
Learning: doyeonk429는 Reed-iOS 프로젝트에서 더미 데이터나 테스트 데이터의 구체적인 내용(예: URL 주소)에 대해서는 리뷰 시 지적하지 않기를 선호한다. 더미 데이터는 임시적이며 실제 기능 구현 시 교체될 예정이므로 URL의 구체적인 주소는 중요하지 않다고 본다.
📚 Learning: 2025-07-11T12:12:48.911Z
Learnt from: clxxrlove
Repo: YAPP-Github/Reed-iOS PR: 79
File: src/Projects/BKPresentation/Sources/MainFlow/Setting/ViewModel/SettingViewModel.swift:78-85
Timestamp: 2025-07-11T12:12:48.911Z
Learning: AppVersionUseCase.execute() returns AnyPublisher<String, Never> where the Failure type is Never, making error handling unnecessary. The app version is retrieved from the main bundle which is always available, and the implementation already handles missing version by defaulting to "-".
Applied to files:
src/Projects/BKPresentation/Sources/AppCoordinator.swift
📚 Learning: 2025-08-06T08:53:16.909Z
Learnt from: clxxrlove
Repo: YAPP-Github/Reed-iOS PR: 147
File: src/Projects/BKData/Sources/Service/AppleLoginDelegateProxy.swift:65-78
Timestamp: 2025-08-06T08:53:16.909Z
Learning: clxxrlove는 Reed-iOS 프로젝트의 Apple 로그인 구현에서 authorizationCode 강제 언래핑 이슈에 대해 현재 구현으로도 문제없다고 판단했다. 초기 구현 단계에서는 기본 기능 동작을 우선시하고 추후 개선할 예정이라는 기존 패턴과 일치한다.
Applied to files:
src/Projects/BKPresentation/Sources/AppCoordinator.swift
📚 Learning: 2025-07-30T11:32:20.533Z
Learnt from: clxxrlove
Repo: YAPP-Github/Reed-iOS PR: 120
File: src/Projects/BKPresentation/Sources/AppCoordinator.swift:31-41
Timestamp: 2025-07-30T11:32:20.533Z
Learning: Reed-iOS 프로젝트의 OnboardingCheckUseCase.execute() 메서드는 AnyPublisher<Bool, Never>를 반환하므로 실패할 수 없도록 설계되었다. Never 타입은 에러가 발생하지 않음을 보장하므로 에러 처리 로직이 불필요하다.
Applied to files:
src/Projects/BKPresentation/Sources/AppCoordinator.swift
🧬 Code graph analysis (1)
src/Projects/BKPresentation/Sources/AppCoordinator.swift (2)
src/Projects/BKCore/Sources/Logger/AppLogger.swift (1)
debug(31-42)src/Projects/BKPresentation/Sources/Common/Constant/AppStoreLinker.swift (1)
openAppStore(9-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (3)
src/Projects/BKPresentation/Sources/AppCoordinator.swift (3)
22-22: 새 의존성 추가가 적절합니다
FetchRemoteAppVersionUseCase를 통해 Remote Config 기반 버전 체크로 전환하는 구조가 깔끔하게 구현되었습니다. 의존성 주입 패턴을 일관되게 유지하고 있어요.Also applies to: 32-32, 40-40
70-105: 업데이트 분기 로직이 올바르게 수정되었습니다과거 리뷰에서 지적된 critical issue(권장 업데이트 시
proceedWithAppFlow()를 즉시 호출해 로그인/온보딩 플로우가 막히는 문제)가 해결되었습니다. 현재 코드는:
- Line 97-99: 권장 업데이트 시 다이얼로그만 띄우고 즉시 진행하지 않음
- Line 238-243: "나중에 하기" 버튼의 dismiss completion에서 플로우 진행
버전 비교 로직(강제 업데이트 vs 권장 업데이트)과 에러 처리도 적절합니다. Remote Config fetch 실패 시 사용자가 앱을 계속 사용할 수 있도록 폴백하는 것이 좋은 선택입니다.
90-92: 디버그 로그 레벨 확인버전 정보를 디버그 로그로 남기는 것은 개발 중 유용하지만,
AppLogger.ui를 사용하고 있네요.AppLogger.debug가 이미#if DEBUG로 보호되고 있다면 문제없지만, 프로덕션에서 불필요한 로그가 남지 않는지 확인해주세요.관련 코드에서
AppLogger.debug의 구현을 확인해보니#if DEBUG로 보호되고 있습니다. 프로덕션에서는 이 로그가 출력되지 않으므로 안전합니다.
73db761 to
f004f05
Compare
🔗 관련 이슈
📘 작업 유형
📙 작업 내역
🧪 테스트 내역
🎨 스크린샷 또는 시연 영상 (선택)
Simulator.Screen.Recording.-.ReedDefaultSize.-.2025-11-11.at.22.42.30.mp4
✅ PR 체크리스트
💬 추가 설명 or 리뷰 포인트 (선택)
App Store 이동 테스트 관련
업데이트 얼럿(Alert) 구현 관련
Summary by CodeRabbit
새로운 기능
수정