diff --git a/DevLog/Data/Common/Error+.swift b/DevLog/Data/Common/DataLayerError.swift similarity index 63% rename from DevLog/Data/Common/Error+.swift rename to DevLog/Data/Common/DataLayerError.swift index cda9fc17..c12d40d0 100644 --- a/DevLog/Data/Common/Error+.swift +++ b/DevLog/Data/Common/DataLayerError.swift @@ -1,8 +1,8 @@ // -// Error+.swift +// DataLayerError.swift // DevLog // -// Created by 최윤진 on 11/29/25. +// Created by opfic on 3/11/26. // import Foundation @@ -13,21 +13,6 @@ enum AuthError: Error { case unsupportedProvider } -enum FirestoreError: Error, LocalizedError { - case dataNotFound(_ key: String) - - var errorDescription: String? { - switch self { - case .dataNotFound(let key): - return "\(key)가 Firestore에서 존재하지 않음" - } - } -} - -enum UIError: Error { - case notFoundTopViewController -} - enum DataError: Error { case invalidData(context: String) diff --git a/DevLog/Infra/Common/InfraLayerError.swift b/DevLog/Infra/Common/InfraLayerError.swift new file mode 100644 index 00000000..4bbd9c67 --- /dev/null +++ b/DevLog/Infra/Common/InfraLayerError.swift @@ -0,0 +1,52 @@ +// +// InfraLayerError.swift +// DevLog +// +// Created by opfic on 3/11/26. +// + +import AuthenticationServices +import Foundation +import GoogleSignIn + +enum FirestoreError: Error, LocalizedError { + case dataNotFound(_ key: String) + + var errorDescription: String? { + switch self { + case .dataNotFound(let key): + return "\(key)가 Firestore에서 존재하지 않음" + } + } +} + +enum UIError: Error { + case notFoundTopViewController +} + +enum EmailFetchError: Error, Equatable { + case emailNotFound + case emailMismatch +} + +enum SocialLoginError: Error { + case invalidOAuthState + case failedToStartWebAuthenticationSession +} + +extension Error { + var isSocialLoginCancelled: Bool { + switch self { + // Apple 로그인 취소 + case let authError as ASAuthorizationError: + return authError.code == .canceled + // Github 로그인 취소 + case let webAuthError as ASWebAuthenticationSessionError: + return webAuthError.code == .canceledLogin + default: + let nsError = self as NSError + // Google 로그인 취소 + return nsError.domain == kGIDSignInErrorDomain && nsError.code == GIDSignInError.canceled.rawValue + } + } +} diff --git a/DevLog/Infra/Util/Logger.swift b/DevLog/Infra/Common/Logger.swift similarity index 100% rename from DevLog/Infra/Util/Logger.swift rename to DevLog/Infra/Common/Logger.swift diff --git a/DevLog/Infra/Util/TopViewControllerProvider.swift b/DevLog/Infra/Common/TopViewControllerProvider.swift similarity index 100% rename from DevLog/Infra/Util/TopViewControllerProvider.swift rename to DevLog/Infra/Common/TopViewControllerProvider.swift diff --git a/DevLog/Infra/Service/SocialLogin/EmailFetchError.swift b/DevLog/Infra/Service/SocialLogin/EmailFetchError.swift deleted file mode 100644 index 5923aacc..00000000 --- a/DevLog/Infra/Service/SocialLogin/EmailFetchError.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// EmailFetchError.swift -// DevLog -// -// Created by 최윤진 on 11/2/25. -// - -import Foundation - -enum EmailFetchError: Error, Equatable { - case emailNotFound - case emailMismatch -} diff --git a/DevLog/Infra/Service/SocialLogin/GithubAuthenticationService.swift b/DevLog/Infra/Service/SocialLogin/GithubAuthenticationService.swift index 1e5d94c4..81c7a342 100644 --- a/DevLog/Infra/Service/SocialLogin/GithubAuthenticationService.swift +++ b/DevLog/Infra/Service/SocialLogin/GithubAuthenticationService.swift @@ -187,7 +187,7 @@ final class GithubAuthenticationService: NSObject, AuthenticationService { // 반환된 state 값 확인 / 받아온 값이 다르면 CSRF 공격 가능성 있음 guard let returnedState = queryItems.first(where: { $0.name == "state" })?.value, returnedState == state else { - continuation.resume(throwing: URLError(.userCancelledAuthentication)) + continuation.resume(throwing: SocialLoginError.invalidOAuthState) return } @@ -198,7 +198,7 @@ final class GithubAuthenticationService: NSObject, AuthenticationService { session.prefersEphemeralWebBrowserSession = false // 웹에서 깃헙 로그인 후 세션 유지 if !session.start() { - continuation.resume(throwing: URLError(.userCancelledAuthentication)) + continuation.resume(throwing: SocialLoginError.failedToStartWebAuthenticationSession) } } } diff --git a/DevLog/Presentation/ViewModel/LoginViewModel.swift b/DevLog/Presentation/ViewModel/LoginViewModel.swift index 7f192bda..a1fd81c8 100644 --- a/DevLog/Presentation/ViewModel/LoginViewModel.swift +++ b/DevLog/Presentation/ViewModel/LoginViewModel.swift @@ -8,7 +8,6 @@ import Combine import Foundation import FirebaseAuth -import GoogleSignIn @Observable final class LoginViewModel: Store { @@ -93,6 +92,7 @@ final class LoginViewModel: Store { } catch { send(.setLogined(false)) sessionUseCase.execute(false) + if error.isSocialLoginCancelled { return } send(.setAlert(true)) } }