๐ง :: SwiftLint ๊ฒฝ๊ณ ์ ๋ฆฌ ๋ฐ Completable dead-code ๋ฒ๊ทธ ์์ #445
Conversation
Completable.asObservable()์ Observable<Never>๊ฐ ๋์ด .next ์ด๋ฒคํธ๊ฐ ์ ๋ ๋ฐ์ํ์ง ์์ผ๋ฏ๋ก, ์ด๋ฅผ .flatMap/.map์ผ๋ก ๋ฐ์ Mutation์ ๋ง๋ค๋ ์ฝ๋๋ ์ปดํ์ผ๋ฌ๊ฐ ๋ณด์ฅํ๋ dead code์์. RxSwift ํ์ค ํจํด์ธ Completable.andThen(Observable<Element>)์ผ๋ก ๊ต์ฒด. - ์ค์ ๋์ ๋ฒ๊ทธ ์์ : AlarmReactor(์ฝ์ ์ฒ๋ฆฌ), MyPageReactor(ํ๋กํ ์ด๋ฏธ์ง ๋ณ๊ฒฝ), BugReportReactor(์ ์ถ ์๋ฃ), NotificationSettingReactor (์๋ฆผ ํ ๊ธ) โ API ์ฑ๊ณต ํ ์๋ํ Mutation์ด ๋ฐ์ํ๋๋ก ์์ - ๋ฌดํดํ์ง๋ง ์คํด๋ฅผ ๋ถ๋ฅด๋ dead code ์ ๋ฆฌ: InterestFieldReactor, OnboardingReactor, RecruitmentReactor, RecruitmentDetailReactor, SearchRecruitmentReactor, WinterInternReactor, WinterInternDetailReactor Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
force_unwrapping, closure_parameter_position ๋ฑ ๊ธฐ์กด SwiftLint ๊ฒฝ๊ณ ๋ฅผ ์ ๋ฆฌํ๊ณ , MainPresentationAssembly์ ์ฌ์ ์กด์ฌํ๋ function_body_length/ type_body_length ์๋ฐ์ ๊ตฌ์กฐ ๋ณ๊ฒฝ(๋ณ๋ ์์ ๋ฒ์) ์์ด disable ์ฃผ์์ผ๋ก ๋ช ์์ ์ผ๋ก ํ์.
Walkthrough๋ฒ๊ทธ ๋ฆฌํฌํธ ๋ชฉ๋ก ํ๋ฉด์ ๊ณต๊ฐ ํ์
์ ์ธ์ด ๋ณต์๋๊ณ , ์ฌ๋ฌ Flow/DI ์ ์ธ๊ณผ ํ๋ฉด ์ปดํฌ๋ํธ์ ์ค๋ฐ๊ฟยท๊ณต๋ฐฑยทํด๋ก์ ํ๊ธฐ๊ฐ ์ ๋ฆฌ๋์์ต๋๋ค. ์ฌ๋ฌ Reactor๋ ์ ์ค์ผ์ด์ค ์๋ฃ ํ Mutation ๋ฐฉ์ถ ๋ฐฉ์์ Changes๋ฒ๊ทธ ๋ฆฌํฌํธ ํ๋ฉด ๋ณต์
๋ฆฌ์กํฐ๋ธ ์๋ฃ ์ฒด์ด๋ ์ ๋ฆฌ
Flow/DI์ ํ๋ฉด ์์ ์ ๋ฆฌ
Estimated code review effort๐ฏ 4 (Complex) | โฑ๏ธ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
๐ฅ Pre-merge checks | โ 4 | โ 1โ Failed checks (1 warning)
โ Passed checks (4 passed)
โ๏ธ Tip: You can configure your own custom pre-merge checks in the settings. โจ Finishing Touches๐ Generate docstrings
๐งช Generate unit tests (beta)
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.
Actionable comments posted: 1
๐งน Nitpick comments (2)
Projects/Presentation/Sources/NotificationSetting/NotificationSettingReactor.swift (1)
78-83: ๐ฉบ Stability & Availability | ๐ต Trivialํ ๊ธ ์ก์ ์ ์๋ฌ ์ฒ๋ฆฌ ์ถ๊ฐ ๊ถ์ฅ
SubscribeNotificationUseCase์SubscribeAllNotificationUseCase๋Completable์ ๋ฐํํ๋ฉฐ, ํ์ฌ.andThen(.just(...))์ฒด์ธ์๋ ์๋ฌ ์ฒ๋ฆฌ๊ฐ ๋๋ฝ๋์ด ์์ต๋๋ค. ๋คํธ์ํฌ ์์ฒญ ์คํจ ์ ์คํธ๋ฆผ์ด ์๋ฌ ์ํ๋ก ์ข ๋ฃ๋์ด ํ ๊ธ ๊ธฐ๋ฅ ์์ฒด๋ฅผ ์ด์ฉํ์ง ๋ชปํ๊ฒ ๋ ์ ์์ต๋๋ค.์คํจ ์ ์ ์ ํ ์ํ ๋ณต์์ด๋ ์๋ฌ ์๋ฆผ์ ์ํด
catch์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ๋๋ก ์์ ์ ๊ถ์ฅํฉ๋๋ค.ํ์ฌ ์ฝ๋
.andThen(.just(.toggleNotificationState(notificationType))) case .toggleAllNotifications: let newState = !currentState.isAllNotificationEnabled return subscribeAllNotificationUseCase.execute() .andThen(.just(.setAllNotificationStates(newState)))๐ค Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Projects/Presentation/Sources/NotificationSetting/NotificationSettingReactor.swift` around lines 78 - 83, `NotificationSettingReactor`์ `toggleNotificationState`์ `toggleAllNotifications` ๋ถ๊ธฐ์์ `SubscribeNotificationUseCase`/`SubscribeAllNotificationUseCase`์ `Completable` ์คํจ๊ฐ ๊ทธ๋๋ก ์ ํ๋์ง ์๋๋ก ์ฒ๋ฆฌํ์ธ์. ๊ฐ `execute()` ๋ค์ `.andThen(.just(...))` ์ฒด์ธ์ `catch`๋ฅผ ์ถ๊ฐํด ์๋ฌ๋ฅผ ํก์ํ๊ณ , ํ์ํ๋ฉด `currentState`๋ก ์ํ๋ฅผ ๋ณต์ํ๊ฑฐ๋ ์๋ฌ ์๋ฆผ์ฉ Action์ผ๋ก ์ ํํ๋๋ก `NotificationSettingReactor` ๋ด๋ถ ํ๋ฆ์ ์์ ํ์ธ์.Projects/Presentation/Sources/Recruitment/RecruitmentReactor.swift (1)
101-105: ๐ฉบ Stability & Availability | ๐ต Trivial๋ถ๋งํฌ ์คํจ ์ mutation ์คํธ๋ฆผ ์ข ๋ฃ ์ํ์ด ํ์ธ๋์์ต๋๋ค.
bookmarkUseCase.execute๊ฐCompletable์ด๋ฏ๋ก ๊ธฐ์กดflatMap { _ in .empty() }์ฝ๋๋ dead-code ์์ผ๋ฉฐ,.andThen(.empty())๋ก ๋ณ๊ฒฝ๋ ๊ฒ์ ์ฑ๊ณต ๊ฒฝ๋ก์ ๋์๊ณผ ๋์ผํฉ๋๋ค. ํ์ง๋ง ํด๋น ์ฝ๋๋.catch์ฒ๋ฆฌ๊ฐ ์์ด, ๋ถ๋งํฌ ์คํจ ์ ์ ์ฒด mutation ์คํธ๋ฆผ์ด ์๋ฌ๋ก ์ข ๋ฃ๋์ด ์ดํ ์ก์ ์ฒ๋ฆฌ๊ฐ ์ค๋จ๋ ์ ์์ต๋๋ค. (RxSwift ๊ธฐ๋ฐ ReactorKit ์ ๋์ ๋ฐฉ์).ํ์ฌ
RecruitmentDetailReactor(Line 73) ๋.catch { _ in .empty() }๋ฅผ ์ ์ฉํ์ฌ ์๋ฌ๋ฅผ ํก์ํ์ง๋ง,RecruitmentReactor(Line 104),WinterInternReactor(Line 93),SearchRecruitmentReactor(Line 74) ๋ ์ด๋ฅผ ๋๋ฝํ๊ณ ์์ด ํจํด์ด ๋ถ์ผ์นํฉ๋๋ค. ์ ๋ฆฌ PR ์ธ ๋งํผ ์ผ๊ด๋ ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ๊ถ์ฅํฉ๋๋ค.โป๏ธ ์๋ฌ ๋ฌด์๊ฐ ์๋๋ผ๋ฉด
- bookmarkUseCase.execute(id: id).andThen(.empty()) + bookmarkUseCase.execute(id: id) + .andThen(.empty()) + .catch { _ in .empty() }๐ค Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Projects/Presentation/Sources/Recruitment/RecruitmentReactor.swift` around lines 101 - 105, `RecruitmentReactor`โs `.bookmarkButtonDidTap` mutation chain can terminate the ReactorKit stream if `bookmarkUseCase.execute(id:)` fails because it currently only uses `andThen(.empty())` without error handling. Update the `bookmarkButtonDidTap` branch to absorb errors the same way as `RecruitmentDetailReactor` by adding a `.catch { _ in .empty() }` after the `Completable` chain, so a bookmark failure does not stop subsequent actions from being processed. Keep the fix aligned with the existing bookmark handling patterns used across the reactor implementations.
๐ค Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Projects/Presentation/Sources/MyPage/MyPageReactor.swift`:
- Around line 91-97: In MyPageReactorโs profile image flow, the current
Completable.zip call runs uploadImageToS3UseCase.execute and
changeProfileImageUseCase.execute in parallel, so replace it with a sequential
chain that only invokes changeProfileImageUseCase after uploadImageToS3UseCase
completes successfully. Use the existing execute(url:) and
execute(presignedURL:data:) calls in MyPageReactor to preserve the intended
order and ensure the backend update happens only after the S3 upload is
confirmed.
---
Nitpick comments:
In
`@Projects/Presentation/Sources/NotificationSetting/NotificationSettingReactor.swift`:
- Around line 78-83: `NotificationSettingReactor`์ `toggleNotificationState`์
`toggleAllNotifications` ๋ถ๊ธฐ์์
`SubscribeNotificationUseCase`/`SubscribeAllNotificationUseCase`์ `Completable`
์คํจ๊ฐ ๊ทธ๋๋ก ์ ํ๋์ง ์๋๋ก ์ฒ๋ฆฌํ์ธ์. ๊ฐ `execute()` ๋ค์ `.andThen(.just(...))` ์ฒด์ธ์ `catch`๋ฅผ ์ถ๊ฐํด
์๋ฌ๋ฅผ ํก์ํ๊ณ , ํ์ํ๋ฉด `currentState`๋ก ์ํ๋ฅผ ๋ณต์ํ๊ฑฐ๋ ์๋ฌ ์๋ฆผ์ฉ Action์ผ๋ก ์ ํํ๋๋ก
`NotificationSettingReactor` ๋ด๋ถ ํ๋ฆ์ ์์ ํ์ธ์.
In `@Projects/Presentation/Sources/Recruitment/RecruitmentReactor.swift`:
- Around line 101-105: `RecruitmentReactor`โs `.bookmarkButtonDidTap` mutation
chain can terminate the ReactorKit stream if `bookmarkUseCase.execute(id:)`
fails because it currently only uses `andThen(.empty())` without error handling.
Update the `bookmarkButtonDidTap` branch to absorb errors the same way as
`RecruitmentDetailReactor` by adding a `.catch { _ in .empty() }` after the
`Completable` chain, so a bookmark failure does not stop subsequent actions from
being processed. Keep the fix aligned with the existing bookmark handling
patterns used across the reactor implementations.
๐ช Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
โน๏ธ Review info
โ๏ธ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3d8ed638-3bb7-4b9b-a140-5a795cd7bce2
๐ Files selected for processing (46)
Projects/Domain/Sources/Entities/RecentCompany/RecentCompanyEntity.swiftProjects/Domain/Sources/UseCases/Companies/FetchRecentCompanyListUseCase.swiftProjects/Flow/Sources/Home/HomeFlow.swiftProjects/Flow/Sources/MyPage/BugReport/BugReportListFlow.swiftProjects/Flow/Sources/Recruitment/RecruitmentFlow.swiftProjects/Flow/Sources/Signup/GenderSettingFlow.swiftProjects/Flow/Sources/Signup/PrivacyFlow.swiftProjects/Flow/Sources/Signup/ProfileSettingFlow.swiftProjects/Flow/Sources/WinterIntern/WinterInternDetailFlow.swiftProjects/Flow/Sources/WinterIntern/WinterInternFlow.swiftProjects/Modules/DesignSystem/Sources/Dropdown/JobisDropdownView.swiftProjects/Presentation/Sources/Base/BaseCollectionViewCell.swiftProjects/Presentation/Sources/BugList/BugReportListViewController.swiftProjects/Presentation/Sources/BugList/BugReportListViewModel.swiftProjects/Presentation/Sources/BugList/Component/Cell/BugReportListTableViewCell.swiftProjects/Presentation/Sources/BugReport/BugReportReactor.swiftProjects/Presentation/Sources/Company/CompanyViewController.swiftProjects/Presentation/Sources/DI/Assembly/AuthPresentationAssembly.swiftProjects/Presentation/Sources/DI/Assembly/MainPresentationAssembly.swiftProjects/Presentation/Sources/EasterEgg/EasterEggViewController.swiftProjects/Presentation/Sources/Home/Alarm/AlarmReactor.swiftProjects/Presentation/Sources/Home/Components/Cell/RecentCompanyCollectionViewCell.swiftProjects/Presentation/Sources/Home/EmployStatus/Components/ClassCategory.swiftProjects/Presentation/Sources/InterestField/Components/Cell/MajorCollectionViewCell.swiftProjects/Presentation/Sources/InterestField/InterestFieldReactor.swiftProjects/Presentation/Sources/InterestField/InterestFieldViewController.swiftProjects/Presentation/Sources/MyPage/Components/BookmarkSectionView.swiftProjects/Presentation/Sources/MyPage/MyPageReactor.swiftProjects/Presentation/Sources/NotificationSetting/NotificationSettingReactor.swiftProjects/Presentation/Sources/Onboarding/OnboardingReactor.swiftProjects/Presentation/Sources/Recruitment/RecruitmentReactor.swiftProjects/Presentation/Sources/Recruitment/RecruitmentViewController.swiftProjects/Presentation/Sources/RecruitmentDetail/RecruitmentDetailReactor.swiftProjects/Presentation/Sources/RecruitmentDetail/RecruitmentDetailViewController.swiftProjects/Presentation/Sources/ReviewFilter/Cell/ReviewTechStackView.swiftProjects/Presentation/Sources/ReviewFilter/ReviewFilterViewController.swiftProjects/Presentation/Sources/SearchRecruitment/SearchRecruitmentReactor.swiftProjects/Presentation/Sources/Signup/VerifyEmail/VerifyEmailReactor.swiftProjects/Presentation/Sources/WinterIntern/WinterInternReactor.swiftProjects/Presentation/Sources/WinterInternDetail/WinterInternDetailReactor.swiftProjects/Presentation/Sources/WinterInternDetail/WinterInternDetailViewController.swiftProjects/Presentation/Sources/WritableReview/AddQuestion/AddQuestionViewModel.swiftProjects/Presentation/Sources/WritableReview/AddReview/AddReviewViewController.swiftProjects/Presentation/Sources/WritableReview/BottomSheet/Component/AddReviewView.swiftProjects/Presentation/Sources/WritableReview/BottomSheet/Component/AreaReviewView.swiftProjects/Presentation/Sources/WritableReview/BottomSheet/Component/TechCodeStackView.swift
๐ค Files with no reviewable changes (5)
- Projects/Presentation/Sources/MyPage/Components/BookmarkSectionView.swift
- Projects/Presentation/Sources/WritableReview/AddReview/AddReviewViewController.swift
- Projects/Presentation/Sources/Base/BaseCollectionViewCell.swift
- Projects/Presentation/Sources/Company/CompanyViewController.swift
- Projects/Presentation/Sources/EasterEgg/EasterEggViewController.swift
| return Completable.zip( | ||
| self.uploadImageToS3UseCase.execute( | ||
| presignedURL: url.presignedUrl, | ||
| data: file.file | ||
| ) | ||
| .asObservable(), | ||
| ), | ||
| self.changeProfileImageUseCase.execute(url: url.filePath) | ||
| .asObservable() | ||
| ) |
There was a problem hiding this comment.
๐๏ธ Data Integrity & Integration | ๐ Major
S3 ์ ๋ก๋ ์๋ฃ ํ ํ๋กํ URL ๋ณ๊ฒฝ ๋ก์ง์ ์์ ๋ณด์ฅ ํ์
Completable.zip ์ ๋ ์์์ ์์
์ ๋ณ๋ ฌ๋ก ์คํํ๋ฏ๋ก, S3 ์
๋ก๋๊ฐ ์์ ํ ์๋ฃ๋๊ธฐ ์ ์ ๋ฐฑ์๋ ํ๋กํ ๋ณ๊ฒฝ ์์ฒญ์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด๋ก ์ธํด ์์ฑ๋ URL ์ด ์คํจ ์ํ์ผ ์ ์์ต๋๋ค.
uploadImageToS3UseCase ์ ์ฑ๊ณต์ด ํ์ ๋ ํ changeProfileImageUseCase ๋ฅผ ์คํํ๋ ์์ฐจ์ ์ฒด์ด๋์ผ๋ก ๋ณ๊ฒฝํ์ฌ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํด์ผ ํฉ๋๋ค.
์ ์ ์์
- return Completable.zip(
- self.uploadImageToS3UseCase.execute(
- presignedURL: url.presignedUrl,
- data: file.file
- ),
- self.changeProfileImageUseCase.execute(url: url.filePath)
- )
+ return self.uploadImageToS3UseCase.execute(
+ presignedURL: url.presignedUrl,
+ data: file.file
+ )
+ .andThen(self.changeProfileImageUseCase.execute(url: url.filePath))
.andThen(Observable.concat([๐ Committable suggestion
โผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return Completable.zip( | |
| self.uploadImageToS3UseCase.execute( | |
| presignedURL: url.presignedUrl, | |
| data: file.file | |
| ) | |
| .asObservable(), | |
| ), | |
| self.changeProfileImageUseCase.execute(url: url.filePath) | |
| .asObservable() | |
| ) | |
| return self.uploadImageToS3UseCase.execute( | |
| presignedURL: url.presignedUrl, | |
| data: file.file | |
| ) | |
| .andThen(self.changeProfileImageUseCase.execute(url: url.filePath)) | |
| .andThen(Observable.concat([ |
๐ค Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Projects/Presentation/Sources/MyPage/MyPageReactor.swift` around lines 91 -
97, In MyPageReactorโs profile image flow, the current Completable.zip call runs
uploadImageToS3UseCase.execute and changeProfileImageUseCase.execute in
parallel, so replace it with a sequential chain that only invokes
changeProfileImageUseCase after uploadImageToS3UseCase completes successfully.
Use the existing execute(url:) and execute(presignedURL:data:) calls in
MyPageReactor to preserve the intended order and ensure the backend update
happens only after the S3 upload is confirmed.
Summary
Completable.asObservable().flatMap/.mapํจํด์ผ๋ก ์ธํด ์ปดํ์ผ๋ฌ๊ฐ dead-code๋ก ํ๋จํ๋ 11๊ฐ Reactor์ RxSwift ์ฝ๋๋ฅผCompletable.andThen(...)์ผ๋ก ๊ต์ฒด (์ค์ ๊ธฐ๋ฅ ๋ฒ๊ทธ 5๊ฑด ํฌํจ, ๋๋จธ์ง๋ ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ฌดํดํ์ผ๋ ์ฝ๋ ๋ช ํ์ฑ์ ์ํด ์ ๋ฆฌ)MainPresentationAssembly์ ์ฌ์ ์กด์ฌํ๋function_body_length/type_body_length์๋ฐ์ ๊ตฌ์กฐ ๋ณ๊ฒฝ(๋ณ๋ ์์ ๋ฒ์) ์์ด disable ์ฃผ์์ผ๋ก ๋ช ์์ ์ผ๋ก ํ์Test plan
swiftlint lint๋ก ๋ณ๊ฒฝ๋ ํ์ผ์ error ๋ฑ๊ธ ์๋ฐ ์์ ํ์ธSummary by CodeRabbit
New Features
Bug Fixes
Style