diff --git a/.gitignore b/.gitignore index e25c661..d4fa430 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ ### Configuration ### Configuration/ +*.xcconfig ### Firebase ### GoogleService-Info*.plist diff --git a/Core/AppDI/AppDI.xcodeproj/project.pbxproj b/Core/AppDI/AppDI.xcodeproj/project.pbxproj index c94f714..2093893 100644 --- a/Core/AppDI/AppDI.xcodeproj/project.pbxproj +++ b/Core/AppDI/AppDI.xcodeproj/project.pbxproj @@ -277,7 +277,7 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_NSHumanReadableCopyright = ""; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 18.4; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; LD_RUNPATH_SEARCH_PATHS = ( "@executable_path/Frameworks", "@loader_path/Frameworks", @@ -286,7 +286,7 @@ "@executable_path/../Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 15.4; + MACOSX_DEPLOYMENT_TARGET = 14.0; MARKETING_VERSION = 1.0; MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; @@ -300,7 +300,7 @@ SWIFT_INSTALL_OBJC_HEADER = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; - XROS_DEPLOYMENT_TARGET = 2.4; + XROS_DEPLOYMENT_TARGET = 2.0; }; name = Debug; }; @@ -321,7 +321,7 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_NSHumanReadableCopyright = ""; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 18.4; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; LD_RUNPATH_SEARCH_PATHS = ( "@executable_path/Frameworks", "@loader_path/Frameworks", @@ -330,7 +330,7 @@ "@executable_path/../Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 15.4; + MACOSX_DEPLOYMENT_TARGET = 14.0; MARKETING_VERSION = 1.0; MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; @@ -344,7 +344,7 @@ SWIFT_INSTALL_OBJC_HEADER = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; - XROS_DEPLOYMENT_TARGET = 2.4; + XROS_DEPLOYMENT_TARGET = 2.0; }; name = Release; }; diff --git a/Core/NetworkKit/Interface/APIEndpoint.swift b/Core/NetworkKit/Interface/APIEndpoint.swift new file mode 100644 index 0000000..bc64a8d --- /dev/null +++ b/Core/NetworkKit/Interface/APIEndpoint.swift @@ -0,0 +1,16 @@ +// +// APIEndpoint.swift +// NetworkKit +// +// Created by 이정동 on 7/7/25. +// + +import Foundation + +public protocol APIEndpoint { + var baseURL: URL { get } + var path: String { get } + var method: HTTPMethod { get } + var task: HTTPTask { get } + var headers: [String: String]? { get } +} diff --git a/Core/NetworkKit/Interface/APIs/AppleAuthAPI.swift b/Core/NetworkKit/Interface/APIs/AppleAuthAPI.swift new file mode 100644 index 0000000..1a4e8df --- /dev/null +++ b/Core/NetworkKit/Interface/APIs/AppleAuthAPI.swift @@ -0,0 +1,54 @@ +// +// AppleAuthAPI.swift +// NetworkKitInterface +// +// Created by 이정동 on 7/15/25. +// + +import Foundation + +public enum AppleAuthAPI { + case refreshToken(code: String) + case revokeToken(token: String) +} + +extension AppleAuthAPI: APIEndpoint { + public var baseURL: URL { + switch self { + case .refreshToken: + URL(string: NetworkConfig.refreshTokenBaseURL)! + case .revokeToken: + URL(string: NetworkConfig.revokeTokenBaseURL)! + } + } + + public var path: String { + switch self { + case .refreshToken: + "/getRefreshToken" + case .revokeToken: + "/revokeToken" + } + } + + public var method: HTTPMethod { .get } + + public var task: HTTPTask { + switch self { + case .refreshToken(let code): + .requestQueryParameters(parameters: [ + "code": code + ]) + case .revokeToken(let token): + .requestQueryParameters(parameters: [ + "refresh_token": token + ]) + } + } + + public var headers: [String : String]? { + [ + "accept": "application/json" + ] + } +} diff --git a/Core/NetworkKit/Interface/Config/NetworkConfig.swift b/Core/NetworkKit/Interface/Config/NetworkConfig.swift new file mode 100644 index 0000000..d085fc7 --- /dev/null +++ b/Core/NetworkKit/Interface/Config/NetworkConfig.swift @@ -0,0 +1,18 @@ +// +// NetworkConfig.swift +// NetworkKitInterface +// +// Created by 이정동 on 7/16/25. +// + +import Foundation + +struct NetworkConfig { + private static let bundle: Bundle? = { + let identifier = "kr.co.ios.swift.apple.NetworkKitInterface" + return .init(identifier: identifier) + }() + + static let refreshTokenBaseURL = bundle?.infoDictionary?["GetRefreshTokenURL"] as? String ?? "" + static let revokeTokenBaseURL = bundle?.infoDictionary?["RevokeTokenURL"] as? String ?? "" +} diff --git a/Core/NetworkKit/Interface/HTTPMethod.swift b/Core/NetworkKit/Interface/HTTPMethod.swift new file mode 100644 index 0000000..e21791f --- /dev/null +++ b/Core/NetworkKit/Interface/HTTPMethod.swift @@ -0,0 +1,12 @@ +// +// HTTPMethod.swift +// NetworkKit +// +// Created by 이정동 on 7/7/25. +// + +import Foundation + +public enum HTTPMethod: String { + case get = "GET" +} diff --git a/Core/NetworkKit/Interface/HTTPTask.swift b/Core/NetworkKit/Interface/HTTPTask.swift new file mode 100644 index 0000000..0633216 --- /dev/null +++ b/Core/NetworkKit/Interface/HTTPTask.swift @@ -0,0 +1,13 @@ +// +// HTTPTask.swift +// NetworkKitInterface +// +// Created by 이정동 on 7/15/25. +// + +import Foundation + +public enum HTTPTask { + case requestPlain + case requestQueryParameters(parameters: [String: Any]) +} diff --git a/Core/NetworkKit/Interface/NetworkError.swift b/Core/NetworkKit/Interface/NetworkError.swift new file mode 100644 index 0000000..7002e4b --- /dev/null +++ b/Core/NetworkKit/Interface/NetworkError.swift @@ -0,0 +1,15 @@ +// +// NetworkError.swift +// NetworkKitInterface +// +// Created by 이정동 on 7/7/25. +// + +import Foundation + +public enum NetworkError: Error { + case invalidURL + case httpStatusError(Int) + case urlSessionError(Error) + case stringDecodingError +} diff --git a/Core/NetworkKit/Interface/NetworkProvider.swift b/Core/NetworkKit/Interface/NetworkProvider.swift new file mode 100644 index 0000000..a0abbd9 --- /dev/null +++ b/Core/NetworkKit/Interface/NetworkProvider.swift @@ -0,0 +1,20 @@ +// +// NetworkProvider.swift +// NetworkKitInterface +// +// Created by 이정동 on 7/7/25. +// + +import Foundation + +public protocol NetworkProvider { + func request( + endpoint: APIEndpoint, + type: T.Type + ) async throws -> T + + func requestString( + endpoint: APIEndpoint, + encoding: String.Encoding + ) async throws -> String +} diff --git a/Core/NetworkKit/NetworkKit.xcodeproj/project.pbxproj b/Core/NetworkKit/NetworkKit.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e824ecc --- /dev/null +++ b/Core/NetworkKit/NetworkKit.xcodeproj/project.pbxproj @@ -0,0 +1,610 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXBuildFile section */ + 574F04DA2E1BB19900997207 /* NetworkKitInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 574F04CD2E1BB17600997207 /* NetworkKitInterface.framework */; }; + 574F04DB2E1BB19900997207 /* NetworkKitInterface.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 574F04CD2E1BB17600997207 /* NetworkKitInterface.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 574F04DC2E1BB19900997207 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 574F04AF2E1BB15800997207 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 574F04CC2E1BB17600997207; + remoteInfo = NetworkKitInterface; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 574F04DE2E1BB19900997207 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 574F04DB2E1BB19900997207 /* NetworkKitInterface.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 574F04B82E1BB15800997207 /* NetworkKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NetworkKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 574F04CD2E1BB17600997207 /* NetworkKitInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NetworkKitInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 57E222172E2794170095BD84 /* Exceptions for "Resources" folder in "NetworkKit" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Config.xcconfig, + Info.plist, + ); + target = 574F04B72E1BB15800997207 /* NetworkKit */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 574F04BA2E1BB15800997207 /* Sources */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = Sources; + sourceTree = ""; + }; + 574F04CE2E1BB17600997207 /* Interface */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = Interface; + sourceTree = ""; + }; + 57E2220C2E278EB70095BD84 /* Resources */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + 57E222172E2794170095BD84 /* Exceptions for "Resources" folder in "NetworkKit" target */, + ); + path = Resources; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 574F04B52E1BB15800997207 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 574F04DA2E1BB19900997207 /* NetworkKitInterface.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 574F04CA2E1BB17600997207 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 574F04AE2E1BB15800997207 = { + isa = PBXGroup; + children = ( + 57E2220C2E278EB70095BD84 /* Resources */, + 574F04BA2E1BB15800997207 /* Sources */, + 574F04CE2E1BB17600997207 /* Interface */, + 574F04D42E1BB18000997207 /* Frameworks */, + 574F04B92E1BB15800997207 /* Products */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + }; + 574F04B92E1BB15800997207 /* Products */ = { + isa = PBXGroup; + children = ( + 574F04B82E1BB15800997207 /* NetworkKit.framework */, + 574F04CD2E1BB17600997207 /* NetworkKitInterface.framework */, + ); + name = Products; + sourceTree = ""; + }; + 574F04D42E1BB18000997207 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 574F04B32E1BB15800997207 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 574F04C82E1BB17600997207 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 574F04B72E1BB15800997207 /* NetworkKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 574F04BF2E1BB15800997207 /* Build configuration list for PBXNativeTarget "NetworkKit" */; + buildPhases = ( + 574F04B32E1BB15800997207 /* Headers */, + 574F04B42E1BB15800997207 /* Sources */, + 574F04B52E1BB15800997207 /* Frameworks */, + 574F04B62E1BB15800997207 /* Resources */, + 574F04DE2E1BB19900997207 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 574F04DD2E1BB19900997207 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 574F04BA2E1BB15800997207 /* Sources */, + 57E2220C2E278EB70095BD84 /* Resources */, + ); + name = NetworkKit; + packageProductDependencies = ( + ); + productName = NetworkKit; + productReference = 574F04B82E1BB15800997207 /* NetworkKit.framework */; + productType = "com.apple.product-type.framework"; + }; + 574F04CC2E1BB17600997207 /* NetworkKitInterface */ = { + isa = PBXNativeTarget; + buildConfigurationList = 574F04D12E1BB17600997207 /* Build configuration list for PBXNativeTarget "NetworkKitInterface" */; + buildPhases = ( + 574F04C82E1BB17600997207 /* Headers */, + 574F04C92E1BB17600997207 /* Sources */, + 574F04CA2E1BB17600997207 /* Frameworks */, + 574F04CB2E1BB17600997207 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 574F04CE2E1BB17600997207 /* Interface */, + ); + name = NetworkKitInterface; + packageProductDependencies = ( + ); + productName = NetworkKitInterface; + productReference = 574F04CD2E1BB17600997207 /* NetworkKitInterface.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 574F04AF2E1BB15800997207 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1640; + LastUpgradeCheck = 1640; + TargetAttributes = { + 574F04B72E1BB15800997207 = { + CreatedOnToolsVersion = 16.4; + LastSwiftMigration = 1640; + }; + 574F04CC2E1BB17600997207 = { + CreatedOnToolsVersion = 16.4; + }; + }; + }; + buildConfigurationList = 574F04B22E1BB15800997207 /* Build configuration list for PBXProject "NetworkKit" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 574F04AE2E1BB15800997207; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = 574F04B92E1BB15800997207 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 574F04B72E1BB15800997207 /* NetworkKit */, + 574F04CC2E1BB17600997207 /* NetworkKitInterface */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 574F04B62E1BB15800997207 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 574F04CB2E1BB17600997207 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 574F04B42E1BB15800997207 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 574F04C92E1BB17600997207 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 574F04DD2E1BB19900997207 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 574F04CC2E1BB17600997207 /* NetworkKitInterface */; + targetProxy = 574F04DC2E1BB19900997207 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 574F04BD2E1BB15800997207 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 5DFZR8RCQR; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = ""; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 574F04BE2E1BB15800997207 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 5DFZR8RCQR; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = ""; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SWIFT_COMPILATION_MODE = wholemodule; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 574F04C02E1BB15800997207 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = NO; + DEVELOPMENT_TEAM = 5DFZR8RCQR; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LD_RUNPATH_SEARCH_PATHS = ( + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = kr.co.ios.swift.apple.NetworkKit; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = auto; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + XROS_DEPLOYMENT_TARGET = 2.0; + }; + name = Debug; + }; + 574F04C12E1BB15800997207 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = NO; + DEVELOPMENT_TEAM = 5DFZR8RCQR; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LD_RUNPATH_SEARCH_PATHS = ( + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = kr.co.ios.swift.apple.NetworkKit; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = auto; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + XROS_DEPLOYMENT_TARGET = 2.0; + }; + name = Release; + }; + 574F04D22E1BB17600997207 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = 57E2220C2E278EB70095BD84 /* Resources */; + baseConfigurationReferenceRelativePath = Config.xcconfig; + buildSettings = { + ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5DFZR8RCQR; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Resources/Info.plist; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LD_RUNPATH_SEARCH_PATHS = ( + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = kr.co.ios.swift.apple.NetworkKitInterface; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = auto; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + XROS_DEPLOYMENT_TARGET = 2.0; + }; + name = Debug; + }; + 574F04D32E1BB17600997207 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = 57E2220C2E278EB70095BD84 /* Resources */; + baseConfigurationReferenceRelativePath = Config.xcconfig; + buildSettings = { + ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 5DFZR8RCQR; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = Resources/Info.plist; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LD_RUNPATH_SEARCH_PATHS = ( + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = ( + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = kr.co.ios.swift.apple.NetworkKitInterface; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = auto; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + XROS_DEPLOYMENT_TARGET = 2.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 574F04B22E1BB15800997207 /* Build configuration list for PBXProject "NetworkKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 574F04BD2E1BB15800997207 /* Debug */, + 574F04BE2E1BB15800997207 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 574F04BF2E1BB15800997207 /* Build configuration list for PBXNativeTarget "NetworkKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 574F04C02E1BB15800997207 /* Debug */, + 574F04C12E1BB15800997207 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 574F04D12E1BB17600997207 /* Build configuration list for PBXNativeTarget "NetworkKitInterface" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 574F04D22E1BB17600997207 /* Debug */, + 574F04D32E1BB17600997207 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 574F04AF2E1BB15800997207 /* Project object */; +} diff --git a/Core/NetworkKit/Resources/Info.plist b/Core/NetworkKit/Resources/Info.plist new file mode 100644 index 0000000..3a52d89 --- /dev/null +++ b/Core/NetworkKit/Resources/Info.plist @@ -0,0 +1,10 @@ + + + + + GetRefreshTokenURL + $(GET_REFRESH_TOKEN_URL) + RevokeTokenURL + $(REVOKE_TOKEN_URL) + + diff --git a/Core/NetworkKit/Sources/APIEndpoint+Ext.swift b/Core/NetworkKit/Sources/APIEndpoint+Ext.swift new file mode 100644 index 0000000..cd207bd --- /dev/null +++ b/Core/NetworkKit/Sources/APIEndpoint+Ext.swift @@ -0,0 +1,44 @@ +// +// APIEndpoint+Ext.swift +// NetworkKitInterface +// +// Created by 이정동 on 7/7/25. +// + +import Foundation + +import NetworkKitInterface + +extension APIEndpoint { + func asURLRequest() -> URLRequest? { + + /// Full URL Path 설정 + guard var urlComponents = URLComponents( + url: baseURL.appending(path: path), + resolvingAgainstBaseURL: true + ), + let url = urlComponents.url else { return nil } + + /// URLRequest 객체 생성 + var urlRequest = URLRequest(url: url) + urlRequest.httpMethod = method.rawValue + urlRequest.allHTTPHeaderFields = headers ?? urlRequest.allHTTPHeaderFields + + /// 요청 작업 별 설정 + switch self.task { + case .requestPlain: + break + case let .requestQueryParameters(parameter): + let queryItems: [URLQueryItem] = parameter.compactMap { + guard let value = $0.value as? String else { return nil } + return URLQueryItem(name: $0.key, value: value) + } + urlComponents.queryItems = urlComponents.queryItems.map { $0 + queryItems } ?? queryItems + urlRequest.url = urlComponents.url + @unknown default: + break + } + + return urlRequest + } +} diff --git a/Core/NetworkKit/Sources/NetworkProviderImpl.swift b/Core/NetworkKit/Sources/NetworkProviderImpl.swift new file mode 100644 index 0000000..6bc4f72 --- /dev/null +++ b/Core/NetworkKit/Sources/NetworkProviderImpl.swift @@ -0,0 +1,63 @@ +// +// NetworkProviderImpl.swift +// NetworkKit +// +// Created by 이정동 on 7/7/25. +// + +import Foundation + +import NetworkKitInterface + +public struct NetworkProviderImpl: NetworkProvider { + + private let session: URLSession + + public init(session: URLSession = .shared) { + self.session = session + } + + public func request(endpoint: APIEndpoint, type: T.Type) async throws -> T { + let data = try await requestData(endpoint: endpoint) + do { + let decodedData = try JSONDecoder().decode(T.self, from: data) + return decodedData + } catch { + throw NetworkError.stringDecodingError + } + } + + public func requestString( + endpoint: APIEndpoint, + encoding: String.Encoding + ) async throws -> String { + + let data = try await requestData(endpoint: endpoint) + guard let string = String(data: data, encoding: encoding) else { + throw NetworkError.stringDecodingError + } + return string + } +} + +private extension NetworkProviderImpl { + func requestData(endpoint: APIEndpoint) async throws -> Data { + guard let request = endpoint.asURLRequest() else { + throw NetworkError.invalidURL + } + + do { + let (data, response) = try await session.data(for: request) + + if let httpResponse = response as? HTTPURLResponse { + guard 200...299 ~= httpResponse.statusCode else { + throw NetworkError.httpStatusError(httpResponse.statusCode) + } + } + + return data + } catch { + throw NetworkError.urlSessionError(error) + } + } +} diff --git a/Mark-In.xcodeproj/project.pbxproj b/Mark-In.xcodeproj/project.pbxproj index 255c0e7..464daad 100644 --- a/Mark-In.xcodeproj/project.pbxproj +++ b/Mark-In.xcodeproj/project.pbxproj @@ -7,6 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 574F04E22E1BB1A300997207 /* NetworkKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 574F04C72E1BB15900997207 /* NetworkKit.framework */; }; + 574F04E32E1BB1A300997207 /* NetworkKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 574F04C72E1BB15900997207 /* NetworkKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 574F04E42E1BB1A300997207 /* NetworkKitInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 574F04E12E1BB1A300997207 /* NetworkKitInterface.framework */; }; + 574F04E52E1BB1A300997207 /* NetworkKitInterface.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 574F04E12E1BB1A300997207 /* NetworkKitInterface.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 574FFE6B2E168CD200997207 /* DesignSystem.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 574FFE6A2E168CB700997207 /* DesignSystem.framework */; }; 574FFE6C2E168CD200997207 /* DesignSystem.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 574FFE6A2E168CB700997207 /* DesignSystem.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 57588B452DD640C100DBD9A7 /* ReducerKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57588B412DD63D9700DBD9A7 /* ReducerKit.framework */; }; @@ -27,6 +31,20 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 574F04C62E1BB15900997207 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 574F04C22E1BB15800997207 /* NetworkKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 574F04B82E1BB15800997207; + remoteInfo = NetworkKit; + }; + 574F04E02E1BB1A300997207 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 574F04C22E1BB15800997207 /* NetworkKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 574F04CD2E1BB17600997207; + remoteInfo = NetworkKitInterface; + }; 574FFE692E168CB700997207 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 57AC52EF2DA4FBC900BA84BD /* DesignSystem.xcodeproj */; @@ -89,8 +107,10 @@ 57AC56A92DA5120600BA84BD /* Util.framework in Embed Frameworks */, 57664F242DEEB2A100CA8D68 /* LinkMetadataKit.framework in Embed Frameworks */, 574FFE6C2E168CD200997207 /* DesignSystem.framework in Embed Frameworks */, + 574F04E52E1BB1A300997207 /* NetworkKitInterface.framework in Embed Frameworks */, 57588CED2DD9B66C00DBD9A7 /* AppDI.framework in Embed Frameworks */, 57588B462DD640C100DBD9A7 /* ReducerKit.framework in Embed Frameworks */, + 574F04E32E1BB1A300997207 /* NetworkKit.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -98,6 +118,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 574F04C22E1BB15800997207 /* NetworkKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = NetworkKit.xcodeproj; path = NetworkKit/NetworkKit.xcodeproj; sourceTree = ""; }; 57588CE42DD9B4D500DBD9A7 /* AppDI.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AppDI.xcodeproj; path = AppDI/AppDI.xcodeproj; sourceTree = ""; }; 57606D652DD63B14005EBE3D /* ReducerKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReducerKit.xcodeproj; path = ReducerKit/ReducerKit.xcodeproj; sourceTree = ""; }; 57664F682DF03A9000CA8D68 /* Mark-In-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Mark-In-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -111,8 +132,6 @@ 57B7E0242DC3D44100D9225A /* Exceptions for "Mark-In" folder in "Mark-In" target */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( - Configuration/Debug.xcconfig, - Configuration/Release.xcconfig, Resources/Info.plist, ); target = 57BFD8C22DA4E19600648AD4 /* Mark-In */; @@ -149,7 +168,9 @@ files = ( 57AC56A82DA5120600BA84BD /* Util.framework in Frameworks */, 57588CEC2DD9B66C00DBD9A7 /* AppDI.framework in Frameworks */, + 574F04E22E1BB1A300997207 /* NetworkKit.framework in Frameworks */, 57664F232DEEB2A100CA8D68 /* LinkMetadataKit.framework in Frameworks */, + 574F04E42E1BB1A300997207 /* NetworkKitInterface.framework in Frameworks */, 57944D0C2DC52AEF00EF3D9A /* GoogleSignIn in Frameworks */, 57E1F9852DA8F9B40033F30C /* FirebaseAuth in Frameworks */, 57664F252DEEB2A100CA8D68 /* LinkMetadataKitInterface.framework in Frameworks */, @@ -164,6 +185,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 574F04C32E1BB15800997207 /* Products */ = { + isa = PBXGroup; + children = ( + 574F04C72E1BB15900997207 /* NetworkKit.framework */, + 574F04E12E1BB1A300997207 /* NetworkKitInterface.framework */, + ); + name = Products; + sourceTree = ""; + }; 574FFE662E168CB700997207 /* Products */ = { isa = PBXGroup; children = ( @@ -207,6 +237,7 @@ 57AC565F2DA511A900BA84BD /* Core */ = { isa = PBXGroup; children = ( + 574F04C22E1BB15800997207 /* NetworkKit.xcodeproj */, 57588CE42DD9B4D500DBD9A7 /* AppDI.xcodeproj */, 57AC53232DA4FC4900BA84BD /* LinkMetadataKit.xcodeproj */, 57606D652DD63B14005EBE3D /* ReducerKit.xcodeproj */, @@ -356,6 +387,10 @@ ProductGroup = 57985FAB2DDDC2CD00A383F2 /* Products */; ProjectRef = 57AC53232DA4FC4900BA84BD /* LinkMetadataKit.xcodeproj */; }, + { + ProductGroup = 574F04C32E1BB15800997207 /* Products */; + ProjectRef = 574F04C22E1BB15800997207 /* NetworkKit.xcodeproj */; + }, { ProductGroup = 57588A542DD63B5900DBD9A7 /* Products */; ProjectRef = 57606D652DD63B14005EBE3D /* ReducerKit.xcodeproj */; @@ -374,6 +409,20 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ + 574F04C72E1BB15900997207 /* NetworkKit.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = NetworkKit.framework; + remoteRef = 574F04C62E1BB15900997207 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 574F04E12E1BB1A300997207 /* NetworkKitInterface.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = NetworkKitInterface.framework; + remoteRef = 574F04E02E1BB1A300997207 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 574FFE6A2E168CB700997207 /* DesignSystem.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; @@ -463,6 +512,8 @@ /* Begin XCBuildConfiguration section */ 57664F6F2DF03A9000CA8D68 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = 57BFD8C52DA4E19600648AD4 /* Mark-In */; + baseConfigurationReferenceRelativePath = Configuration/Debug.xcconfig; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -486,6 +537,8 @@ }; 57664F702DF03A9000CA8D68 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = 57BFD8C52DA4E19600648AD4 /* Mark-In */; + baseConfigurationReferenceRelativePath = Configuration/Release.xcconfig; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -631,6 +684,8 @@ }; 57BFD8D02DA4E19700648AD4 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = 57BFD8C52DA4E19600648AD4 /* Mark-In */; + baseConfigurationReferenceRelativePath = Configuration/Debug.xcconfig; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-Dev"; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -673,6 +728,8 @@ }; 57BFD8D12DA4E19700648AD4 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = 57BFD8C52DA4E19600648AD4 /* Mark-In */; + baseConfigurationReferenceRelativePath = Configuration/Release.xcconfig; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; diff --git a/Mark-In/Resources/Info.plist b/Mark-In/Resources/Info.plist index 9ab63ae..a4b7330 100644 --- a/Mark-In/Resources/Info.plist +++ b/Mark-In/Resources/Info.plist @@ -2,10 +2,6 @@ - RevokeTokenURL - $(REVOKE_TOKEN_URL) - GetRefreshTokenURL - $(GET_REFRESH_TOKEN_URL) GIDClientID $(GID_CLIENT) CFBundleURLTypes diff --git a/Mark-In/Sources/App/Config.swift b/Mark-In/Sources/App/Config.swift deleted file mode 100644 index 904a994..0000000 --- a/Mark-In/Sources/App/Config.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// Config.swift -// Mark-In -// -// Created by 이정동 on 5/14/25. -// - -import Foundation - -struct Config { - enum Key: String { - case getRefreshTokenURL = "GetRefreshTokenURL" - case revokeTokenURL = "RevokeTokenURL" - } - - static func value(forKey: Self.Key) -> String { - guard let value = Bundle.main.object(forInfoDictionaryKey: forKey.rawValue) as? String else { - fatalError("\(forKey.rawValue) not set") - } - return value - } -} diff --git a/Mark-In/Sources/App/DIContainer+.swift b/Mark-In/Sources/App/DIContainer+.swift index d5a40e7..1f09c2d 100644 --- a/Mark-In/Sources/App/DIContainer+.swift +++ b/Mark-In/Sources/App/DIContainer+.swift @@ -10,6 +10,8 @@ import Foundation import AppDI import LinkMetadataKit import LinkMetadataKitInterface +import NetworkKit +import NetworkKitInterface extension DIContainer { @@ -31,10 +33,12 @@ private extension DIContainer { let authUserManager: AuthUserManager = AuthUserManagerImpl( keychainStore: keychainStore ) + let networkProvider: NetworkProvider = NetworkProviderImpl() register(keychainStore) register(linkMetadataProvider) register(authUserManager) + register(networkProvider) } // MARK: - Domain - Repository @@ -68,7 +72,8 @@ private extension DIContainer { ) let signInUseCase: SignInUseCase = SignInUseCaseImpl( keychainStore: resolve(), - authUserManager: resolve() + authUserManager: resolve(), + networkProvider: resolve() ) let signOutUseCase: SignOutUseCase = SignOutUseCaseImpl( authUserManager: resolve() @@ -76,6 +81,7 @@ private extension DIContainer { let withdrawalUseCase: WithdrawalUseCase = WithdrawalUseCaseImpl( keychainStore: resolve(), authUserManager: resolve(), + networkProvider: resolve(), linkRepository: resolve(), folderRepsoitory: resolve() ) diff --git a/Mark-In/Sources/Domain/UseCases/Implements/Auth/SignInUseCaseImpl.swift b/Mark-In/Sources/Domain/UseCases/Implements/Auth/SignInUseCaseImpl.swift index e71c8ae..cdfc0bc 100644 --- a/Mark-In/Sources/Domain/UseCases/Implements/Auth/SignInUseCaseImpl.swift +++ b/Mark-In/Sources/Domain/UseCases/Implements/Auth/SignInUseCaseImpl.swift @@ -9,19 +9,23 @@ import Foundation import FirebaseAuth +import NetworkKitInterface import Util struct SignInUseCaseImpl: SignInUseCase { private let keychainStore: KeychainStore private let authUserManager: AuthUserManager + private let networkProvider: NetworkProvider init( keychainStore: KeychainStore, - authUserManager: AuthUserManager + authUserManager: AuthUserManager, + networkProvider: NetworkProvider ) { self.keychainStore = keychainStore self.authUserManager = authUserManager + self.networkProvider = networkProvider } func execute(using info: AppleSignInInfo) async throws { @@ -34,13 +38,11 @@ struct SignInUseCaseImpl: SignInUseCase { throw SignInError.missingData } - // TODO: 아래 코드들을 Core(Auth) 모듈에서 처리하도록 리팩토링 - /// 애플 서버에 Refresh Token 요청 - let urlString = "https://\(Config.value(forKey: .getRefreshTokenURL))/getRefreshToken?code=\(codeString)" - let url = URL(string: urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)! - let (data, _) = try await URLSession.shared.data(from: url) - let refreshToken = String(data: data, encoding: .utf8) ?? "" + let refreshToken = try await networkProvider.requestString( + endpoint: AppleAuthAPI.refreshToken(code: codeString), + encoding: .utf8 + ) /// Refresh Token 저장 try keychainStore.save(refreshToken, forKey: .refreshToken) diff --git a/Mark-In/Sources/Domain/UseCases/Implements/Auth/WithdrawalUseCaseImpl.swift b/Mark-In/Sources/Domain/UseCases/Implements/Auth/WithdrawalUseCaseImpl.swift index 05335a4..4e73fc7 100644 --- a/Mark-In/Sources/Domain/UseCases/Implements/Auth/WithdrawalUseCaseImpl.swift +++ b/Mark-In/Sources/Domain/UseCases/Implements/Auth/WithdrawalUseCaseImpl.swift @@ -10,10 +10,13 @@ import Foundation import FirebaseAuth import GoogleSignIn +import NetworkKitInterface + struct WithdrawalUseCaseImpl: WithdrawalUseCase { private let keychainStore: KeychainStore private let authUserManager: AuthUserManager + private let networkProvider: NetworkProvider private let linkRepository: LinkRepository private let folderRepsoitory: FolderRepository @@ -21,11 +24,13 @@ struct WithdrawalUseCaseImpl: WithdrawalUseCase { init( keychainStore: KeychainStore, authUserManager: AuthUserManager, + networkProvider: NetworkProvider, linkRepository: LinkRepository, folderRepsoitory: FolderRepository ) { self.keychainStore = keychainStore self.authUserManager = authUserManager + self.networkProvider = networkProvider self.linkRepository = linkRepository self.folderRepsoitory = folderRepsoitory } @@ -74,11 +79,11 @@ private extension WithdrawalUseCaseImpl { let token: String? = try? keychainStore.load(forKey: .refreshToken) guard let token else { return } - let url = URL(string: "https://\(Config.value(forKey: .revokeTokenURL))/revokeToken?refresh_token=\(token)" - .addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)! - - _ = try await URLSession.shared.data(from: url) - + _ = try await networkProvider.requestString( + endpoint: AppleAuthAPI.revokeToken(token: token), + encoding: .utf8 + ) + try keychainStore.delete(forKey: .refreshToken) }