Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//
// Error+.swift
// DataLayerError.swift
// DevLog
//
// Created by 최윤진 on 11/29/25.
// Created by opfic on 3/11/26.
//

import Foundation
Expand All @@ -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)

Expand Down
52 changes: 52 additions & 0 deletions DevLog/Infra/Common/InfraLayerError.swift
Original file line number Diff line number Diff line change
@@ -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
}
}
Comment on lines +38 to +51
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.

medium

isSocialLoginCancelled 프로퍼티의 가독성을 높이기 위해 switch 문을 사용하는 것을 제안합니다. 여러 if let을 사용하는 현재 구현도 올바르게 동작하지만, switch를 사용하면 다양한 오류 유형을 더 명확하게 구분하고 코드를 더 깔끔하게 만들 수 있습니다.

extension Error {
    var isSocialLoginCancelled: Bool {
        switch self {
        case let authError as ASAuthorizationError:
            return authError.code == .canceled
        case let webAuthError as ASWebAuthenticationSessionError:
            return webAuthError.code == .canceledLogin
        default:
            let nsError = self as NSError
            return nsError.domain == kGIDSignInErrorDomain && nsError.code == GIDSignInError.canceled.rawValue
        }
    }
}

이렇게 변경하면 각 소셜 로그인 서비스별 취소 오류를 명시적으로 처리하는 구조가 되어 향후 다른 소셜 로그인이 추가되더라도 확장하기 용이합니다.

    var isSocialLoginCancelled: Bool {
        switch self {
        case let authError as ASAuthorizationError:
            return authError.code == .canceled
        case let webAuthError as ASWebAuthenticationSessionError:
            return webAuthError.code == .canceledLogin
        default:
            let nsError = self as NSError
            return nsError.domain == kGIDSignInErrorDomain && nsError.code == GIDSignInError.canceled.rawValue
        }
    }

}
File renamed without changes.
13 changes: 0 additions & 13 deletions DevLog/Infra/Service/SocialLogin/EmailFetchError.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -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)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion DevLog/Presentation/ViewModel/LoginViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import Combine
import Foundation
import FirebaseAuth
import GoogleSignIn

@Observable
final class LoginViewModel: Store {
Expand Down Expand Up @@ -93,6 +92,7 @@ final class LoginViewModel: Store {
} catch {
send(.setLogined(false))
sessionUseCase.execute(false)
if error.isSocialLoginCancelled { return }
send(.setAlert(true))
}
}
Expand Down