✔︎ 오늘의 정리
- RxSwift 복습
- Interceptor
- 구현 로직
- 실제 구현
RxSwift 복습
왜케 나 RxSwift 관련 글을 쓴 적이 있는 거 같지? 왜 정리한 적이 잇던 거 같지?? 했는데 전에 TIL로 정리한 적이 있었다.
.. ..
너무열심히정리했는데?!
한창 코드 쓰다가 막혀서 그냥 이전에 정리해뒀던 필기 보면서 공부하고 RxSwift 시리즈나 써야지 했건만 ,, ,,
갑자기 의욕을 잃엇다
복습을 열심히 한 걸루... 나중에 까묵을만할 때 다시 정리해보고자 한다.
[SeSAC] November 1, 2023
✔︎ 오늘의 정리 사용자가 라이트 / 다크 모드를 바꿀 때 대응하기 스토리보드 코드로 화면 전환하기 RxSwift Observable / Observer subject bind withUnretained, subscribe(onNext:...) / subscribe(with:...) / subscribe(onNe
dk308c.tistory.com
그 글은 위와 같다.
암튼.
Interceptor
요즘 LSLP 프로젝트를 진행하고 있는데 토큰을 저장하는 방식으로 UserDefaults를 쓸지 KeyChain을 쓸지 고민햇는데 그냥 빠르고 간편하게 UserDefaults를 쓰기로 했다. KeyChain을 쓰는 이유는 보안상의 이유가 가장 크고 앱을 삭제해도 해당 유저의 값을 저장하고 있는 장점이 있어서,, 겠지만? 해당 프로젝트는 실제로 출시할 게 아니라서 일부 유저들끼리만 testFlight로 돌려볼 예정이라 보안상으로 탈취당할 위험이 적고 아무래도 UserDefaults가 구현이 간편하니까 ,, ^__^ 하는 걸루~ 결정했다.
문득 만약에 이 앱이 유료 구독 모델을 생각하고 있고 뭐 일부 유저한테 일주일 동안 무료 체험 기간을 줄 거야! 한다면 무조건 키체인을 쓰겠구나! 싶지만 말이다 ,, ,,
암튼. 인터셉터는 왜 나왔냐면 얘가 왜 굳이 필요한 걸까?! 라는 생각이 들어서 .. 한번 적어보기로 했다.
얘가 왜 필요한지 알려면 인터셉터가 어디에, 왜 쓰이는지 알아야 한다.
일단,, 처리 과정은 다음과 같다.
App에서 Server로 통신을 보내고 싶고 Moya를 사용하고 있다고 한다면 위와 같이 동작한다.
Moya Provider에 plugin까지 사용하게 된다면 request와 response를 할 경우 아래와 같이 동작할 것이다.
request :
1. Plugin.prepare -> 2. Plugin.willSend -> 3. Interceptor.adapt
response :
4. Interceptor.retry -> 5. Plugin.didReceive -> 6. Plugin.process
참고로 plugin은 moya에 있는 기능이고 interceptor는 alamofire에 있다.
암튼. 그럼 request를 보낼 때 interceptor에서 전처리를 하고 받은 response를 다시 interceptor에서 받아서 후처리를 한다고 보면 되겠당.
인터셉터 로직 처리가 잘 이해가 안 가서 그냥... 써봤다.
계속 ㅜㅜ 얘를 어느 타이밍에 불러주고? 어떻게 실행되는지를 좀 헤맸는데 생각보다 간단했다
내가 구태여 실행시켜줄 필요 없이 구현하고 provider 혹은 request에 넣어준다면 moya랑 alamofire에서 데이터를 통신할 때 처리하고 나한테 보여주는 거였음
adapt의 경우 대부분 header에 무언가를 추가할 때? 사용하는 것 같았다. (본 블로그들은 대부분 그랬음)
나 같은 경우에는 header를 이미 request를 만들 때 어떤 요청을 보내느냐에 따라서 미리 처리해놔서 adapt 처리를 할 필요가 없고, retry만 만들어주면 됐다.
구현 로직
retry 로직은 다음과 같다.
- response가 왔을 때, error가 있다면 Interceptor의 retry 구문이 실행된다.
- 이때, 이 error가 token 만료 error인지 확인한다.
- 토큰 만료 에러가 아니라면 Interceptor에서 별 다른 처리 없이 (retry X) 에러를 보낸다.
- 토큰 만료 에러가 맞다면 refreshToken을 이용하여 accessToken을 새로 받을 수 있는지 데이터 통신을 한다.
- 만약 사용 가능한 refreshToken이라면 accessToken을 갈아끼운다.
- 이후 원래 실행하려고 했던 데이터 통신을 한다.
- 만료된 refreshToken이라면 사용자의 재로그인이 필요하므로 화면을 전환해준다.
- 만약 사용 가능한 refreshToken이라면 accessToken을 갈아끼운다.
- 이때, 이 error가 token 만료 error인지 확인한다.
실제 구현
아래는 구현한 Interceptor이다.
final class AuthInterceptor: RequestInterceptor {
static let shared = AuthInterceptor()
private init() {}
func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
print("retry 진입")
guard let response = request.task?.response as? HTTPURLResponse, response.statusCode == 419
else {
completion(.doNotRetryWithError(error))
return
}
// statusCode == 419
MoyaAPIManager.shared.fetchInSignProgress(.refreshAccessToken, type: TokenResponse.self)
.subscribe(with: self) { owner, response in
switch response {
case .success(let result):
// 토큰 재발급 성공 -> 갈아끼우기
UserDefaultsHelper.shared.accessToken = result.token
completion(.retry)
case .failure(let error):
// 갱신 실패 -> 로그인 화면으로 전환
completion(.doNotRetryWithError(error))
// 이전에 쌓였던 화면이 clear => 새로 진입
let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
let SceneDelegate = windowScene?.delegate as? SceneDelegate
let vc = LoginViewController()
let nav = UINavigationController(rootViewController: vc)
SceneDelegate?.window?.rootViewController = nav
SceneDelegate?.window?.makeKeyAndVisible()
}
}
.dispose()
}
}
이후, validationType도 추가적으로 설정해 주었다.
기본은 `.none`으로 되어 있는데, 200번대의 성공적인 access만 validation 처리를 해줬다 ... ...
extension MoyaNetwork: TargetType {
... ...
var validationType: ValidationType {
return .successCodes
}
}
provider에 적용은 아래와 같이 했다.
private lazy var provider = MoyaProvider<MoyaNetwork>(requestClosure: requestClosure, session: Session(interceptor: AuthInterceptor.shared))
참고 자료
https://github.com/Moya/Moya/blob/master/docs/Plugins.md
https://lsj8706.tistory.com/21
Swift Moya에 Interceptor 적용하여 자동로그인(토큰 갱신) 구현하기
오늘은 iOS에서 로그인을 구현할 때 Interceptor를 사용해 자동으로 토큰을 갱신하는 방법을 알아봅시다! 🏃🏻♀️ 오늘의 주제 현재 진행중인 프로젝트에서는 Apple과 카카오로 로그인하는 소셜
lsj8706.tistory.com
https://eeyatho.tistory.com/256
Swift ) Moya Interceptor, Plugin - EEYatHo iOS
Moya 에서 네트워크 통신에 접근할 수 있는 방법 2가지 Interceptor Plugin Interceptor #git RequestInterceptor의 구현체를 MoyaProvider.Session 에 넣기 let insterceptor = MyInterceptor() let session = Session(interceptor: insterceptor
eeyatho.tistory.com
[iOS] RequestInterceptor를 이용한 JWT 인증 구현
안녕하세요. 이전에 [iOS] Authenticator 프로토콜로 JWT 인증 구현하기 라는 JWT 인증 관련 글을 올린 적이 있는데 그때는 무슨 일인지 adapt와 retry가 호출되지 않아서 Authenticator를 사용 했었는데요. 이
bugle.tistory.com
'TIL' 카테고리의 다른 글
[SeSAC] December 6, 2023 (1) | 2023.12.11 |
---|---|
[SeSAC] December 2, 2023 (1) | 2023.12.03 |
[SeSAC] November 27, 2023 (1) | 2023.11.28 |
[SeSAC] November 20, 2023 (0) | 2023.11.21 |
[SeSAC] November 18, 2023 (0) | 2023.11.19 |