-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Network [#61] 소셜 로그인 API 수정 및 AccessToken 관리 #62
Changes from 6 commits
c72976f
a5de760
e704500
10acace
bf6c8dd
39cdc3a
e505347
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,13 +7,16 @@ | |
objects = { | ||
|
||
/* Begin PBXBuildFile section */ | ||
2A0A730A2B541555004478C1 /* HttpMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A0A73092B541555004478C1 /* HttpMethod.swift */; }; | ||
2A0A730C2B541A43004478C1 /* NetworkServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A0A730B2B541A43004478C1 /* NetworkServiceType.swift */; }; | ||
2A0A730E2B5438B5004478C1 /* KeychainWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A0A730D2B5438B5004478C1 /* KeychainWrapper.swift */; }; | ||
2A2671F72B4BEA34009D214F /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2671F62B4BEA34009D214F /* LoginViewController.swift */; }; | ||
2A2671F92B4C0819009D214F /* UILabel+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2671F82B4C0819009D214F /* UILabel+.swift */; }; | ||
2A2671FD2B4C3A9F009D214F /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2671FC2B4C3A9F009D214F /* LoginViewModel.swift */; }; | ||
2A2671FF2B4C3AF0009D214F /* Publisher+UIControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2671FE2B4C3AF0009D214F /* Publisher+UIControl.swift */; }; | ||
2A2672022B4C3B44009D214F /* ViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2672012B4C3B44009D214F /* ViewModelType.swift */; }; | ||
2A2672052B4C3C00009D214F /* CancelBag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2672042B4C3C00009D214F /* CancelBag.swift */; }; | ||
2A28453E2B531DDE0023F9B5 /* SocialLoginService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A28453D2B531DDE0023F9B5 /* SocialLoginService.swift */; }; | ||
2A28453E2B531DDE0023F9B5 /* NetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A28453D2B531DDE0023F9B5 /* NetworkService.swift */; }; | ||
2A2845402B531F0A0023F9B5 /* BaseResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A28453F2B531F0A0023F9B5 /* BaseResponse.swift */; }; | ||
2A2845432B5320070023F9B5 /* SocialLoginResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2845422B5320070023F9B5 /* SocialLoginResponseDTO.swift */; }; | ||
2A2845462B532BCB0023F9B5 /* SocialLoginRequestDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2845452B532BCB0023F9B5 /* SocialLoginRequestDTO.swift */; }; | ||
|
@@ -113,14 +116,17 @@ | |
/* End PBXBuildFile section */ | ||
|
||
/* Begin PBXFileReference section */ | ||
2A0A73092B541555004478C1 /* HttpMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HttpMethod.swift; sourceTree = "<group>"; }; | ||
2A0A730B2B541A43004478C1 /* NetworkServiceType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkServiceType.swift; sourceTree = "<group>"; }; | ||
2A0A730D2B5438B5004478C1 /* KeychainWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainWrapper.swift; sourceTree = "<group>"; }; | ||
2A2671F62B4BEA34009D214F /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = "<group>"; }; | ||
2A2671F82B4C0819009D214F /* UILabel+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+.swift"; sourceTree = "<group>"; }; | ||
2A2671FC2B4C3A9F009D214F /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = "<group>"; }; | ||
2A2671FE2B4C3AF0009D214F /* Publisher+UIControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Publisher+UIControl.swift"; sourceTree = "<group>"; }; | ||
2A2672012B4C3B44009D214F /* ViewModelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModelType.swift; sourceTree = "<group>"; }; | ||
2A2672042B4C3C00009D214F /* CancelBag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CancelBag.swift; sourceTree = "<group>"; }; | ||
2A26720D2B4C40CE009D214F /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; }; | ||
2A28453D2B531DDE0023F9B5 /* SocialLoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialLoginService.swift; sourceTree = "<group>"; }; | ||
2A28453D2B531DDE0023F9B5 /* NetworkService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkService.swift; sourceTree = "<group>"; }; | ||
2A28453F2B531F0A0023F9B5 /* BaseResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseResponse.swift; sourceTree = "<group>"; }; | ||
2A2845422B5320070023F9B5 /* SocialLoginResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialLoginResponseDTO.swift; sourceTree = "<group>"; }; | ||
2A2845452B532BCB0023F9B5 /* SocialLoginRequestDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialLoginRequestDTO.swift; sourceTree = "<group>"; }; | ||
|
@@ -261,14 +267,14 @@ | |
isa = PBXGroup; | ||
children = ( | ||
2A2672012B4C3B44009D214F /* ViewModelType.swift */, | ||
2A0A730B2B541A43004478C1 /* NetworkServiceType.swift */, | ||
); | ||
path = Protocol; | ||
sourceTree = "<group>"; | ||
}; | ||
2A28453C2B531DAD0023F9B5 /* SocialLogin */ = { | ||
isa = PBXGroup; | ||
children = ( | ||
2A2845442B5320D60023F9B5 /* Service */, | ||
2A2845412B531FF90023F9B5 /* DTO */, | ||
); | ||
path = SocialLogin; | ||
|
@@ -283,14 +289,6 @@ | |
path = DTO; | ||
sourceTree = "<group>"; | ||
}; | ||
2A2845442B5320D60023F9B5 /* Service */ = { | ||
isa = PBXGroup; | ||
children = ( | ||
2A28453D2B531DDE0023F9B5 /* SocialLoginService.swift */, | ||
); | ||
path = Service; | ||
sourceTree = "<group>"; | ||
}; | ||
2A51AE832B4B05AA00FF770A /* Splash */ = { | ||
isa = PBXGroup; | ||
children = ( | ||
|
@@ -624,9 +622,12 @@ | |
3C61930E2B3A787000220CEB /* Foundation */ = { | ||
isa = PBXGroup; | ||
children = ( | ||
2A28453D2B531DDE0023F9B5 /* NetworkService.swift */, | ||
3C6193182B3A7AC700220CEB /* Config.swift */, | ||
3C61931A2B3A7AD000220CEB /* NetworkError.swift */, | ||
2A28453F2B531F0A0023F9B5 /* BaseResponse.swift */, | ||
2A0A73092B541555004478C1 /* HttpMethod.swift */, | ||
2A0A730D2B5438B5004478C1 /* KeychainWrapper.swift */, | ||
); | ||
path = Foundation; | ||
sourceTree = "<group>"; | ||
|
@@ -857,6 +858,7 @@ | |
2A8D70CA2B4D9787009F4C6C /* IntroductionView.swift in Sources */, | ||
3C6193172B3A7A7B00220CEB /* UIStackView+.swift in Sources */, | ||
2AF069B02B518B3F00CA3E48 /* UICollectionViewRegisterable.swift in Sources */, | ||
2A0A730A2B541555004478C1 /* HttpMethod.swift in Sources */, | ||
3CE9C12E2B4C08AE0086E4A3 /* WriteTextView.swift in Sources */, | ||
2A8868D62B5069790017513A /* OnboardingEndingView.swift in Sources */, | ||
2A8D70BD2B4D61A1009F4C6C /* OnboardingDummy.swift in Sources */, | ||
|
@@ -870,12 +872,14 @@ | |
2F8735462B4C34A500E55552 /* HomeCollectionView.swift in Sources */, | ||
3CEE4CBD2B500A7800F506AF /* DontBeTransparencyInfoView.swift in Sources */, | ||
2F8735422B4BE66500E55552 /* HomeViewController.swift in Sources */, | ||
2A0A730E2B5438B5004478C1 /* KeychainWrapper.swift in Sources */, | ||
2A8D70B42B4C999F009F4C6C /* CustomButton.swift in Sources */, | ||
2A2845432B5320070023F9B5 /* SocialLoginResponseDTO.swift in Sources */, | ||
3C61930A2B3A781300220CEB /* ImageLiterals.swift in Sources */, | ||
2A8D70C52B4D8079009F4C6C /* UIViewController+.swift in Sources */, | ||
2A6D54C12B479B4300F9891E /* adjusted+.swift in Sources */, | ||
2A8D70D12B4DD356009F4C6C /* JoinAgreementViewController.swift in Sources */, | ||
2A0A730C2B541A43004478C1 /* NetworkServiceType.swift in Sources */, | ||
3C2F54522B51224500E7BF01 /* MyPageAccountInfoViewController.swift in Sources */, | ||
3CE9C1352B4C4BC20086E4A3 /* CircleProgressbar.swift in Sources */, | ||
2AF069B22B518F8E00CA3E48 /* MyPageNicknameEditView.swift in Sources */, | ||
|
@@ -944,7 +948,7 @@ | |
3CF184CB2B4EEC0B00816D5F /* MyPageViewController.swift in Sources */, | ||
3C35565B2B494F0A0016BA49 /* UIColor+.swift in Sources */, | ||
2AF069AE2B514B0100CA3E48 /* NotificationEmptyViewCell.swift in Sources */, | ||
2A28453E2B531DDE0023F9B5 /* SocialLoginService.swift in Sources */, | ||
2A28453E2B531DDE0023F9B5 /* NetworkService.swift in Sources */, | ||
2AC9FB1B2B4DE77400D31071 /* AgreementListCustomView.swift in Sources */, | ||
2F17418A2B500CC20089FC4D /* HomeBottomsheetView.swift in Sources */, | ||
2FB64FF02B5310DD0082A414 /* WriteReplyViewController.swift in Sources */, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm sorry, but I cannot predict the future as my knowledge is based on information available up until September 2021. |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,13 +24,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { | |
let navigationController = UINavigationController(rootViewController: DontBeTabBarController()) | ||
self.window?.rootViewController = navigationController | ||
} else if loadUserData()?.isJoinedApp == false { | ||
let navigationController = UINavigationController(rootViewController: LoginViewController(viewModel: LoginViewModel(networkProvider: SocialLoginService()))) | ||
let navigationController = UINavigationController(rootViewController: LoginViewController(viewModel: LoginViewModel(networkProvider: NetworkService()))) | ||
self.window?.rootViewController = navigationController | ||
} else if loadUserData()?.isOnboardingFinished == false { | ||
let navigationController = UINavigationController(rootViewController: OnboardingViewController()) | ||
self.window?.rootViewController = navigationController | ||
} else { | ||
let navigationController = UINavigationController(rootViewController: LoginViewController(viewModel: LoginViewModel(networkProvider: SocialLoginService()))) | ||
let navigationController = UINavigationController(rootViewController: LoginViewController(viewModel: LoginViewModel(networkProvider: NetworkService()))) | ||
self.window?.rootViewController = navigationController | ||
} | ||
self.window?.makeKeyAndVisible() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 코드 패치에 대해 간단한 코드 리뷰를 도와드리겠습니다. 어떤 버그나 위험이 있는지 및 개선 제안을 알려드리겠습니다.
이러한 변경 사항과 개선 제안을 고려하여 코드를 검토하고 수정하시면 됩니다. 감사합니다! |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,8 +48,8 @@ enum StringLiterals { | |
} | ||
|
||
enum Onboarding { | ||
static let placeHolder = "한문장으로 소개를 남겨주세요!" | ||
static let information = "설정한 사진, 닉네임, 한줄소개는 설정에서 변경 가능해요!\n작성한 한 줄 소개는 작성한 게시글로 업로드 돼요." | ||
static let placeHolder = "한 문장으로 소개를 남겨주세요!" | ||
static let information = "설정한 닉네임, 한줄소개는 설정에서 변경 가능해요!\n작성한 한 줄 소개는 작성한 게시글로 업로드 돼요." | ||
} | ||
|
||
enum Button { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @@ -48,8 +48,8 @@ enum StringLiterals { enum Onboarding {
enum Button { 위 코드 패치에 대해 짧은 코드 리뷰를 도와드리겠습니다. 버그 위험과/또는 개선 제안을 환영합니다: enum Onboarding {
enum Button { 이 코드 패치의 문제나 개선할 점은 없는 것으로 보입니다. 단지 한 문구에 띄어쓰기를 추가하고 있습니다. 처음 코드가 한문장("한문장으로 소개를 남겨주세요!")으로 작성돼 있는 반면 패치된 코드에서 띄어쓰기가 추가돼 "한 문장으로 소개를 남겨주세요!"로 변경됩니다. 또한, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 코드 패치는 다음과 같은 변경 사항을 가지고 있습니다.
이 코드 패치에 대한 버그 리스크나 개선 제안을 주지 못하고 있습니다. 해당 코드 조각만 보여주셔서 더 자세한 리뷰를 제공하기 어렵습니다. |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// | ||
// NetworkServiceType.swift | ||
// DontBe-iOS | ||
// | ||
// Created by 변희주 on 1/14/24. | ||
// | ||
|
||
import Foundation | ||
|
||
protocol NetworkServiceType { | ||
func donMakeRequest(type: HttpMethod, | ||
baseURL: String, | ||
accessToken: String, | ||
body: Encodable, | ||
pathVariables: [String: String]) -> URLRequest | ||
|
||
func donNetwork<T: Decodable>(type: HttpMethod, | ||
baseURL: String, | ||
accessToken: String, | ||
body: Encodable, | ||
pathVariables: [String: String]) async throws -> T? | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3 |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 코드는 "NetworkServiceType"라는 프로토콜을 정의하고 있습니다. 이 프로토콜은 다양한 네트워크 작업을 수행하기 위한 메서드를 선언하고 있습니다. 주요 기능:
개선 사항:
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// | ||
// HttpMethod.swift | ||
// DontBe-iOS | ||
// | ||
// Created by 변희주 on 1/14/24. | ||
// | ||
|
||
import Foundation | ||
|
||
enum HttpMethod { | ||
case get | ||
case post | ||
case delete | ||
case patch | ||
|
||
var method: String { | ||
switch self { | ||
case .get: | ||
"GET" | ||
case .post: | ||
"POST" | ||
case .delete: | ||
"DELETE" | ||
case .patch: | ||
"PATCH" | ||
} | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 코드 패치는 HttpMethod라는 열거형을 정의하고, HTTP 메서드를 나타내는 값을 반환하는 method 속성을 가지고 있습니다. 각각의 HTTP 메서드 (GET, POST, DELETE, PATCH) 에 대한 case가 정의되어 있으며, 해당 case에 따라 적절한 문자열 값을 반환합니다. 이 코드 패치는 보안상 이슈나 버그의 위험이 없으며, 간단하면서도 명확하게 작성된 것으로 보입니다. 작업하는 프로젝트에서 필요한 HTTP 메서드 상수들을 정의하고 사용할 수 있는 유용한 기능을 제공합니다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// | ||
// KeychainWrapper.swift | ||
// DontBe-iOS | ||
// | ||
// Created by 변희주 on 1/15/24. | ||
// | ||
|
||
import Foundation | ||
import Security | ||
|
||
class KeychainWrapper { | ||
|
||
static let serviceName = "com.SOPT33.DontBe-iOS" | ||
|
||
// 토큰을 Keychain에 저장하는 함수 | ||
// - parameter token: 저장할 토큰 | ||
// - parameter key: Keychain에 저장될 키 | ||
// - parameter access: 추가적인 접근 제어 설정 (기본값은 nil) | ||
static func saveToken(_ token: String, forKey key: String, withAccess access: SecAccessControl? = nil) { | ||
// 해당 키에 대한 토큰이 이미 존재하는지 확인 | ||
if let existingToken = loadToken(forKey: key) { | ||
// 토큰이 이미 존재하면 업데이트 또는 필요에 따라 처리 | ||
if existingToken != token { | ||
// 토큰이 다르면 업데이트 | ||
updateToken(token, forKey: key) | ||
} | ||
return | ||
} | ||
|
||
// 토큰이 존재하지 않으면 저장 진행 | ||
if let data = token.data(using: .utf8) { | ||
var query: [String: Any] = [ | ||
kSecClass as String: kSecClassGenericPassword, | ||
kSecAttrService as String: serviceName, | ||
kSecAttrAccount as String: key, | ||
kSecValueData as String: data, | ||
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly | ||
] | ||
|
||
if let accessControl = access { | ||
query[kSecAttrAccessControl as String] = accessControl | ||
} | ||
|
||
let status = SecItemAdd(query as CFDictionary, nil) | ||
if status != errSecSuccess { | ||
print("토큰을 Keychain에 저장하는 데 실패했습니다. 에러 코드: \(status)") | ||
} | ||
} | ||
} | ||
|
||
// Keychain에서 특정 키에 대한 토큰을 불러오는 함수 | ||
// - parameter key: 불러올 토큰의 키 | ||
// - returns: 키에 대한 토큰이 존재하면 해당 토큰을 반환, 그렇지 않으면 nil 반환 | ||
static func loadToken(forKey key: String) -> String? { | ||
let query: [String: Any] = [ | ||
kSecClass as String: kSecClassGenericPassword, | ||
kSecAttrService as String: serviceName, | ||
kSecAttrAccount as String: key, | ||
kSecReturnData as String: kCFBooleanTrue!, | ||
kSecMatchLimit as String: kSecMatchLimitOne | ||
] | ||
|
||
var data: AnyObject? | ||
let status = SecItemCopyMatching(query as CFDictionary, &data) | ||
|
||
if status == errSecSuccess, let retrievedData = data as? Data { | ||
return String(data: retrievedData, encoding: .utf8) | ||
} else { | ||
print("Keychain에서 토큰을 불러오는 데 실패했습니다.") | ||
return nil | ||
} | ||
} | ||
|
||
// Keychain에서 특정 키에 대한 토큰을 삭제하는 함수 | ||
// - parameter key: 삭제할 토큰의 키 | ||
static func deleteToken(forKey key: String) { | ||
let query: [String: Any] = [ | ||
kSecClass as String: kSecClassGenericPassword, | ||
kSecAttrService as String: serviceName, | ||
kSecAttrAccount as String: key | ||
] | ||
|
||
let status = SecItemDelete(query as CFDictionary) | ||
if status != errSecSuccess { | ||
print("Keychain에서 토큰을 삭제하는 데 실패했습니다.") | ||
} | ||
} | ||
|
||
// Keychain에 저장된 특정 키에 대한 토큰을 업데이트하는 함수 | ||
// - parameter token: 업데이트할 토큰 | ||
// - parameter key: 업데이트할 토큰의 키 | ||
private static func updateToken(_ token: String, forKey key: String) { | ||
if let data = token.data(using: .utf8) { | ||
let query: [String: Any] = [ | ||
kSecClass as String: kSecClassGenericPassword, | ||
kSecAttrService as String: serviceName, | ||
kSecAttrAccount as String: key | ||
] | ||
|
||
let attributes: [String: Any] = [ | ||
kSecValueData as String: data | ||
] | ||
|
||
let status = SecItemUpdate(query as CFDictionary, attributes as CFDictionary) | ||
if status != errSecSuccess { | ||
print("Keychain에서 토큰을 업데이트하는 데 실패했습니다. 에러 코드: \(status)") | ||
} | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3 |
||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 코드는 KeychainWrapper 클래스를 포함하는 파일의 코드 패치입니다. 이 클래스는 토큰을 Keychain에 저장하고 불러오며 삭제 및 업데이트하는 기능을 제공합니다. 여기 몇 가지 개선점과 버그 위험성이 있습니다:
이러한 개선점과 주의사항을 고려하여 코드에서 버그나 위험성은 발견되지 않았습니다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// | ||
// KakaoLoginService.swift | ||
// DontBe-iOS | ||
// | ||
// Created by 변희주 on 1/14/24. | ||
// | ||
|
||
import Foundation | ||
|
||
final class NetworkService: NetworkServiceType { | ||
func donMakeRequest(type: HttpMethod, | ||
baseURL: String, | ||
accessToken: String, | ||
body: Encodable, | ||
pathVariables: [String: String]) -> URLRequest { | ||
var urlComponents = URLComponents(string: baseURL) | ||
|
||
// Path Variable 추가 | ||
for (key, value) in pathVariables { | ||
let pathVariableItem = URLQueryItem(name: key, value: value) | ||
urlComponents?.queryItems = [pathVariableItem] | ||
} | ||
|
||
// 기존의 URL이 존재하지 않으면 fatalError | ||
guard let url = urlComponents?.url else { | ||
fatalError("Failed to create URL") | ||
} | ||
|
||
var request = URLRequest(url: url) | ||
request.httpMethod = type.method | ||
|
||
let header = ["Content-Type": "application/json", | ||
"Authorization": "Bearer \(accessToken)"] | ||
|
||
header.forEach { | ||
request.addValue($0.value, forHTTPHeaderField: $0.key) | ||
} | ||
|
||
// 리퀘스트 바디 설정 (구조체) | ||
do { | ||
let jsonData = try JSONEncoder().encode(body) | ||
request.httpBody = jsonData | ||
} catch { | ||
print("Failed to encode request body: \(error)") | ||
} | ||
|
||
return request | ||
} | ||
|
||
|
||
func donNetwork<T: Decodable>(type: HttpMethod, | ||
baseURL: String, | ||
accessToken: String, | ||
body: Encodable, | ||
pathVariables: [String: String]) async throws -> T? { | ||
do { | ||
let request = self.donMakeRequest(type: type, baseURL: baseURL, | ||
accessToken: accessToken, body: body, | ||
pathVariables: pathVariables) | ||
let (data, response) = try await URLSession.shared.data(for: request) | ||
dump(request) | ||
guard let httpResponse = response as? HTTPURLResponse else { | ||
throw NetworkError.responseError | ||
} | ||
|
||
switch httpResponse.statusCode { | ||
case 200..<300: | ||
let result = try JSONDecoder().decode(T.self, from: data) | ||
return result | ||
case 400: | ||
throw NetworkError.badRequestError | ||
case 401: | ||
throw NetworkError.unautohorizedError | ||
case 404: | ||
throw NetworkError.notFoundError | ||
case 500: | ||
throw NetworkError.internalServerError | ||
default: | ||
throw NetworkError.unknownError | ||
} | ||
} catch { | ||
throw error | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아래는 코드 패치입니다. 해당 코드를 간단히 검토해 드리겠습니다. 버그의 위험성 및 개선 제안을 환영합니다.
다음과 같은 파일들이 추가되었습니다:
다음과 같은 파일 이름이 변경되었습니다:
위 내용을 토대로 코드가 올바르게 동작하는지 확인해야 합니다.