Skip to content

Commit ee19f37

Browse files
재인증 API 요청들의 순서 보장 (#123)
* [수정] 재인증 시 API 순서 보장할 수 있도록 수정 * [버전] Prodution 2.1.2(201020) 버전 업데이트 * [버전] Develop 2.1.2(201020) 버전 업데이트 * [수정] sync queue 밖에서 completion 사용
1 parent 724ca22 commit ee19f37

File tree

2 files changed

+78
-69
lines changed

2 files changed

+78
-69
lines changed

SOOUM/SOOUM.xcodeproj/project.pbxproj

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3942,7 +3942,7 @@
39423942
CODE_SIGN_ENTITLEMENTS = "SOOUM/Resources/SOOUM-Dev.entitlements";
39433943
CODE_SIGN_IDENTITY = "Apple Development";
39443944
CODE_SIGN_STYLE = Automatic;
3945-
CURRENT_PROJECT_VERSION = 201010;
3945+
CURRENT_PROJECT_VERSION = 201020;
39463946
DEVELOPMENT_TEAM = 99FRG743RX;
39473947
GENERATE_INFOPLIST_FILE = YES;
39483948
INFOPLIST_FILE = "SOOUM/Resources/Develop/Info-dev.plist";
@@ -3965,7 +3965,7 @@
39653965
"$(inherited)",
39663966
"@executable_path/Frameworks",
39673967
);
3968-
MARKETING_VERSION = 2.1.1;
3968+
MARKETING_VERSION = 2.1.2;
39693969
OTHER_SWIFT_FLAGS = "$(inherited) -D DEVELOP";
39703970
PRODUCT_BUNDLE_IDENTIFIER = com.sooum.dev;
39713971
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -3994,7 +3994,7 @@
39943994
CODE_SIGN_ENTITLEMENTS = "SOOUM/Resources/SOOUM-Dev.entitlements";
39953995
CODE_SIGN_IDENTITY = "Apple Development";
39963996
CODE_SIGN_STYLE = Automatic;
3997-
CURRENT_PROJECT_VERSION = 201010;
3997+
CURRENT_PROJECT_VERSION = 201020;
39983998
DEVELOPMENT_TEAM = 99FRG743RX;
39993999
GENERATE_INFOPLIST_FILE = YES;
40004000
INFOPLIST_FILE = "SOOUM/Resources/Develop/Info-dev.plist";
@@ -4017,7 +4017,7 @@
40174017
"$(inherited)",
40184018
"@executable_path/Frameworks",
40194019
);
4020-
MARKETING_VERSION = 2.1.1;
4020+
MARKETING_VERSION = 2.1.2;
40214021
OTHER_SWIFT_FLAGS = "$(inherited) -D DEVELOP";
40224022
PRODUCT_BUNDLE_IDENTIFIER = com.sooum.dev;
40234023
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -4233,7 +4233,7 @@
42334233
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
42344234
CODE_SIGN_ENTITLEMENTS = "SOOUM/Resources//SOOUM.entitlements";
42354235
CODE_SIGN_STYLE = Automatic;
4236-
CURRENT_PROJECT_VERSION = 201010;
4236+
CURRENT_PROJECT_VERSION = 201020;
42374237
DEVELOPMENT_TEAM = 99FRG743RX;
42384238
GENERATE_INFOPLIST_FILE = YES;
42394239
INFOPLIST_FILE = "SOOUM/Resources/Production/Info-prod.plist";
@@ -4255,7 +4255,7 @@
42554255
"$(inherited)",
42564256
"@executable_path/Frameworks",
42574257
);
4258-
MARKETING_VERSION = 2.1.1;
4258+
MARKETING_VERSION = 2.1.2;
42594259
OTHER_SWIFT_FLAGS = "$(inherited) -D PRODUCTION";
42604260
PRODUCT_BUNDLE_IDENTIFIER = com.sooum.prod;
42614261
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -4282,7 +4282,7 @@
42824282
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
42834283
CODE_SIGN_ENTITLEMENTS = "SOOUM/Resources//SOOUM.entitlements";
42844284
CODE_SIGN_STYLE = Automatic;
4285-
CURRENT_PROJECT_VERSION = 201010;
4285+
CURRENT_PROJECT_VERSION = 201020;
42864286
DEVELOPMENT_TEAM = 99FRG743RX;
42874287
GENERATE_INFOPLIST_FILE = YES;
42884288
INFOPLIST_FILE = "SOOUM/Resources/Production/Info-prod.plist";
@@ -4304,7 +4304,7 @@
43044304
"$(inherited)",
43054305
"@executable_path/Frameworks",
43064306
);
4307-
MARKETING_VERSION = 2.1.1;
4307+
MARKETING_VERSION = 2.1.2;
43084308
OTHER_SWIFT_FLAGS = "$(inherited) -D PRODUCTION";
43094309
PRODUCT_BUNDLE_IDENTIFIER = com.sooum.prod;
43104310
PRODUCT_NAME = "$(TARGET_NAME)";

SOOUM/SOOUM/Data/Managers/AuthManager/AuthManager.swift

Lines changed: 70 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ protocol AuthManagerDelegate: AnyObject {
3737

3838
class AuthManager: CompositeManager<AuthManagerConfiguration> {
3939

40+
private let reAuthenticateQueue = DispatchQueue(label: "com.sooum.reAuthenticate.serial.queue")
41+
4042
private var isReAuthenticating: Bool = false
4143
private var pendingResults: [(AuthResult) -> Void] = []
4244

@@ -229,72 +231,79 @@ extension AuthManager: AuthManagerDelegate {
229231
4. RefreshToken 도 유효하지 않다면 로그인 시도
230232
*/
231233
func reAuthenticate(_ token: Token, _ completion: @escaping (AuthResult) -> Void) {
232-
233-
guard self.authInfo.token.isEmpty == false else {
234-
let error = NSError(
235-
domain: "SOOUM",
236-
code: -99,
237-
userInfo: [NSLocalizedDescriptionKey: "tokens not found"]
238-
)
239-
completion(.failure(error))
240-
return
241-
}
242-
243-
/// 1개 이상의 API에서 reAuthenticate 요청 했을 때,
244-
/// 처음 요청이 끝날 떄까지 대기
245-
guard self.isReAuthenticating == false else {
234+
var immediateResult: AuthResult?
235+
/// isReAuthenticating == true로 변경되기 전 짧은 시간에 재인증 요청이 들어왔을 때, 순서 보장
236+
let shouldRequest: Bool = self.reAuthenticateQueue.sync {
237+
guard self.authInfo.token.isEmpty == false else {
238+
let error = NSError(
239+
domain: "SOOUM",
240+
code: -99,
241+
userInfo: [NSLocalizedDescriptionKey: "tokens not found"]
242+
)
243+
immediateResult = .failure(error)
244+
return false
245+
}
246+
247+
/// AccessToken이 업데이트 됐다면, 즉시 성공 처리
248+
guard token == self.authInfo.token else {
249+
immediateResult = .success
250+
return false
251+
}
252+
246253
self.pendingResults.append(completion)
247-
return
248-
}
249-
250-
/// AccessToken이 업데이트 됐다면, 즉시 성공 처리
251-
guard token == self.authInfo.token else {
252-
completion(.success)
253-
return
254+
255+
/// 1개 이상의 API에서 reAuthenticate 요청 했을 때,
256+
/// 처음 요청이 끝날 떄까지 대기
257+
guard self.isReAuthenticating == false else { return false }
258+
self.isReAuthenticating = true
259+
260+
return true
254261
}
255-
256-
self.isReAuthenticating = true
257-
self.pendingResults.append(completion)
258-
259-
let request: AuthRequest = .reAuthenticationWithRefreshSession(token: token)
260-
self.provider.networkManager.perform(TokenResponse.self, request: request)
261-
.map(\.token)
262-
.subscribe(
263-
with: self,
264-
onNext: { object, token in
265-
266-
if token.accessToken.isEmpty && token.refreshToken.isEmpty {
267-
let error = NSError(
268-
domain: "SOOUM",
269-
code: -99,
270-
userInfo: [NSLocalizedDescriptionKey: "Session not refresh"]
271-
)
272-
273-
object.excutePendingResults(.failure(error))
274-
} else {
275-
276-
object.updateTokens(token)
262+
/// 여러 API가 재인증 요청 시, 맨 처음 요청만 재인증 요청
263+
if shouldRequest == false, let result = immediateResult {
264+
completion(result)
265+
} else if shouldRequest {
266+
267+
let request: AuthRequest = .reAuthenticationWithRefreshSession(token: token)
268+
self.provider.networkManager.perform(TokenResponse.self, request: request)
269+
.map(\.token)
270+
.subscribe(
271+
with: self,
272+
onNext: { object, token in
277273

278-
// FCM token 업데이트
279-
object.provider.networkManager.registerFCMToken(from: #function)
274+
if token.accessToken.isEmpty && token.refreshToken.isEmpty {
275+
let error = NSError(
276+
domain: "SOOUM",
277+
code: -99,
278+
userInfo: [NSLocalizedDescriptionKey: "Session not refresh"]
279+
)
280+
281+
object.excutePendingResults(.failure(error))
282+
} else {
283+
284+
object.updateTokens(token)
285+
286+
// FCM token 업데이트
287+
object.provider.networkManager.registerFCMToken(from: #function)
288+
289+
object.excutePendingResults(.success)
290+
}
280291

281-
object.excutePendingResults(.success)
292+
object.isReAuthenticating = false
293+
},
294+
onError: { object, error in
295+
/// 재인증 과정이 실패하면 항상 재로그인 시도
296+
object.certification()
297+
.subscribe(onNext: { isRegistered in
298+
object.excutePendingResults(isRegistered ? .success : .failure(error))
299+
300+
object.isReAuthenticating = false
301+
})
302+
.disposed(by: object.disposeBag)
282303
}
283-
284-
object.isReAuthenticating = false
285-
},
286-
onError: { object, error in
287-
/// 재인증 과정이 실패하면 항상 재로그인 시도
288-
object.certification()
289-
.subscribe(onNext: { isRegistered in
290-
object.excutePendingResults(isRegistered ? .success : .failure(error))
291-
292-
object.isReAuthenticating = false
293-
})
294-
.disposed(by: object.disposeBag)
295-
}
296-
)
297-
.disposed(by: self.disposeBag)
304+
)
305+
.disposed(by: self.disposeBag)
306+
}
298307
}
299308

300309
func initializeAuthInfo() {

0 commit comments

Comments
 (0)