From 66be1190e87f890b40c133d5cd564eed7ea5fc14 Mon Sep 17 00:00:00 2001 From: ericKwon95 Date: Sat, 7 Dec 2024 12:32:31 +0900 Subject: [PATCH 1/5] =?UTF-8?q?chore:=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - reqeust -> request --- NetworkKit/Sources/NetworkKit/Kit/APILogger.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NetworkKit/Sources/NetworkKit/Kit/APILogger.swift b/NetworkKit/Sources/NetworkKit/Kit/APILogger.swift index 0031a69..8c95975 100644 --- a/NetworkKit/Sources/NetworkKit/Kit/APILogger.swift +++ b/NetworkKit/Sources/NetworkKit/Kit/APILogger.swift @@ -6,7 +6,7 @@ struct APILogger: EventMonitor { func requestDidFinish(_ request: Request) { #if DEBUG - print("πŸš€ NETWORK Reqeust LOG") + print("πŸš€ NETWORK Request LOG") print(request.description) print( From c7f0097c0afdf1124c056806e8e4774fa91eeecb Mon Sep 17 00:00:00 2001 From: ericKwon95 Date: Sat, 7 Dec 2024 12:35:08 +0900 Subject: [PATCH 2/5] =?UTF-8?q?style:=20=EB=84=A4=ED=8A=B8=EC=9B=8C?= =?UTF-8?q?=ED=81=AC=20=EB=A1=9C=EA=B7=B8=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - μ‹€νŒ¨ μ‹œ μ—λŸ¬ localizedDescription 좜λ ₯ - 가독성 μ €ν•΄ 이슈둜 응닡 λ°μ΄ν„°λŠ” 좜λ ₯ν•˜μ§€ μ•Šλ„λ‘ λ³€κ²½ --- .../Sources/NetworkKit/Kit/APILogger.swift | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/NetworkKit/Sources/NetworkKit/Kit/APILogger.swift b/NetworkKit/Sources/NetworkKit/Kit/APILogger.swift index 8c95975..d34beef 100644 --- a/NetworkKit/Sources/NetworkKit/Kit/APILogger.swift +++ b/NetworkKit/Sources/NetworkKit/Kit/APILogger.swift @@ -22,12 +22,20 @@ struct APILogger: EventMonitor { func request(_ request: DataRequest, didParseResponse response: DataResponse) { #if DEBUG print("βœ… NETWORK Response LOG") - print( - "URL: " + (request.request?.url?.absoluteString ?? "nil") + "\n" - + "Result: " + "\(response.result)" + "\n" - + "StatusCode: " + "\(response.response?.statusCode ?? 0)" + "\n" - + "Data: \(response.data?.prettyJson ?? "nil")" - ) + switch response.result { + case let .success(data): + print( + "URL: " + (request.request?.url?.absoluteString ?? "nil") + "\n" + + "Result: " + "\(data)" + "\n" + + "StatusCode: " + "\(response.response?.statusCode ?? 0)" + ) + case let .failure(error): + print( + "URL: " + (request.request?.url?.absoluteString ?? "nil") + "\n" + + "Result: " + "\(error.localizedDescription)" + "\n" + + "StatusCode: " + "\(response.response?.statusCode ?? 0)" + ) + } #endif } } From 0df47058f1332eb3c7c342a8cda9f6f04af03473 Mon Sep 17 00:00:00 2001 From: ericKwon95 Date: Sat, 7 Dec 2024 12:36:23 +0900 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20sessionDeinitialized=20=EC=9D=B4?= =?UTF-8?q?=EC=8A=88=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - lazy var둜 μ„ μ–Έλ˜μ–΄ 있던 μ„Έμ…˜ ν”„λ‘œνΌν‹°λ₯Ό μ—¬λŸ¬ μŠ€λ ˆλ“œμ—μ„œ λ™μ‹œμ— μ΄ˆκΈ°ν™”ν•˜λ©° 문제 λ°œμƒ - μ΄ˆκΈ°ν™” κ³Όμ •μ—μ„œ ν•œ 번만 μ΄ˆκΈ°ν™”ν•˜λ„λ‘ ꡬ쑰 λ³€κ²½ν•˜μ—¬ 문제 ν•΄κ²° --- NetworkKit/Sources/NetworkKit/Kit/APIClient.swift | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift b/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift index d09389e..9c7acd7 100644 --- a/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift +++ b/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift @@ -6,20 +6,19 @@ public final class APIClient: APIProtocol, @unchecked Sendable { public static let shared = APIClient() private var tokenRefresher: TokenRefreshable? private var isConfigured = false + private let session: Session - private init() { } - - private lazy var session: Session = { + private init() { let configuration = URLSessionConfiguration.af.default configuration.waitsForConnectivity = true configuration.timeoutIntervalForRequest = 60 // seconds that a task will wait for data to arrive configuration.timeoutIntervalForResource = 300 // seconds for whole resource request to complete ,. - return Session( + self.session = Session( configuration: configuration, interceptor: tokenRefresher.map { APIInterceptor(tokenRefresher: $0) }, eventMonitors: [APILogger()] ) - }() + } public func configure(tokenRefresher: TokenRefreshable) { guard !isConfigured else { From f79930737a720ea1227a3371e017f648ba7ee297 Mon Sep 17 00:00:00 2001 From: woogi Date: Wed, 18 Dec 2024 21:25:33 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20Session=20memory=20=ED=95=A0?= =?UTF-8?q?=EB=8B=B9=20=EA=B4=80=EB=A0=A8=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit session μ΄ˆκΈ°ν™” λ¬Έμ œκ°€ μžˆμ„ μ˜ˆκ°μ€ ν•˜μ˜€μ§€λ§Œ μ΄λž˜λ„ λ˜κ² μ§€λž€ 마음으둜... ν–ˆλ˜κ²Œ λ“€ν‚΄ μΆ”κ°€ λ³΄μ™„ν•΄μ„œ μ˜¬λ¦½λ‹ˆλ‹Ή --- .../Climeet-iOS.xcodeproj/project.pbxproj | 4 ++-- .../Climeet-iOS/App/Climeet_iOSApp.swift | 5 ---- .../Data/Common/APIClient+Extension.swift | 14 +++++++++++ .../Sources/NetworkKit/Kit/APIClient.swift | 24 +++---------------- 4 files changed, 19 insertions(+), 28 deletions(-) create mode 100644 Climeet-iOS/Climeet-iOS/Data/Common/APIClient+Extension.swift diff --git a/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj b/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj index e914b17..0d9dd11 100644 --- a/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj +++ b/Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj @@ -558,7 +558,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"Climeet-iOS/Preview Content\""; - DEVELOPMENT_TEAM = 7MJ69FU8BU; + DEVELOPMENT_TEAM = L56LNTR7PZ; ENABLE_PREVIEWS = YES; ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = YES; @@ -594,7 +594,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"Climeet-iOS/Preview Content\""; - DEVELOPMENT_TEAM = 7MJ69FU8BU; + DEVELOPMENT_TEAM = L56LNTR7PZ; ENABLE_PREVIEWS = YES; ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = YES; diff --git a/Climeet-iOS/Climeet-iOS/App/Climeet_iOSApp.swift b/Climeet-iOS/Climeet-iOS/App/Climeet_iOSApp.swift index e483295..0054de5 100644 --- a/Climeet-iOS/Climeet-iOS/App/Climeet_iOSApp.swift +++ b/Climeet-iOS/Climeet-iOS/App/Climeet_iOSApp.swift @@ -17,7 +17,6 @@ struct ClimeetiOSApp: App { KeyChain.shared.refreshToken = Env.MASTER_TOKEN // ν…ŒμŠ€νŠΈ κ°’ μ„€μ • // print(KeyChain.shared.refreshToken) // κ°’ μ½μ–΄μ˜€κΈ° // KeyChain.shared.deleteRefreshToken() // λ¦¬ν”„λ ˆμ‹œ 토큰 μ΄ˆκΈ°ν™”(ν…ŒμŠ€νŠΈλ©”μ„œλ“œ) - configureAPIClient() applyGlobalNavigationTitleAttributes() } @@ -34,8 +33,4 @@ struct ClimeetiOSApp: App { // Font.climeetFontTitle4 해당함 ] } - - func configureAPIClient() { - APIClient.shared.configure(tokenRefresher: TokenRefresher()) - } } diff --git a/Climeet-iOS/Climeet-iOS/Data/Common/APIClient+Extension.swift b/Climeet-iOS/Climeet-iOS/Data/Common/APIClient+Extension.swift new file mode 100644 index 0000000..c53b319 --- /dev/null +++ b/Climeet-iOS/Climeet-iOS/Data/Common/APIClient+Extension.swift @@ -0,0 +1,14 @@ +// +// APIClient+Extension.swift +// Climeet-iOS +// +// Created by μ†‘ν˜•μš± on 12/18/24. +// + +import Foundation +import Alamofire +import NetworkKit + +extension APIClient { + static let shared: APIClient = APIClient(session: .default, tokenRefresher: TokenRefresher()) +} diff --git a/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift b/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift index 9c7acd7..e16642a 100644 --- a/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift +++ b/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift @@ -2,34 +2,16 @@ import Foundation import Alamofire public final class APIClient: APIProtocol, @unchecked Sendable { - - public static let shared = APIClient() - private var tokenRefresher: TokenRefreshable? - private var isConfigured = false private let session: Session - private init() { - let configuration = URLSessionConfiguration.af.default - configuration.waitsForConnectivity = true - configuration.timeoutIntervalForRequest = 60 // seconds that a task will wait for data to arrive - configuration.timeoutIntervalForResource = 300 // seconds for whole resource request to complete ,. + public init(session: Session, tokenRefresher: TokenRefreshable) { self.session = Session( - configuration: configuration, - interceptor: tokenRefresher.map { APIInterceptor(tokenRefresher: $0) }, + configuration: session.sessionConfiguration, + interceptor: APIInterceptor(tokenRefresher: tokenRefresher), eventMonitors: [APILogger()] ) } - public func configure(tokenRefresher: TokenRefreshable) { - guard !isConfigured else { - print("APIClientλŠ” 이미 μ΄ˆκΈ°ν™” λ˜μ—ˆμŠ΅λ‹ˆλ‹€.") - return - } - - self.tokenRefresher = tokenRefresher - self.isConfigured = true - } - public func request(_ endpoint: Endpoint, decode: T.Type) async throws -> T { do { let result = try await self.session.request(endpoint.asURLRequest()).serializingData().response From 14b9d017d7c0855860811afdd108638b9b28bde9 Mon Sep 17 00:00:00 2001 From: woogi Date: Fri, 20 Dec 2024 16:43:26 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20Login=20=EA=B4=80=EB=A0=A8=20APIClie?= =?UTF-8?q?nt=20session=20=EC=A3=BC=EC=9E=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Client/ClimberClient.swift | 2 +- .../Sources/NetworkKit/Kit/APIClient.swift | 19 +++++++++++++------ .../NetworkKit/Kit/APIInterceptor.swift | 12 ++++++++++-- .../Sources/NetworkKit/Kit/EndPoint.swift | 2 +- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Climeet-iOS/Climeet-iOS/Data/Client/ClimberClient.swift b/Climeet-iOS/Climeet-iOS/Data/Client/ClimberClient.swift index 3964678..7958426 100644 --- a/Climeet-iOS/Climeet-iOS/Data/Client/ClimberClient.swift +++ b/Climeet-iOS/Climeet-iOS/Data/Client/ClimberClient.swift @@ -76,7 +76,7 @@ extension ClimberClient: DependencyKey { }, login: { param in let endPoint = ClimberEndPoint.login(param) - return try await APIClient.shared.request(endPoint, decode: SignResponse.self) + return try await APIClient(session: .default, tokenRefresher: nil).request(endPoint, decode: SignResponse.self) } ) } diff --git a/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift b/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift index e16642a..aa75255 100644 --- a/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift +++ b/NetworkKit/Sources/NetworkKit/Kit/APIClient.swift @@ -4,12 +4,19 @@ import Alamofire public final class APIClient: APIProtocol, @unchecked Sendable { private let session: Session - public init(session: Session, tokenRefresher: TokenRefreshable) { - self.session = Session( - configuration: session.sessionConfiguration, - interceptor: APIInterceptor(tokenRefresher: tokenRefresher), - eventMonitors: [APILogger()] - ) + public init(session: Session, tokenRefresher: TokenRefreshable?) { + if let tokenRefresher { + self.session = Session( + configuration: session.sessionConfiguration, + interceptor: APIInterceptor(tokenRefresher: tokenRefresher), + eventMonitors: [APILogger()] + ) + } else { + self.session = Session( + configuration: session.sessionConfiguration, + eventMonitors: [APILogger()] + ) + } } public func request(_ endpoint: Endpoint, decode: T.Type) async throws -> T { diff --git a/NetworkKit/Sources/NetworkKit/Kit/APIInterceptor.swift b/NetworkKit/Sources/NetworkKit/Kit/APIInterceptor.swift index 8dd6a57..b150edc 100644 --- a/NetworkKit/Sources/NetworkKit/Kit/APIInterceptor.swift +++ b/NetworkKit/Sources/NetworkKit/Kit/APIInterceptor.swift @@ -20,7 +20,11 @@ final class APIInterceptor: RequestInterceptor { let token = tokenRefresher.readToken() guard !token.isEmpty else { - completion(.failure(APIError(errorCode: "401 Token Error", message: "Token Missing"))) + completion(.failure(APIError( + statusCode: 401, + errorCode: "401 Token Error", + message: "Token Missing" + ))) return } @@ -34,7 +38,11 @@ final class APIInterceptor: RequestInterceptor { } func retry(_ request: Request, for session: Session, dueTo error: any Error, completion: @escaping @Sendable (RetryResult) -> Void) { - + guard let response = request.task?.response as? HTTPURLResponse, + response.statusCode == 401 else { + completion(.doNotRetryWithError(error)) + return + } let retryLimit = 3 guard request.retryCount < retryLimit else { completion(.doNotRetry) diff --git a/NetworkKit/Sources/NetworkKit/Kit/EndPoint.swift b/NetworkKit/Sources/NetworkKit/Kit/EndPoint.swift index 97ba593..358ca46 100644 --- a/NetworkKit/Sources/NetworkKit/Kit/EndPoint.swift +++ b/NetworkKit/Sources/NetworkKit/Kit/EndPoint.swift @@ -13,7 +13,7 @@ public protocol Endpoint: URLRequestConvertible { extension Endpoint { private var defaultHeaders: HTTPHeaders { - var headers: HTTPHeaders = [] + var headers: HTTPHeaders = [.contentType("application/json")] if let token = token { headers.add(.authorization(bearerToken: token))