Skip to content

Conversation

@youz2me
Copy link
Member

@youz2me youz2me commented Jun 30, 2025

👻 PULL REQUEST

📄 작업 내용

  • 로그인 중 에러 발생 시 토스트가 뜨도록 구현했어요.
  • UserDefaultsStorage의 생성자에서 JSONEncoder, JSONDecoder를 선택적으로 명시할 수 있도록 리팩토링을 진행했어요.
  • 가독성을 위해 LoginViewModel에서 기능별 메서드 분리를 진행했어요.
  • 로그인 실패 시 유저에게 더 친숙한 문장이 표시되도록 WableError의 카카오, 애플 로그인 관련 case의 네이밍과 description을 수정했어요.

💻 주요 코드 설명

UserProfileUseCase 메서드 수정

  • 기존 UserProfileUseCase에서는 profile 정보를 받아오는 메서드, profile 정보를 업데이트하는 메서드만 구현되어 있었습니다.
  • Presentation 레이어에서 유저의 profile 정보를 업데이트하기 위해서는 profile 프로퍼티를 필요로 하는데, 이를 가져오기 위해서는 같은 useCase 내에 있는 정보 불러오기 execute 메서드를 실행 후, 해당 정보를 가지고 정보 업데이트 execute 메서드를 연속적으로 실행해야 해 불편하고 비효율적인 코드가 구현되었습니다.
  • 따라서 메서드명을 각각 updateProfile, fetchProfile로 변경하고 updateProfile 내에서는 자체적으로 레포지토리에서 유저 프로필을 받아오도록 구현해 Presentation 레이어에서 불필요한 작업을 실행하지 않아도 되도록 리팩토링을 진행했습니다.
 func updateProfileWithUserID(
        userID: Int,
        isPushAlarmAllowed: Bool? = nil,
        isAlarmAllowed: Bool? = nil,
        image: UIImage? = nil,
        defaultProfileType: String? = nil
    ) -> AnyPublisher<Void, WableError> {
        let fetchProfile = repository.fetchUserProfile(memberID: userID)
        let updateProfile = { [weak self] (profile: UserProfile) -> AnyPublisher<Void, WableError> in
            guard let self = self else { return Fail(error: WableError.unknownError).eraseToAnyPublisher() }

            return self.execute(
                profile: profile,
                isPushAlarmAllowed: isPushAlarmAllowed,
                isAlarmAllowed: isAlarmAllowed,
                image: image,
                defaultProfileType: defaultProfileType
            )
        }

        return fetchProfile.flatMap(updateProfile).eraseToAnyPublisher()
    }

👀 기타 더 이야기해볼 점

  • 해당 PR 머지 후 계정 정보 수정해 재심사 올리겠습니다 ~!

🔗 연결된 이슈

Summary by CodeRabbit

  • New Features

    • Added explicit error handling for login failures, now displaying user-friendly error messages via modal toasts during login.
  • Bug Fixes

    • Improved error messages for Kakao and Apple login failures to provide clearer feedback to users.
  • Refactor

    • Streamlined login and profile update flows for better maintainability and code clarity.
    • Updated method names in the profile management features for improved semantic clarity.
    • Reduced redundant instantiations of repositories and storage components across multiple screens.

@youz2me youz2me requested a review from JinUng41 June 30, 2025 13:49
@youz2me youz2me self-assigned this Jun 30, 2025
@youz2me youz2me added 🛠️ fix 기능적 버그나 오류 해결 시 사용 ♻️ refactor 기존 코드를 리팩토링하거나 수정하는 등 사용 (생산적인 경우) labels Jun 30, 2025
@youz2me youz2me added the 🦉 유진 🛌🛌🛌🛌🛌🛌🛌🛌🛌🛌 label Jun 30, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jun 30, 2025

Walkthrough

This update refactors error handling and dependency injection in the login and profile flows. It introduces a dedicated error publisher in the login view model, allowing the login view controller to present a toast when login errors occur. Use case and repository instantiations are streamlined, and method names are updated for clarity.

Changes

Files/Paths Change Summary
Wable-iOS/App/SceneDelegate.swift, Wable-iOS/Presentation/Profile/My/View/MyProfileViewController.swift, Wable-iOS/Presentation/Profile/Withdrawal/Guide/View/WithdrawalGuideViewController.swift Refactored use case and repository instantiation for clarity and reduced redundancy.
Wable-iOS/Domain/Error/WableError.swift, Wable-iOS/Infra/Auth/AppleAuthProvider.swift, Wable-iOS/Infra/Auth/KakaoAuthProvider.swift Renamed enum cases and updated error messages for Kakao and Apple login failures.
Wable-iOS/Domain/UseCase/Onboarding/UserProfileUseCase.swift, Wable-iOS/Presentation/Profile/Edit/ProfileEditViewController.swift, Wable-iOS/Presentation/Onboarding/ViewController/AgreementViewController.swift Renamed methods for updating and fetching user profiles; added a new method for updating profiles by user ID.
Wable-iOS/Domain/UseCase/Onboarding/UpdateFCMTokenUseCase.swift Refactored guard statement for FCM token check to a single line.
Wable-iOS/Infra/Local/UserDefaultsStorage.swift Provided default values for JSON encoder and decoder in the initializer.
Wable-iOS/Presentation/Login/LoginViewModel.swift Refactored login flow: modularized logic, added error publisher, and improved error handling with helper methods.
Wable-iOS/Presentation/Login/LoginViewController.swift Subscribed to the new error publisher and presented a toast on login error. Refactored event tracking condition.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LoginViewController
    participant LoginViewModel

    User->>LoginViewController: Triggers login (Kakao/Apple)
    LoginViewController->>LoginViewModel: Input event
    LoginViewModel->>LoginViewModel: fetchUserAuth(platform)
    alt Auth error
        LoginViewModel->>LoginViewModel: Send error to loginErrorSubject
        LoginViewModel-->>LoginViewController: Output.error emits error
        LoginViewController->>LoginViewController: Present toast with error message
    else Auth success
        LoginViewModel->>LoginViewModel: updateFCMToken
        LoginViewModel->>LoginViewModel: updateUserProfile
        LoginViewModel-->>LoginViewController: Output.success
    end
Loading

Assessment against linked issues

Objective Addressed Explanation
로그인 중 에러 발생 시 토스트 추가 (#252)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Refactoring of use case/repository instantiation in profile and withdrawal view controllers (Wable-iOS/Presentation/Profile/My/View/MyProfileViewController.swift, Wable-iOS/Presentation/Profile/Withdrawal/Guide/View/WithdrawalGuideViewController.swift) These changes improve dependency injection clarity but are not directly related to login error toast.
Renaming and addition of methods in UserProfileUseCase (Wable-iOS/Domain/UseCase/Onboarding/UserProfileUseCase.swift) Method renaming and new method addition are not required for login error toast functionality.
Refactoring guard statement in UpdateFCMTokenUseCase (Wable-iOS/Domain/UseCase/Onboarding/UpdateFCMTokenUseCase.swift) This is a code style change and unrelated to login error toast.
Default parameter addition in UserDefaultsStorage initializer (Wable-iOS/Infra/Local/UserDefaultsStorage.swift) Simplifies initialization but is not required for the login error toast feature.
Renaming error enums and messages (Wable-iOS/Domain/Error/WableError.swift, Wable-iOS/Infra/Auth/AppleAuthProvider.swift, Wable-iOS/Infra/Auth/KakaoAuthProvider.swift) Error message changes are not strictly required for the toast implementation.

Suggested labels

✨ feat, 🍻 진웅

Suggested reviewers

  • JinUng41

Poem

In the warren of code, a toast now appears,
For login mishaps, to soothe user fears.
With errors now caught and messages shown,
The login flow’s smoother, as everybun’s known.
🐰✨

So hop with delight, for bugs take their flight—
The toast brings some comfort, and all is made right!


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 43aabc5 and a663264.

📒 Files selected for processing (13)
  • Wable-iOS/App/SceneDelegate.swift (2 hunks)
  • Wable-iOS/Domain/Error/WableError.swift (1 hunks)
  • Wable-iOS/Domain/UseCase/Onboarding/UpdateFCMTokenUseCase.swift (1 hunks)
  • Wable-iOS/Domain/UseCase/Onboarding/UserProfileUseCase.swift (2 hunks)
  • Wable-iOS/Infra/Auth/AppleAuthProvider.swift (1 hunks)
  • Wable-iOS/Infra/Auth/KakaoAuthProvider.swift (1 hunks)
  • Wable-iOS/Infra/Local/UserDefaultsStorage.swift (1 hunks)
  • Wable-iOS/Presentation/Login/LoginViewController.swift (1 hunks)
  • Wable-iOS/Presentation/Login/LoginViewModel.swift (1 hunks)
  • Wable-iOS/Presentation/Onboarding/ViewController/AgreementViewController.swift (1 hunks)
  • Wable-iOS/Presentation/Profile/Edit/ProfileEditViewController.swift (3 hunks)
  • Wable-iOS/Presentation/Profile/My/View/MyProfileViewController.swift (1 hunks)
  • Wable-iOS/Presentation/Profile/Withdrawal/Guide/View/WithdrawalGuideViewController.swift (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
Wable-iOS/Presentation/Onboarding/ViewController/AgreementViewController.swift (1)
Wable-iOS/Domain/UseCase/Onboarding/UserProfileUseCase.swift (1)
  • updateProfile (21-36)
Wable-iOS/Domain/UseCase/Onboarding/UpdateFCMTokenUseCase.swift (1)
Wable-iOS/Data/RepositoryImpl/ProfileRepositoryImpl.swift (1)
  • fetchFCMToken (44-50)
Wable-iOS/Presentation/Login/LoginViewController.swift (2)
Wable-iOS/Core/Amplitude/AmplitudeManager.swift (1)
  • trackEvent (21-23)
Wable-iOS/Core/Combine+/Publisher+.swift (1)
  • withUnretained (34-40)
Wable-iOS/Presentation/Profile/Edit/ProfileEditViewController.swift (1)
Wable-iOS/Domain/UseCase/Onboarding/UserProfileUseCase.swift (2)
  • updateProfile (21-36)
  • fetchProfile (38-40)
🔇 Additional comments (27)
Wable-iOS/Infra/Local/UserDefaultsStorage.swift (1)

16-20: LGTM! Good improvement to the initializer.

Adding default values for jsonEncoder and jsonDecoder parameters simplifies usage while maintaining flexibility. This reduces boilerplate code when standard JSON encoding/decoding is sufficient, and maintains backward compatibility for existing code.

Wable-iOS/Presentation/Onboarding/ViewController/AgreementViewController.swift (1)

157-157: LGTM! Method call updated correctly.

The method call has been properly updated from execute to updateProfile to align with the refactored UserProfileUseCase. The parameters and functionality remain unchanged.

Wable-iOS/Infra/Auth/KakaoAuthProvider.swift (1)

44-44: LGTM! Improved error case naming.

The error cases have been updated from .kakaoUnauthorizedUser to .failedToKakaoLogin, which provides clearer and more descriptive error messaging. This aligns with the PR's goal of making error messages more user-friendly.

Also applies to: 49-49

Wable-iOS/Infra/Auth/AppleAuthProvider.swift (1)

60-60: LGTM! Consistent error case naming.

The error case has been updated from .failedToValidateAppleLogin to .failedToAppleLogin, which provides more concise and consistent naming with other login providers. This improves error messaging clarity across the authentication flow.

Wable-iOS/Domain/UseCase/Onboarding/UpdateFCMTokenUseCase.swift (1)

23-23: LGTM! Good refactoring for conciseness.

The guard statement has been effectively condensed into a single-line return, making the code more concise while preserving the same functional behavior. This is a clean refactoring that maintains the error handling semantics.

Wable-iOS/Presentation/Login/LoginViewController.swift (2)

159-159: LGTM: Good code style improvement.

The refactoring simplifies the conditional check while preserving the exact same logic, improving readability.


164-176: LGTM: Well-implemented error toast notification.

The error handling subscription correctly implements the PR objective of showing toast notifications when login errors occur. The implementation follows good patterns:

  • Proper threading with receive(on: DispatchQueue.main)
  • Memory-safe with withUnretained(self)
  • Consistent UI presentation using WableSheetViewController
  • Proper lifecycle management in cancelBag
Wable-iOS/App/SceneDelegate.swift (2)

23-23: LGTM: Good use of simplified initializer.

The simplified UserDefaultsStorage() initialization leverages the refactored initializer with default parameters, reducing boilerplate while maintaining functionality.


63-76: LGTM: Excellent dependency injection refactoring.

Extracting use case instantiations into local constants significantly improves code readability and maintainability. This refactoring:

  • Makes dependencies explicit and easy to identify
  • Reduces nesting in constructor calls
  • Follows dependency injection best practices
  • Improves testability
Wable-iOS/Presentation/Profile/Edit/ProfileEditViewController.swift (2)

119-119: LGTM: Better semantic clarity with method renaming.

The change from execute to updateProfile improves code readability by making the method's intent more explicit. This aligns with the UserProfileUseCase refactoring mentioned in the PR objectives.

Also applies to: 172-172


293-293: LGTM: Improved method naming for clarity.

The rename from execute(userID:) to fetchProfile(userID:) makes the method's purpose immediately clear, improving code self-documentation and maintainability.

Wable-iOS/Domain/Error/WableError.swift (1)

37-38: LGTM: Improved error naming and user-friendly messages.

The error case renaming and message updates provide several benefits:

  • More descriptive and consistent case names (failedToKakaoLogin, failedToAppleLogin)
  • User-friendly Korean error messages that clearly explain the issue
  • Standardized error format across social login providers
  • Better alignment with the toast notification implementation in LoginViewController
Wable-iOS/Presentation/Profile/My/View/MyProfileViewController.swift (1)

468-484: LGTM: Consistent dependency injection improvement.

The refactoring follows the same excellent pattern seen in SceneDelegate:

  • Simplified UserDefaultsStorage initialization using default parameters
  • Extracted use case instantiations for better readability
  • Consistent dependency injection patterns across the codebase
  • Improved maintainability while preserving functionality
Wable-iOS/Presentation/Profile/Withdrawal/Guide/View/WithdrawalGuideViewController.swift (2)

102-116: LGTM! Clean dependency injection refactoring.

The refactoring improves code organization by extracting use case initializations into local constants and sharing a single UserSessionRepositoryImpl instance. This reduces duplication and makes the dependency injection more readable and maintainable.

The change aligns well with the updated UserDefaultsStorage default parameters mentioned in the AI summary.


102-116: LGTM! Clean dependency injection refactoring.

The extraction of use case instantiations into local constants significantly improves code readability. The shared UserSessionRepositoryImpl instance across multiple use cases is a good approach for consistency and reduces object creation overhead.

Wable-iOS/Domain/UseCase/Onboarding/UserProfileUseCase.swift (5)

21-40: LGTM! Method renamings improve API clarity.

The method renamings from execute to updateProfile and fetchProfile make the API more descriptive and self-documenting. This enhances code readability and aligns with the refactoring mentioned in the PR objectives.


42-63: Well-implemented combined operation with proper error handling.

The new updateProfileWithUserID method effectively combines fetch and update operations, simplifying the interface for the presentation layer. The implementation correctly:

  • Uses weak self capture to prevent retain cycles
  • Handles the case when self becomes nil by returning an appropriate error
  • Chains operations using flatMap for proper error propagation
  • Maintains the same error handling contract as individual methods

This addresses the PR objective of removing the need for multiple calls from the presentation layer.


21-36: Excellent method renaming for API clarity.

Renaming execute to updateProfile makes the method's purpose immediately clear and improves the overall API design.


38-40: Good method renaming for consistency.

The rename from execute(userID:) to fetchProfile(userID:) maintains consistency with the other method renaming and clearly indicates the method's functionality.


42-63: Well-implemented convenience method that simplifies the presentation layer.

The updateProfileWithUserID method effectively combines fetch and update operations, reducing complexity for callers. The implementation correctly:

  • Uses weak self capture to prevent retain cycles
  • Handles potential deallocation with proper error return
  • Chains operations using flatMap for proper error propagation
  • Reuses existing methods for consistency

This is a great example of providing a higher-level API that encapsulates common usage patterns.

Wable-iOS/Presentation/Login/LoginViewModel.swift (7)

17-36: LGTM! Clean property reordering and initialization.

The property reordering and corresponding initializer updates improve code organization. The addition of loginErrorSubject enables centralized error handling, which aligns with the PR objective of implementing toast notifications for login errors.


46-72: Excellent refactoring with improved error handling.

The refactored transform method is much cleaner and more maintainable:

  • Simplified main reactive chain by extracting complex operations to helper methods
  • Added dedicated error publisher for better error propagation
  • Maintained proper reactive programming patterns

The new Output.error publisher enables the presentation layer to handle login errors appropriately, supporting the toast notification feature mentioned in the PR objectives.


78-113: Well-structured helper methods with consistent error handling.

The extracted helper methods demonstrate good separation of concerns:

  • fetchUserAuth: Properly forwards errors to loginErrorSubject and prevents stream termination with Empty publisher
  • updateFCMToken: Consistent error handling pattern with graceful fallback
  • updateUserProfile: Correctly uses Task for async notification permission check

The error handling pattern is consistent across all methods, ensuring errors are properly communicated to the presentation layer while maintaining reactive stream integrity.


17-20: Property reordering for improved readability.

Moving userProfileUseCase before updateFCMTokenUseCase improves logical grouping of related dependencies.


46-46: Excellent addition of explicit error handling.

Adding the error publisher to the Output struct enables the presentation layer to handle login errors appropriately, which is a significant improvement over silent failures.


51-66: Outstanding refactoring that improves maintainability.

The simplified transform method is much more readable and maintainable. Extracting the complex login flow into helper methods while maintaining proper error propagation is excellent architecture.


78-113: Excellent separation of concerns with proper error handling.

The helper methods demonstrate several best practices:

  1. fetchUserAuth: Properly handles errors by forwarding to loginErrorSubject and prevents stream termination using Empty publisher
  2. updateFCMToken: Uses .just(()) to continue the stream after error handling
  3. updateUserProfile: Correctly handles async notification authorization check within Task scope

The error handling strategy ensures that individual operation failures don't terminate the entire reactive stream while still propagating errors to the presentation layer.

✨ Finishing Touches
  • 📝 Generate Docstrings

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.
    • @coderabbitai modularize this function.
  • 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.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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 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 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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
Collaborator

@JinUng41 JinUng41 left a comment

Choose a reason for hiding this comment

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

고생하셨습니다! 👍🏼

@github-project-automation github-project-automation bot moved this to In Review in Wable-iOS Jun 30, 2025
@youz2me youz2me changed the title [Feat] 로그인 에러 시 토스트 구현, LoginViewModel 메서드 분리 및 코드 리팩토링 [Feat] 로그인 에러 토스트 구현, LoginViewModel 메서드 분리 및 코드 리팩토링 Jun 30, 2025
@youz2me youz2me merged commit 048f3c2 into develop Jun 30, 2025
1 check was pending
@github-project-automation github-project-automation bot moved this from In Review to Done in Wable-iOS Jun 30, 2025
@youz2me youz2me deleted the fix/#252-login-error branch June 30, 2025 13:52
youz2me added a commit that referenced this pull request Oct 26, 2025
[Feat] 로그인 에러 토스트 구현, LoginViewModel 메서드 분리 및 코드 리팩토링
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🛠️ fix 기능적 버그나 오류 해결 시 사용 ♻️ refactor 기존 코드를 리팩토링하거나 수정하는 등 사용 (생산적인 경우) 🦉 유진 🛌🛌🛌🛌🛌🛌🛌🛌🛌🛌

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Feat] 로그인 중 에러 발생 시 토스트 구현

3 participants