Skip to content

[Feat] 설정 화면 로직 구현#37

Merged
choijungp merged 5 commits intodevelopfrom
feat/setting
Aug 7, 2025
Merged

[Feat] 설정 화면 로직 구현#37
choijungp merged 5 commits intodevelopfrom
feat/setting

Conversation

@taipaise
Copy link
Copy Markdown
Collaborator

@taipaise taipaise commented Aug 5, 2025

🌁 Background

  • 설정 로직을 붙여야 해요!!!!!

👩‍💻 Contents

  • 이미 잘 구현되어 있는 로그아웃, 회원탈퇴 버튼이랑 날먹 연결 시키기
  • 엡스토어 버전 fetch 로직 작성

📝 Review Note

이미 너무 잘 구현해주셔서, 로그아웃과 회원 탈퇴 로직은 5분 컷 했습니다!! 로그아웃 시 IntroView로 돌아갑니다.

주석 처리에 관하여..

  • 물론 사용하지 않는 코드는 올리지 않는 것이 맞다 생각하지만, 아마 곧 추가될 기능이고.. UI 완성도도 높게 구현을 잘 해둬서 나중에 주석만 풀고 사용하는게 좋지 않을까? 하여 알림 관련 목록을 주석처리하였습니다.
  • 하지만 부적절하다고 생각이 드시면, 해당 부분 삭제하고 로컬에서만 보관하는 방식으로 가겠습니다!

AppConfigRepository

  • 설정 페이지에서는 이름처럼 앱 설정과 관련된 값들을 가져옵니다. 아직은 추가되지 않았지만, 추후 알림 관련 API도 요기에 들어갈 것 같습니다.
  • 현재는 버전 값을 가져오는 메서드만 있습니다.!!

버전 가져오기

  • 원래는, 이미 잘 구현해주신 NetworkService를 사용하고자 했습니다. AppStore에서 내려주는 body도 나름 레퍼런스가 많아서 DTO 자체를 구현하는 것은 어렵지 않았거든요.. 하지만 제가 간과 한 것이 있었으니,, Bitnagil에서는모든 응답이 BaseDTO 형태로 내려온다는 것!!! 이걸 파악하지 못해서 진짜 금방 끝나야 하는 로직인데 삽질 하느라 마무리가 늦었습니다 (죄송,,,)

  • 아쉽게도, 애플에서는 저희의 BaseDTO 형식을 따르지 않기 때문에, Repository내부에서 URLSession으로 직접 버전 정보를 가져오는 로직을 구현했습니다.

  • 지금은 아직 배포가되지 않은 상태이기 때문에, 아래 처럼 body를 내려줍니다.

{
 "resultCount":0,
 "results": []
}

하지만, 나중에는 저 results 배열 안에 version 값이 내려올거에요!!

Summary by CodeRabbit

  • 신규 기능

    • 앱 설정 화면에서 앱 버전 정보를 자동으로 확인하고 최신 버전 여부를 안내합니다.
    • 앱 버전 확인을 위해 앱스토어와 연동된 버전 조회 기능이 추가되었습니다.
  • 기능 개선

    • 로그아웃 및 회원탈퇴 시 인증 상태 변경 시 인트로 화면으로 전환되도록 처리 방식이 개선되었습니다.
    • 설정 화면에서 내부 및 외부 URL을 구분하여 적절히 처리합니다.
  • UI 변경

    • 설정 화면에서 알림 관련 섹션이 비활성화되었습니다.

@taipaise taipaise requested a review from choijungp August 5, 2025 14:49
@taipaise taipaise self-assigned this Aug 5, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Aug 5, 2025

Warning

Rate limit exceeded

@choijungp has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 5 minutes and 18 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between f17a823 and c55dc33.

⛔ Files ignored due to path filters (3)
  • Projects/Presentation/Resources/Images.xcassets/profile_graphic.imageset/profile_graphic.png is excluded by !**/*.png
  • Projects/Presentation/Resources/Images.xcassets/profile_graphic.imageset/profile_graphic@2x.png is excluded by !**/*.png
  • Projects/Presentation/Resources/Images.xcassets/profile_graphic.imageset/profile_graphic@3x.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • Projects/DataSource/Sources/Common/DataSourceDependencyAssembler.swift (1 hunks)
  • Projects/DataSource/Sources/DTO/AppVersionDTO.swift (1 hunks)
  • Projects/DataSource/Sources/Repository/AppConfigRepository.swift (1 hunks)
  • Projects/Domain/Sources/Protocol/Repository/AppConfigRepositoryProtocol.swift (1 hunks)
  • Projects/Presentation/Resources/Images.xcassets/profile_graphic.imageset/Contents.json (1 hunks)
  • Projects/Presentation/Sources/Common/DesignSystem/BitnagilGraphic.swift (1 hunks)
  • Projects/Presentation/Sources/MyPage/View/MypageView.swift (1 hunks)
  • Projects/Presentation/Sources/Setting/View/SettingView.swift (12 hunks)
  • Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift (5 hunks)
  • SupportingFiles/Info.plist (1 hunks)

Walkthrough

이번 변경에서는 앱 버전 정보를 원격(App Store)에서 조회하는 기능이 추가되었습니다. 이를 위해 새로운 DTO, 레포지토리 구현, 프로토콜이 도입되었고, DI 컨테이너에 등록되었습니다. SettingView 및 ViewModel에서는 의존성 주입과 버전 조회, 인증 상태 변경 시 루트 뷰 전환 등이 반영되었습니다. 알림 관련 UI는 주석 처리되어 비활성화되었습니다.

Changes

Cohort / File(s) Change Summary
App 버전 DTO 추가
Projects/DataSource/Sources/DTO/AppVersionDTO.swift
App Store 버전 정보를 디코딩할 AppVersionDTO, AppStoreResultDTO 구조체 추가
AppConfigRepository 도입
Projects/DataSource/Sources/Repository/AppConfigRepository.swift
AppConfigRepository 클래스 및 fetchAppVersion() 메서드 구현. iTunes Lookup API를 통해 앱 버전 조회 기능 추가.
AppConfigRepository 프로토콜 도입
Projects/Domain/Sources/Protocol/Repository/AppConfigRepositoryProtocol.swift
AppConfigRepositoryProtocol 프로토콜 및 fetchAppVersion() 메서드 선언
DI 등록
Projects/DataSource/Sources/Common/DataSourceDependencyAssembler.swift
DI 컨테이너에 AppConfigRepositoryProtocolAppConfigRepository 매핑 등록
SettingView 리팩토링 및 버전 조회 연동
Projects/Presentation/Sources/Setting/View/SettingView.swift
알림 관련 코드 전체 주석 처리, DI로 레포지토리 주입 및 버전 조회 액션 추가, 인증 해제 시 루트 뷰 IntroView로 교체, import 추가 등
SettingViewModel 리팩토링 및 버전 조회 로직 추가
Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift
.fetchVersion 입력 추가, configure(...) 메서드로 레포지토리 주입, 비동기 버전 조회/비교 및 상태 발행, 로그아웃/탈퇴 비동기 처리 등
Info.plist 변경
SupportingFiles/Info.plist
앱에서 쿼리 가능한 URL 스킴에 "itms-apps" 추가
프로필 그래픽 자산 추가 및 사용
Projects/Presentation/Resources/Images.xcassets/profile_graphic.imageset/Contents.json, Projects/Presentation/Sources/Common/DesignSystem/BitnagilGraphic.swift, Projects/Presentation/Sources/MyPage/View/MypageView.swift
프로필 그래픽 이미지 셋 추가 및 BitnagilGraphic에 프로필 이미지 프로퍼티 추가, MypageView에서 프로필 이미지 뷰에 해당 이미지 적용, 기존 레이어 스타일 제거

Sequence Diagram(s)

sequenceDiagram
    participant SettingView
    participant SettingViewModel
    participant AppConfigRepository
    participant App Store API

    SettingView->>SettingViewModel: configure(authRepo, appConfigRepo)
    SettingView->>SettingViewModel: action(.fetchVersion)
    SettingViewModel->>AppConfigRepository: fetchAppVersion()
    AppConfigRepository->>App Store API: GET /lookup?bundleId=...&country=KR
    App Store API-->>AppConfigRepository: AppVersionDTO (JSON)
    AppConfigRepository-->>SettingViewModel: 버전 정보 반환
    SettingViewModel-->>SettingView: 버전 상태 발행 (.latest / .needUpdate)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐇
새 버전 찾아 깡총깡총,
앱스토어로 달려가요!
알림 토글 잠시 쉬고,
버전 비교 똑똑하게,
로그아웃도 한 번에 척!
코드 속에 봄바람 불어,
업데이트는 이제 문제없죠!

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/setting

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary or @coderabbitai 요약 to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

♻️ Duplicate comments (1)
Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift (1)

119-128: 회원 탈퇴도 로그아웃과 동일한 에러 처리 개선이 필요합니다.

🧹 Nitpick comments (4)
Projects/DataSource/Sources/DTO/AppVersionDTO.swift (1)

8-15: 접근 제어자를 명시적으로 추가하는 것을 권장합니다.

DTO가 DataSource 모듈 내부에서만 사용된다면 internal 또는 private을 명시적으로 선언하는 것이 좋습니다.

-struct AppVersionDTO: Codable {
+internal struct AppVersionDTO: Codable {
     let resultCount: Int
     let results: [AppStoreResultDTO]
 }

-struct AppStoreResultDTO: Codable {
+internal struct AppStoreResultDTO: Codable {
     let version: String
 }
Projects/DataSource/Sources/Repository/AppConfigRepository.swift (1)

13-21: URLSession 설정에 타임아웃을 추가하는 것을 권장합니다.

기본 URLSession은 매우 긴 타임아웃을 가지고 있어, 네트워크 문제 발생 시 사용자가 오래 기다릴 수 있습니다.

+private lazy var session: URLSession = {
+    let configuration = URLSessionConfiguration.default
+    configuration.timeoutIntervalForRequest = 10.0
+    return URLSession(configuration: configuration)
+}()
+
 func fetchAppVersion() async throws -> String? {
     guard let bundleId = Bundle.main.bundleIdentifier else { return nil }
     let urlString = "https://itunes.apple.com/lookup?bundleId=\(bundleId)&country=KR"
     guard let url = URL(string: urlString) else { return nil }
 
-    let (data, _) = try await URLSession.shared.data(from: url)
+    let (data, _) = try await session.data(from: url)
Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift (1)

114-114: TODO 주석을 이슈로 관리하는 것을 권장합니다.

에러 처리를 위한 토스트 팝업 구현이 필요하다고 명시되어 있습니다. 이를 GitHub 이슈로 등록하여 추적하는 것이 좋습니다.

에러 처리를 위한 토스트 팝업 구현에 대한 이슈를 생성할까요?

Also applies to: 125-125

Projects/Presentation/Sources/Setting/View/SettingView.swift (1)

201-201: 미사용 클로저 매개변수 수정

SwiftLint 경고에 따라 isAuthenticated 매개변수가 사용되지 않으므로 _로 대체해야 합니다.

-            .sink(receiveValue: { isAuthenticated in
+            .sink(receiveValue: { _ in
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0315ddb and c3f1319.

📒 Files selected for processing (6)
  • Projects/DataSource/Sources/Common/DataSourceDependencyAssembler.swift (1 hunks)
  • Projects/DataSource/Sources/DTO/AppVersionDTO.swift (1 hunks)
  • Projects/DataSource/Sources/Repository/AppConfigRepository.swift (1 hunks)
  • Projects/Domain/Sources/Protocol/Repository/AppConfigRepositoryProtocol.swift (1 hunks)
  • Projects/Presentation/Sources/Setting/View/SettingView.swift (12 hunks)
  • Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift (5 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Common/PresentationDependencyAssembler.swift:0-0
Timestamp: 2025-07-16T10:57:16.559Z
Learning: choijungp는 추후 CustomAlertView를 만들어서 에러 처리를 UI로 해결하도록 수정할 계획을 가지고 있음.
Learnt from: taipaise
PR: YAPP-Github/Bitnagil-iOS#33
File: Projects/DataSource/Sources/Repository/RoutineRepository.swift:45-46
Timestamp: 2025-08-04T23:43:28.527Z
Learning: taipaise는 디버깅을 위해 명시적인 에러 처리를 선호함. nil 체크 시 조용히 실패하는 것보다 에러를 던지는 방식을 추후 디버깅에 도움이 된다고 생각함.
📚 Learning: baseviewcontroller의 viewdidload() 메서드에서 이미 configureattribute(), configurelayout(), bind()를 호출하므로, 하...
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Login/View/TermsAgreementView.swift:44-46
Timestamp: 2025-07-16T09:09:13.869Z
Learning: BaseViewController의 viewDidLoad() 메서드에서 이미 configureAttribute(), configureLayout(), bind()를 호출하므로, 하위 클래스에서 super.viewDidLoad()를 호출하면 이 메서드들이 자동으로 호출된다. 따라서 하위 클래스에서 추가로 호출할 필요가 없다.

Applied to files:

  • Projects/Presentation/Sources/Setting/View/SettingView.swift
📚 Learning: onboardingrecommendedroutineview에서 viewwillappear에 registeronboarding 호출하는 것이 적절한 이유: 사용자가 이전 페이지에서 ...
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Onboarding/View/OnboardingRecommendedRoutineView.swift:57-59
Timestamp: 2025-07-16T09:21:15.038Z
Learning: OnboardingRecommendedRoutineView에서 viewWillAppear에 registerOnboarding 호출하는 것이 적절한 이유: 사용자가 이전 페이지에서 온보딩 선택지를 변경한 후 돌아올 때 새로운 선택지로 다시 등록해야 하기 때문. 홈 뷰에서는 이 뷰로 돌아올 수 없어서 중복 호출 문제가 발생하지 않음.

Applied to files:

  • Projects/Presentation/Sources/Setting/View/SettingView.swift
🪛 SwiftLint (0.57.0)
Projects/Presentation/Sources/Setting/View/SettingView.swift

[Warning] 201-201: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)

Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift

[Warning] 114-114: TODOs should be resolved (- 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 ...)

(todo)


[Warning] 125-125: TODOs should be resolved (- 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 ...)

(todo)

🔇 Additional comments (9)
Projects/DataSource/Sources/Common/DataSourceDependencyAssembler.swift (1)

39-42: LGTM!

AppConfigRepositoryProtocol의 DI 등록이 기존 패턴과 일치하게 올바르게 구현되었습니다.

Projects/Domain/Sources/Protocol/Repository/AppConfigRepositoryProtocol.swift (1)

8-10: LGTM!

프로토콜이 깔끔하게 정의되었습니다. 비동기 처리와 에러 핸들링을 위한 async throws 패턴이 적절합니다.

Projects/Presentation/Sources/Setting/View/SettingView.swift (7)

9-9: 새로운 모듈 import 추가

Domain과 Shared 모듈을 import하여 의존성 주입에 필요한 프로토콜과 유틸리티에 접근할 수 있도록 했습니다.

Also applies to: 11-11


30-30: 알림 관련 UI 비활성화

알림 섹션을 주석 처리하여 현재 개발 단계에서는 비활성화했습니다. PR 목표에 언급된 대로 추후 기능 추가 시 활성화할 예정인 것으로 보입니다.

Also applies to: 36-37


119-133: 의존성 주입 구현 및 ViewModel 구성

AuthRepositoryProtocol과 AppConfigRepositoryProtocol을 DI 컨테이너에서 해결하고, ViewModel에 전달하여 구성하는 로직이 잘 구현되었습니다. 또한 앱 버전 정보를 가져오기 위해 .fetchVersion 액션을 트리거하는 것도 적절합니다.


145-169: 알림 관련 바인딩 코드 비활성화

알림 토글 상태 처리를 위한 Combine 바인딩 코드가 주석 처리되었습니다. 알림 UI와 일관성 있게 비활성화되었습니다.


192-192: 버전 표시 포맷 개선

버전 문자열에 공백을 추가하여 가독성을 향상시켰습니다.

Also applies to: 194-194


199-213: 인증 상태 변경 시 루트 뷰 전환 로직

로그아웃 시 IntroView로 루트 뷰 컨트롤러를 교체하는 로직이 적절하게 구현되었습니다. WindowScene을 통해 안전하게 루트 뷰를 변경하는 방식이 좋습니다.


222-223: 테이블뷰 관련 알림 섹션 비활성화

UITableView의 delegate/datasource 메서드에서 알림 관련 처리가 모두 주석 처리되어 일관성 있게 비활성화되었습니다. 추후 알림 기능 추가 시 주석을 해제하면 됩니다.

Also applies to: 271-272, 290-292, 327-330, 345-346, 386-393

Comment on lines +15 to +16
let urlString = "https://itunes.apple.com/lookup?bundleId=\(bundleId)&country=KR"
guard let url = URL(string: urlString) else { return nil }
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

국가 코드를 하드코딩하지 않고 유연하게 처리하는 것을 권장합니다.

현재 "KR"로 하드코딩된 국가 코드는 향후 다른 지역 지원 시 문제가 될 수 있습니다. Bundle의 locale 정보를 사용하거나 설정 가능하도록 개선하는 것이 좋습니다.

 func fetchAppVersion() async throws -> String? {
     guard let bundleId = Bundle.main.bundleIdentifier else { return nil }
-    let urlString = "https://itunes.apple.com/lookup?bundleId=\(bundleId)&country=KR"
+    let countryCode = Locale.current.regionCode ?? "KR"
+    let urlString = "https://itunes.apple.com/lookup?bundleId=\(bundleId)&country=\(countryCode)"
     guard let url = URL(string: urlString) else { return nil }
🤖 Prompt for AI Agents
In Projects/DataSource/Sources/Repository/AppConfigRepository.swift around lines
15 to 16, the country code "KR" is hardcoded in the URL string, which reduces
flexibility for supporting other regions. Modify the code to dynamically obtain
the country code from the device's locale settings or allow it to be passed as a
configurable parameter, then use that value in the URL string instead of the
fixed "KR".

Comment on lines +18 to +21
let (data, _) = try await URLSession.shared.data(from: url)
let decoded = try JSONDecoder().decode(AppVersionDTO.self, from: data)
return decoded.results.first?.version
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

HTTP 응답 상태 코드 검증이 필요합니다.

네트워크 요청 후 HTTP 상태 코드를 확인하지 않고 있어, 서버 오류나 잘못된 응답을 처리하지 못할 수 있습니다.

-let (data, _) = try await URLSession.shared.data(from: url)
+let (data, response) = try await URLSession.shared.data(from: url)
+guard let httpResponse = response as? HTTPURLResponse,
+      (200...299).contains(httpResponse.statusCode) else {
+    throw NSError(domain: "AppConfigRepository", 
+                  code: (response as? HTTPURLResponse)?.statusCode ?? -1,
+                  userInfo: [NSLocalizedDescriptionKey: "Invalid response from App Store"])
+}
 let decoded = try JSONDecoder().decode(AppVersionDTO.self, from: data)
📝 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.

Suggested change
let (data, _) = try await URLSession.shared.data(from: url)
let decoded = try JSONDecoder().decode(AppVersionDTO.self, from: data)
return decoded.results.first?.version
}
let (data, response) = try await URLSession.shared.data(from: url)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
throw NSError(
domain: "AppConfigRepository",
code: (response as? HTTPURLResponse)?.statusCode ?? -1,
userInfo: [NSLocalizedDescriptionKey: "Invalid response from App Store"]
)
}
let decoded = try JSONDecoder().decode(AppVersionDTO.self, from: data)
return decoded.results.first?.version
🤖 Prompt for AI Agents
In Projects/DataSource/Sources/Repository/AppConfigRepository.swift around lines
18 to 21, the code does not check the HTTP response status code after the
network request, which can cause issues if the server returns an error or
invalid response. Modify the code to capture the URLResponse from the data task,
cast it to HTTPURLResponse, and verify that the status code indicates success
(e.g., 200-299). If the status code is outside this range, throw an appropriate
error or handle the failure before attempting to decode the data.

Comment on lines 108 to 126
private func logout() {
// TODO: - 로그아웃 api
Task {
do {
try await authRepository?.logout()
authenticatedSubject.send(false)
} catch {
// TODO: - 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 불안정 알림
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

에러 처리를 개선해야 합니다.

현재 에러를 무시하고 있는데, 사용자에게 피드백이 필요합니다. 또한 authRepository가 nil인 경우 아무 일도 일어나지 않아 혼란을 줄 수 있습니다.

 private func logout() {
+    guard let authRepository = authRepository else {
+        print("AuthRepository is not configured")
+        return
+    }
     Task {
         do {
-            try await authRepository?.logout()
+            try await authRepository.logout()
             authenticatedSubject.send(false)
         } catch {
             // TODO: - 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 불안정 알림
+            print("Logout failed: \(error)")
         }
     }
 }
📝 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.

Suggested change
private func logout() {
// TODO: - 로그아웃 api
Task {
do {
try await authRepository?.logout()
authenticatedSubject.send(false)
} catch {
// TODO: - 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 불안정 알림
}
}
}
private func logout() {
guard let authRepository = authRepository else {
print("AuthRepository is not configured")
return
}
Task {
do {
try await authRepository.logout()
authenticatedSubject.send(false)
} catch {
// TODO: - 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 불안정 알림
print("Logout failed: \(error)")
}
}
}
🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 114-114: TODOs should be resolved (- 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 ...)

(todo)

🤖 Prompt for AI Agents
In Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift around
lines 108 to 117, the logout function currently ignores errors and does nothing
if authRepository is nil, which can confuse users. Update the code to handle the
case when authRepository is nil by providing appropriate user feedback, and
improve error handling by showing a toast or alert to inform the user of network
issues or logout failures.

Comment on lines +130 to 155
private func fetchVersion() {
let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String

Task {
do {
let appStoreAppVersion = try await appConfigRepository?.fetchAppVersion()

if currentVersion != appStoreAppVersion {
versionSubject.send(.needUpdate(version: currentVersion ?? ""))
} else {
versionSubject.send(.latest(version: currentVersion ?? ""))
}
} catch {

}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

fetchVersion 메서드에서 에러 처리가 비어있습니다.

네트워크 오류나 파싱 오류 발생 시 사용자에게 아무런 피드백이 없습니다. 최소한 현재 버전이라도 표시해주는 것이 좋습니다.

 private func fetchVersion() {
     let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
 
     Task {
         do {
             let appStoreAppVersion = try await appConfigRepository?.fetchAppVersion()
 
             if currentVersion != appStoreAppVersion {
                 versionSubject.send(.needUpdate(version: currentVersion ?? ""))
             } else {
                 versionSubject.send(.latest(version: currentVersion ?? ""))
             }
         } catch {
-
+            // 에러 발생 시에도 현재 버전은 표시
+            versionSubject.send(.latest(version: currentVersion ?? ""))
+            print("Failed to fetch app version: \(error)")
         }
     }
 }
🤖 Prompt for AI Agents
In Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift around
lines 130 to 146, the fetchVersion method's catch block is empty, providing no
feedback on errors like network or parsing failures. Update the catch block to
send a versionSubject event indicating the current version as the latest,
ensuring the user sees at least the current version even if fetching the app
store version fails.

Comment on lines +137 to +150
if currentVersion != appStoreAppVersion {
versionSubject.send(.needUpdate(version: currentVersion ?? ""))
} else {
versionSubject.send(.latest(version: currentVersion ?? ""))
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

버전 비교 로직이 단순한 문자열 비교를 사용하고 있습니다.

현재 버전 비교가 단순 문자열 비교로 되어 있어 "1.0.10"과 "1.0.9" 같은 경우 잘못된 결과를 낼 수 있습니다. 또한 appStoreAppVersion이 nil일 때의 처리가 명확하지 않습니다.


🏁 Script executed:

#!/bin/bash
# 버전 비교를 위한 유틸리티 함수나 라이브러리 사용 여부 확인
rg -A 5 "version.*compar|compar.*version" --type swift
ast-grep --pattern 'func $_($$$ version $$$) { $$$ }'

Length of output: 112


버전 비교 로직 재확인을 위해 전체 코드베이스에서 Version 관련 타입 정의 및 Comparable 준수 여부를 검색합니다.


🏁 Script executed:

#!/bin/bash
# Repository 전체에서 Version 관련 타입 정의 및 Comparable 준수 검사
rg -n "struct .*Version" --type swift
rg -n "enum .*Version" --type swift
rg -n "class .*Version" --type swift
rg -n "extension .*Version.*:.*Comparable" --type swift

Length of output: 357


AppVersionDTO와 SettingViewModel의 VersionType 정의를 확인하여 버전 필드 타입과 비교 로직 의존 여부를 검증해야 합니다.


🏁 Script executed:

#!/bin/bash
# AppVersionDTO에서 버전 필드 타입 확인
rg -n "struct AppVersionDTO" -A 20 Projects/DataSource/Sources/DTO/AppVersionDTO.swift

# SettingViewModel 내부 VersionType 확인
rg -n "enum VersionType" -A 20 Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift

Length of output: 1097


버전 비교 로직을 문자열 비교에서 SemVer 비교로 교체 및 nil 처리 명확화 필요

현재 currentVersionappStoreAppVersion을 단순 문자열(!=)로 비교하면

  • “1.0.10” vs “1.0.9” 같은 케이스에서 잘못된 결과 발생
  • appStoreAppVersionnil일 때 업데이트 여부가 불명확

수정 제안:

  • Foundation의 Version 타입(macOS 10.15+) 또는 서드파티 SemanticVersion 라이브러리 등으로 버전 문자열을 파싱해 Comparable로 비교
  • appStoreAppVersion == nil인 경우 로직(에러 표시, 재시도 등)을 명확히 정의
  • 수정 위치:
    • Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift Lines 137–141
🤖 Prompt for AI Agents
In Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift around
lines 137 to 141, replace the current string inequality comparison between
currentVersion and appStoreAppVersion with a semantic version comparison using
Foundation's Version type or a similar semantic versioning library. Parse both
version strings into Version instances and compare them using their Comparable
conformance. Additionally, explicitly handle the case where appStoreAppVersion
is nil by defining clear behavior such as showing an error or retrying, instead
of proceeding with the comparison. Update the logic to send the appropriate
versionSubject event based on this semantic comparison and nil handling.

@taipaise
Copy link
Copy Markdown
Collaborator Author

taipaise commented Aug 5, 2025

@choijungp 업데이트 버튼을 눌렀을때, 앱스토어로 이동해야하는데 관련 로직은 조금 고민해봐야할 것 같아서 우선은 PR을 닫도록 하겠습니다. 죄송합니다.

@taipaise taipaise closed this Aug 5, 2025
@taipaise taipaise reopened this Aug 7, 2025
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a 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

♻️ Duplicate comments (3)
Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift (3)

117-126: 에러 처리를 개선해야 합니다

현재 에러를 무시하고 있는데, 사용자에게 피드백이 필요합니다. 또한 authRepository가 nil인 경우 아무 일도 일어나지 않아 혼란을 줄 수 있습니다.

 private func logout() {
+    guard let authRepository = authRepository else {
+        print("AuthRepository is not configured")
+        return
+    }
     Task {
         do {
-            try await authRepository?.logout()
+            try await authRepository.logout()
             authenticatedSubject.send(false)
         } catch {
             // TODO: - 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 불안정 알림
+            print("Logout failed: \(error)")
         }
     }
 }

139-155: fetchVersion 메서드에서 에러 처리가 비어있습니다

네트워크 오류나 파싱 오류 발생 시 사용자에게 아무런 피드백이 없습니다. 최소한 현재 버전이라도 표시해주는 것이 좋습니다.

 private func fetchVersion() {
     let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
 
     Task {
         do {
             let appStoreAppVersion = try await appConfigRepository?.fetchAppVersion()
 
             if currentVersion != appStoreAppVersion {
                 versionSubject.send(.needUpdate(version: currentVersion ?? ""))
             } else {
                 versionSubject.send(.latest(version: currentVersion ?? ""))
             }
         } catch {
-
+            // 에러 발생 시에도 현재 버전은 표시
+            versionSubject.send(.latest(version: currentVersion ?? ""))
+            print("Failed to fetch app version: \(error)")
         }
     }
 }

146-150: 버전 비교 로직이 단순한 문자열 비교를 사용하고 있습니다

현재 버전 비교가 단순 문자열 비교로 되어 있어 "1.0.10"과 "1.0.9" 같은 경우 잘못된 결과를 낼 수 있습니다. 또한 appStoreAppVersion이 nil일 때의 처리가 명확하지 않습니다.

시맨틱 버전 비교를 위해 다음과 같은 방법을 고려하세요:

  1. Foundation의 Version 타입 사용 (iOS 14+)
  2. 버전 문자열을 컴포넌트로 분리하여 숫자 비교
  3. 서드파티 라이브러리 활용
 private func fetchVersion() {
     let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
+    guard let currentVersion = currentVersion else {
+        versionSubject.send(.latest(version: "Unknown"))
+        return
+    }
 
     Task {
         do {
-            let appStoreAppVersion = try await appConfigRepository?.fetchAppVersion()
+            guard let appStoreAppVersion = try await appConfigRepository?.fetchAppVersion() else {
+                versionSubject.send(.latest(version: currentVersion))
+                return
+            }
 
-            if currentVersion != appStoreAppVersion {
+            // 버전 비교 로직 개선 필요
+            if compareVersions(current: currentVersion, appStore: appStoreAppVersion) {
                 versionSubject.send(.needUpdate(version: currentVersion))
             } else {
                 versionSubject.send(.latest(version: currentVersion))
             }
         } catch {
             versionSubject.send(.latest(version: currentVersion))
         }
     }
 }
+
+private func compareVersions(current: String, appStore: String) -> Bool {
+    // TODO: 시맨틱 버전 비교 구현
+    return current != appStore
+}
🧹 Nitpick comments (2)
Projects/Presentation/Sources/Setting/View/SettingView.swift (1)

132-133: fetchVersion 호출 시점을 viewWillAppear로 이동 고려

현재 configureAttribute에서 즉시 fetchVersion을 호출하고 있습니다. 뷰 라이프사이클을 고려하면 viewWillAppear에서 호출하는 것이 더 적절할 수 있습니다. 이렇게 하면 사용자가 설정 화면으로 돌아올 때마다 최신 버전을 확인할 수 있습니다.

 override func configureAttribute() {
     // ... existing code ...
     viewModel.configure(authRepository: authRepository, appConfigRepository: appConfigRepository)
-    viewModel.action(input: .fetchVersion)
 }
 
 override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     configureNavigationBar(navigationStyle: .withBackButton(title: "설정"))
+    viewModel.action(input: .fetchVersion)
 }
Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift (1)

20-21: App Store URL에 플레이스홀더가 포함되어 있습니다

URL에 {빛나길 id} 플레이스홀더가 있습니다. 앱 출시 전에 실제 App Store ID로 교체해야 합니다.

실제 App Store ID로 교체하는 작업이 필요합니다. 이를 추적하기 위한 이슈를 생성할까요?

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c3f1319 and 9c4ecba.

📒 Files selected for processing (3)
  • Projects/Presentation/Sources/Setting/View/SettingView.swift (12 hunks)
  • Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift (5 hunks)
  • SupportingFiles/Info.plist (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • SupportingFiles/Info.plist
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Common/PresentationDependencyAssembler.swift:0-0
Timestamp: 2025-07-16T10:57:16.559Z
Learning: choijungp는 추후 CustomAlertView를 만들어서 에러 처리를 UI로 해결하도록 수정할 계획을 가지고 있음.
Learnt from: taipaise
PR: YAPP-Github/Bitnagil-iOS#33
File: Projects/DataSource/Sources/Repository/RoutineRepository.swift:45-46
Timestamp: 2025-08-04T23:43:28.527Z
Learning: taipaise는 디버깅을 위해 명시적인 에러 처리를 선호함. nil 체크 시 조용히 실패하는 것보다 에러를 던지는 방식을 추후 디버깅에 도움이 된다고 생각함.
📚 Learning: baseviewcontroller의 viewdidload() 메서드에서 이미 configureattribute(), configurelayout(), bind()를 호출하므로, 하...
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Login/View/TermsAgreementView.swift:44-46
Timestamp: 2025-07-16T09:09:13.869Z
Learning: BaseViewController의 viewDidLoad() 메서드에서 이미 configureAttribute(), configureLayout(), bind()를 호출하므로, 하위 클래스에서 super.viewDidLoad()를 호출하면 이 메서드들이 자동으로 호출된다. 따라서 하위 클래스에서 추가로 호출할 필요가 없다.

Applied to files:

  • Projects/Presentation/Sources/Setting/View/SettingView.swift
📚 Learning: onboardingrecommendedroutineview에서 viewwillappear에 registeronboarding 호출하는 것이 적절한 이유: 사용자가 이전 페이지에서 ...
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Onboarding/View/OnboardingRecommendedRoutineView.swift:57-59
Timestamp: 2025-07-16T09:21:15.038Z
Learning: OnboardingRecommendedRoutineView에서 viewWillAppear에 registerOnboarding 호출하는 것이 적절한 이유: 사용자가 이전 페이지에서 온보딩 선택지를 변경한 후 돌아올 때 새로운 선택지로 다시 등록해야 하기 때문. 홈 뷰에서는 이 뷰로 돌아올 수 없어서 중복 호출 문제가 발생하지 않음.

Applied to files:

  • Projects/Presentation/Sources/Setting/View/SettingView.swift
🧬 Code Graph Analysis (1)
Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift (1)
Projects/DataSource/Sources/Repository/AppConfigRepository.swift (1)
  • fetchAppVersion (13-21)
🪛 SwiftLint (0.57.0)
Projects/Presentation/Sources/Setting/View/SettingView.swift

[Warning] 204-204: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)

Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift

[Warning] 123-123: TODOs should be resolved (- 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 ...)

(todo)


[Warning] 134-134: TODOs should be resolved (- 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 ...)

(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). (2)
  • GitHub Check: build
  • GitHub Check: build


viewModel.output.isAuthenticatedPublisher
.receive(on: DispatchQueue.main)
.sink(receiveValue: { isAuthenticated in
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Aug 7, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

사용하지 않는 클로저 파라미터를 _로 대체

isAuthenticated 파라미터를 사용하지 않으므로 _로 대체해야 합니다.

-            .sink(receiveValue: { isAuthenticated in
+            .sink(receiveValue: { _ in
📝 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.

Suggested change
.sink(receiveValue: { isAuthenticated in
.sink(receiveValue: { _ in
🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 204-204: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)

🤖 Prompt for AI Agents
In Projects/Presentation/Sources/Setting/View/SettingView.swift at line 204, the
closure parameter named isAuthenticated is not used inside the closure body.
Replace the parameter name isAuthenticated with an underscore (_) to indicate
that the parameter is intentionally unused.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

아하 ! 아니면 logout, withdraw 시에 false를 보내니까 false 받았을 때에만 IntroView로 이동하는 것은 어떠신가요 ??

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@choijungp 좋은 제안입니다! 맞습니다. 로그아웃이나 탈퇴 시에만 IntroView로 이동해야 하므로, isAuthenticatedfalse일 때에만 화면 전환을 하는 것이 더 정확한 로직이네요.

viewModel.output.isAuthenticatedPublisher
    .receive(on: DispatchQueue.main)
    .sink(receiveValue: { isAuthenticated in
        guard !isAuthenticated else { return }
        
        guard
            let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
            let sceneDelegate = windowScene.delegate as? UIWindowSceneDelegate,
            let window = sceneDelegate.window
        else { return }

        let introView = IntroView()
        let navigationController = UINavigationController(rootViewController: introView)
        window?.rootViewController = navigationController
        window?.makeKeyAndVisible()
    })
    .store(in: &cancellables)

이렇게 하면 SwiftLint 경고도 해결되고, 로직도 더 명확해집니다!


🧠 Learnings used
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Onboarding/View/OnboardingRecommendedRoutineView.swift:57-59
Timestamp: 2025-07-16T09:21:15.038Z
Learning: OnboardingRecommendedRoutineView에서 viewWillAppear에 registerOnboarding 호출하는 것이 적절한 이유: 사용자가 이전 페이지에서 온보딩 선택지를 변경한 후 돌아올 때 새로운 선택지로 다시 등록해야 하기 때문. 홈 뷰에서는 이 뷰로 돌아올 수 없어서 중복 호출 문제가 발생하지 않음.

Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Common/PresentationDependencyAssembler.swift:0-0
Timestamp: 2025-07-16T10:57:16.559Z
Learning: choijungp는 추후 CustomAlertView를 만들어서 에러 처리를 UI로 해결하도록 수정할 계획을 가지고 있음.

Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Domain/Sources/UseCase/Onboarding/OnboardingUseCase.swift:0-0
Timestamp: 2025-07-16T10:58:30.858Z
Learning: choijungp는 OnboardingUseCase의 convertToDictionary 함수에서 에러 처리 개선을 추후 고민하고 반영할 계획을 가지고 있음.

Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#30
File: Projects/DataSource/Sources/NetworkService/Plugin/RefreshTokenPlugin.swift:42-43
Timestamp: 2025-07-30T03:56:18.617Z
Learning: choijungp는 현재 테스트 단계에서 RefreshTokenPlugin의 토큰 갱신 로직 디버깅을 위해 액세스 토큰과 리프레시 토큰의 실제 값을 로그에 기록하는 것을 선호함.

Comment on lines 128 to +137
private func withdrawal() {
// TODO: - 회원탈퇴 api
Task {
do {
try await authRepository?.withdraw()
authenticatedSubject.send(false)
} catch {
// TODO: - 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 불안정 알림
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

withdrawal 메서드도 동일한 에러 처리 개선이 필요합니다

logout과 마찬가지로 에러 처리와 nil 체크가 필요합니다.

 private func withdrawal() {
+    guard let authRepository = authRepository else {
+        print("AuthRepository is not configured")
+        return
+    }
     Task {
         do {
-            try await authRepository?.withdraw()
+            try await authRepository.withdraw()
             authenticatedSubject.send(false)
         } catch {
             // TODO: - 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 불안정 알림
+            print("Withdrawal failed: \(error)")
         }
     }
 }
📝 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.

Suggested change
private func withdrawal() {
// TODO: - 회원탈퇴 api
Task {
do {
try await authRepository?.withdraw()
authenticatedSubject.send(false)
} catch {
// TODO: - 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 불안정 알림
}
}
}
private func withdrawal() {
guard let authRepository = authRepository else {
print("AuthRepository is not configured")
return
}
Task {
do {
try await authRepository.withdraw()
authenticatedSubject.send(false)
} catch {
// TODO: - 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 불안정 알림
print("Withdrawal failed: \(error)")
}
}
}
🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 134-134: TODOs should be resolved (- 토스트 팝업 구현 시 + 디자인 추가 시 네트워크 ...)

(todo)

🤖 Prompt for AI Agents
In Projects/Presentation/Sources/Setting/ViewModel/SettingViewModel.swift around
lines 128 to 137, the withdrawal() method lacks proper error handling and nil
checking for authRepository similar to logout. Add a nil check for
authRepository before calling withdraw(), and improve the catch block to handle
errors appropriately, such as showing a network instability toast notification
or logging the error.

Copy link
Copy Markdown
Contributor

@choijungp choijungp left a comment

Choose a reason for hiding this comment

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

띵동두 고생 많으셨씀니다 ㅜㅜ !!!!!!!! 조금만 더 힘내붑시다 !!!! 아자아자아자 !!!
🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥


viewModel.output.isAuthenticatedPublisher
.receive(on: DispatchQueue.main)
.sink(receiveValue: { isAuthenticated in
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

아하 ! 아니면 logout, withdraw 시에 false를 보내니까 false 받았을 때에만 IntroView로 이동하는 것은 어떠신가요 ??

Comment on lines +95 to +98
func configure(authRepository: AuthRepositoryProtocol, appConfigRepository: AppConfigRepositoryProtocol) {
self.authRepository = authRepository
self.appConfigRepository = appConfigRepository
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

SettingView에서는 생성자 주입이 아닌 setter로 의존성을 주입하고 있는지 여쭤봐도 될까용 ??

Comment on lines +20 to +21
case .update:
return URL(string: "itms-apps://itunes.apple.com/app/{빛나길 id}")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

요기서 {빛나길 id}는 App bundle id랑은 다른 건가용 ?? 순수 궁금증 !!!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

지금은 무조건 버전 옆에 [업데이트] 버튼이 뜨는 건가욤 ???

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a 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 (1)
Projects/Presentation/Sources/MyPage/View/MypageView.swift (1)

16-16: 사용하지 않는 상수를 제거하세요.

profileImageViewCornerRadius 상수가 더 이상 사용되지 않으므로 제거하는 것이 좋겠습니다.

-        static let profileImageViewCornerRadius: CGFloat = profileImageViewSize / 2
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c4ecba and f17a823.

⛔ Files ignored due to path filters (3)
  • Projects/Presentation/Resources/Images.xcassets/profile_graphic.imageset/profile_graphic.png is excluded by !**/*.png
  • Projects/Presentation/Resources/Images.xcassets/profile_graphic.imageset/profile_graphic@2x.png is excluded by !**/*.png
  • Projects/Presentation/Resources/Images.xcassets/profile_graphic.imageset/profile_graphic@3x.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • Projects/Presentation/Resources/Images.xcassets/profile_graphic.imageset/Contents.json (1 hunks)
  • Projects/Presentation/Sources/Common/DesignSystem/BitnagilGraphic.swift (1 hunks)
  • Projects/Presentation/Sources/MyPage/View/MypageView.swift (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • Projects/Presentation/Sources/Common/DesignSystem/BitnagilGraphic.swift
  • Projects/Presentation/Resources/Images.xcassets/profile_graphic.imageset/Contents.json
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Common/PresentationDependencyAssembler.swift:0-0
Timestamp: 2025-07-16T10:57:16.559Z
Learning: choijungp는 추후 CustomAlertView를 만들어서 에러 처리를 UI로 해결하도록 수정할 계획을 가지고 있음.
Learnt from: taipaise
PR: YAPP-Github/Bitnagil-iOS#33
File: Projects/DataSource/Sources/Repository/RoutineRepository.swift:45-46
Timestamp: 2025-08-04T23:43:28.527Z
Learning: taipaise는 디버깅을 위해 명시적인 에러 처리를 선호함. nil 체크 시 조용히 실패하는 것보다 에러를 던지는 방식을 추후 디버깅에 도움이 된다고 생각함.
🔇 Additional comments (1)
Projects/Presentation/Sources/MyPage/View/MypageView.swift (1)

54-54: 이미지 설정 간소화가 적절합니다.

BitnagilGraphic.profileGraphic을 사용하여 프로필 이미지 설정을 간소화한 것은 좋은 변경입니다. 수동 스타일링 대신 미리 디자인된 그래픽 에셋을 사용하는 것이 더 일관성 있고 유지보수하기 쉽습니다.

@choijungp choijungp merged commit 600438d into develop Aug 7, 2025
1 check passed
@choijungp choijungp deleted the feat/setting branch August 7, 2025 16:02
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.

2 participants