✔︎ 오늘의 정리
- RxSwift와 Moya를 이용하여 네트워크 통신하기
- Observable.create()
- Disposable.create()
- Keypath
RxSwift와 Moya를 이용하여 네트워크 통신하기
꽤 오래 이어진 주제인 걸로 아는데(til에서?!) 이력서 쓰랴 뭐 하랴 하다 보니 조금씩 밀렸다. 사실 이게 제일 중요한 것 같은데!! (ㅠㅠ) 너무 아쉽다... 아무튼.
class MoyaAPIManager {
static let shared = MoyaAPIManager()
private init() { }
private let requestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
do {
var request: URLRequest = try endpoint.urlRequest()
request.timeoutInterval = 10 // timeout 처리 => 10초 지나면 error로 처리됨
done(.success(request))
} catch {
done(.failure(MoyaError.underlying(error, nil)))
}
}
private lazy var provider = MoyaProvider<MoyaNetwork>(requestClosure: requestClosure)
func fetchInSignProgress<T: Decodable>(_ api: MoyaNetwork, type: T.Type, errorHandler: @escaping (ErrorResponse) -> Void) -> Observable<Result<T, Error>> {
return Observable.create { observer in
self.provider.request(api) { response in
switch response {
case .success(let response):
let statusCode = response.statusCode
if response.statusCode == 200 {
let result = try! JSONDecoder().decode(T.self, from: response.data)
observer.onNext(.success(result))
} else {
let value = try! JSONDecoder().decode(ErrorResponse.self, from: response.data)
let error = LSLPError(rawValue: statusCode) ?? .undefinedError
errorHandler(value)
observer.onNext(.failure(error))
}
case .failure(let error):
observer.onError(error)
}
}
return Disposables.create()
}
}
}
전체 코드는 위와 같다.
처음에는 Single을 쓰려고 하다가 멘토님께 질문을 듣고 와,, 나 싱글 모르면서 쓰려고 하네? 로 변해서 싱글을 공부했다.
아! 싱글 왜 쓰는지 알았다. 그리고 쓰려고 하니 .. ..
근데 나 싱글 어떻게 쓰는지 모르네?
깡으로 며칠을 날렸다.
그러다가 모 멘토님께 조언을 들은 게,, 그 이전의 추상화 단계도 구현 못하면서 왜 단계들을 쑥 건너뛰고 RxSwift + RxMoya로 건너뛰냐는 것이다. 너무너무너무 맞는 말이어서 오히려 뼈가 아팠다... :3
나는 .. 밥.
내가 밥인 걸 늘 잊지말자.
겸손하게 아는 걸로 구현을 하고 도전을 했어야 하는 것을~~~~!!! ㅠ,ㅠ
그래도 Moya는 한 번 써 보고 싶었고 추후 unit test 구현을 넣고 싶어서 (물론 alamofire로도 unit test 코드를 잘 구현할 수 있는 거 알고 잇다. 그치만...... 그치만~~~~~!!!!!!!!!!
사실 그치만으로 나오는 이유들은 다 쓸모없고 결국에는 하던 거 계속 하고싶어잉 .. 인 걸,,,,,, 알고잇다,,,,,,,,,,
결국 alamofire로 다시 백 해서 구현하다가 아,, 차라리 moya 잡던 거 조금만 하면 될 거 같은데? 하는 생각으로 깔짝이니까? 정말? 됐? 다?
여기저기 코드를 보고 구현은 하긴 했는데 어떻게 동작하는지는 전~~~~혀 모르겠다.
모르겠는 걸 꼽아보자.
- Observable.create() 얘뭔데?
- Disposable.create() 얘뭔데?
- return Disposable.create() 얘 왜 리턴하는데?
가보자고.
Observable.create()

모르겠고 일단 정의부터 보자.
얘는 보니까? ObservableType에 속한 친구고 내부에서 `subscribe` 함수를 포함한다고 한다.
위에 나와 있는 공식 문서를 보면 ...

엥? 싶지만 그러니까 create 자체가 Observable을 생성하고 내부에서 `onNext`를 사용하여 이벤트를 보낼 수 있다. 내부에서 `onNext`와 `onComplete`, `onError` method를 사용자가 적절히 호출하면 되는듯하다.
그럼 위 코드에서 Observable.create(_:) 를 이용하여 먼가를 했던 건 Observer를 생성 후 subscribe를 한 상태라고 볼 수 있다. 사용한 create 함수는 옵저버를 생성 후 사용자가 클로저 내에서 원하는 event를 emit 하면 Observable로 반환해 주는데, 이 옵저버는 AnonymousObservable을 생성할 때는 create를 호출하며 전달된 클로저가 전달되며 subscribe된다고 한다.
아하~~~~!!!!!!!
추후 single이든 Observable이든 rx에서 사용할 수 있는 친구를 리턴해 줘야 손쉽게 사용할 수 있으니까 Observable을 생성 / subscribe 한 후에 특정 이벤트를 전달하여 보내주는구나?
Disposables.create()
다음. 얘 뭔데?
Disposable ... 이 친구는 어디선가 봤다. 아니? 분명 알고 있다. 왜냠...


익숙하게 사용하는 disposed와 DisposeBag이 속하는 프로토콜이걸랑. Disposable과 Disposables는 비슷하게 생겼으니 암튼 관계가 있지 않을까?.? 하고 disposables... 의 definition을 찾아가 보면 .. ..

엥 빈 구조체이다.
정말 빈 구조체를 만드는 작업?! 만 있을까?
생각해 보면 그럴 리가 없다. 내부에 create() 함수도 있어야 하고, 그 외에도 무수한 함수들이 저 안에 있는데 대체 우떤 방식으로 구현되어 있길래 절케 되어 있을까?

RxSwift의 공식 문서에 들어가 보면 Disposable을 모아둔 폴더가 있다. 그 중, NopDisposable에 원하는 내용이 있었다.

엥 ..
결국 Disposables.create()는 disposable을 생성하기는 하지만 아무것도 하지 않고 반환되는 친구를 말하는 거였는갑다.
create 함수 중에 매개변수로 클로저를 받아서 실행하는 함수도 있는 모양인데 그건 아래 블로그로~!
https://jeonyeohun.tistory.com/365
[RxSwift] Disposables.create() 왜 하지?
Disposables.create 분석해보기 Rx를 하면서 많이 들었던 의문.. let numbers = Observable.create { observer in observer.onNext(1) observer.onNext(2) observer.onNext(2) return Disposables.create() } 여기서 마지막에 Disposables.create()를
jeonyeohun.tistory.com
왜 하지? 관련 답안은 다음과 같다.
비동기 코드가 없는 Disposables.create()의 경우에는 시퀀스가 종료되면 모든 작업이 종료되니까 말 그대로 빈 Disposable을 반환하기 위해서고, 비동기 코드가 있는 경우(지금!!!!!)에는 Dispose 되는 시점에 해당하는 클로저를 전달하여 비동기 작업이 실행되도록 하기 위함이다.
아하, 그래서 추후에 ViewModel에서 해당하는 부분을 받을 때? flatmap을 통해 받은 후, 다시금 구독을 통해 값을 전달받아 처리해줄수 수 있게 대는군아.
Rx를 활용하여 네트워크를 통신하는 방법도 그렇게 하는 이유도? 몰랐다. 사실 수업 코드를 활용했으면 이렇게까지 삽질 안 하고 금방 끝날 수 있엇는데 괜히 욕심부리다가 이렇게 됐다.
.. .. 뭐 그렇게됏다.
다음부터는 오래 붙잡고 있지 말아야지... 젭알~
https://reactivex.io/documentation/operators/create.html
ReactiveX - Create operator
You can create an Observable from scratch by using the Create operator. You pass this operator a function that accepts the observer as its parameter. Write this function so that it behaves as an Observable — by calling the observer’s onNext, onError, a
reactivex.io
https://jeonyeohun.tistory.com/374
[RxSwift] Observable.create의 동작원리 이해하기
Observable.create Observable을 사용하면서 진짜 많이 쓰는 create 메서드가 어떻게 동작하는지 알아보려고 합니다. 일반적으로 create에 클로저를 전달하고 Observable을 반환받습니다. let observable = Observable.
jeonyeohun.tistory.com
Keypath 이용하기

대체 이 친구가 뭐시냐,, 싶었다
첨 들어본 거 같은데? 왠지 여러 블로그를 보면 쓰는 방법은 익숙하다. 바로바로~ SwiftUI ForEach에서 id를 가져오는 방법과 유사했다!
... ...
var body: some View {
NavigationStack {
List {
ForEach(filterMovie, id: \.id) { movie in
... ...
왜, 저기 `\.id` 부분 말이다!!!
\<#type name#>.<#path#>
swift 공식 문서에 따르면, 이런 방식으로 표현한다고 한다.
흠. 쓰는 건 그렇다고 치고 ,, ,,
근데 이 친구를 왜 활용할까? 애초에 keyPath는 뭘까?
먼저, KeyPath를 말하기 전에 Key-Value Coding에 대해서 알아야 한다.
Key-Value Coding은 옵젝씨 때부터 사용되어 Key 또는 KeyValue 값을 통해 간접적으로 데이터를 가져오는 방식을 의미한다. 공식 문서에 의하면 직접적인 접근을 하지 않음으로써 보안을 보장한다고. 또, Key는 stirng이어야 하는 등 여러 규칙이 잇는데 이는 글 아래 문서에 찾아볼 수 있당.
KeyPath란 값에 의한 참조가 아니라 프로퍼티에 대한 참조로, 말 그대로 그 경로에 닿기 위한 path를 의미한다.
struct Employee {
let name: String
let role: String
let level: Int
}
var designer = Employee(name: "Song", role: "Designer", level: 10)
// KeyPath<Employee, String>
let nameKeyPath = Employee.name
이런 식으루.
근데 이 KeyPath를 사용하는 이유가 무엇일까?
정답! 보안 때문이다.
네트워크 통신을 통해 사용자의 id / pw / token을 주고 받을 때는 암호화하여 보내는 작업이 필요하다. 어느 하나 암호화되지 않는다면 해커가 중간에 정보를 탈취하게 되었을 때 아주 곤란해질 것이다.
,, 그간 자주 보았지 않은가?! 수많은 은행 앱에서 털린 우리의 개인 정보를 ,, ,,
암튼. 우리 앱이 그 꼴이 나기 전에 자체적으로 보안을 신경써야 한다.
.. ... 어라?
분명 오늘 키패스로 토큰 로직까지 짜려고 햇는데 시간이 왜 이렇게 ,, ㅠ,ㅠ
아오 로그인 언제 넘어가냐고
https://developer.apple.com/documentation/swift/keypath
KeyPath | Apple Developer Documentation
A key path from a specific root type to a specific resulting value type.
developer.apple.com
Documentation
docs.swift.org
https://techblog.woowahan.com/2715/
알아두면 쓸모 있는 Swift의 기능들 | 우아한형제들 기술블로그
{{item.name}} Swift는 C와 Objective-C와의 연동은 뛰어나지만 JS, Python 과 같은 dynamic 언어들과는 상대적으로 떨어집니다. 그 이유들로 추가되고 있는 기능들이 있습니다. KeyPath, dynamicMemberLookup 등 Swift의
techblog.woowahan.com
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueCoding/index.html
Key-Value Coding Programming Guide: About Key-Value Coding
Key-Value Coding Programming Guide
developer.apple.com
https://80000coding.oopy.io/2c9f09c6-8162-4336-b8fe-a2d2d721f5ae#6df96dd747214add94a8547232d3a4c9
(Swift) 이름은 모르지만 어쨌든 "\." 에 대한 포스팅 (feat. KeyPath)
SwiftUI 튜토리얼을 따라하다가 아래와 같은 코드를 보게되었다.
80000coding.oopy.io
'TIL' 카테고리의 다른 글
[SeSAC] December 2, 2023 (1) | 2023.12.03 |
---|---|
[SeSAC] November 30, 2023 (0) | 2023.12.01 |
[SeSAC] November 20, 2023 (0) | 2023.11.21 |
[SeSAC] November 18, 2023 (0) | 2023.11.19 |
[SeSAC] November 14, 2023 (6) | 2023.11.15 |