Single
์๋ ์ฝ๋๋ observable๋ก ๋ง๋ ๋คํธ์ํฌ ํต์ ์ฝ๋์ด๋ค.
    func fetchTestData() -> Observable<TestModel> {
        return Observable.create { observer -> Disposable in
            
            AF.request(NetworkManager.testURL)
                .validate(statusCode: 200..<300)
                .responseDecodable(of: TestModel.self) { response in
                    
                    switch response.result {
                    case .success(let success):
                        observer.onNext(success)
                    case .failure(let error):
                        observer.onError(error)
                    }
                }
            
            return Disposables.create()
        }
    } 
๊ทธ๋ฌ๋, ์ ์ฝ๋์๋ ๋ฌธ์ ์ ์ด ํ๋ ์๋ค. 
๋ฒํผ์ ํญํ์ ๋, fetchTestData() ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค๊ณ  ํ๋ค๋ฉด,
ํด๋น ํธ์ถ๋ถ๋ flatMap์ ํ์ฉํด์ ๋คํธ์ํฌ ์์ฒญ์ ํ์ฌ
ํด๋น ์๋ต๊ฐ์ observable๋ก ๋ณํํ์ฌ subscribe๋ฅผ ํ๊ฒ ๋๋๋ฐ,
๊ตฌ๋
๊ณผ ๋์์ next๋ก ๊ฐ์ด ์ ์ ๋ฌ๋์ง๋ง,
ํ๋ฒ ๋ ํธ์ถํ๋ ค๊ณ  ์๋ํ๋ ๊ฒฝ์ฐ!!
์์ subscribe๊ฐ dispose๋์ง ์๊ณ  ์คํธ๋ฆผ์ด ์ ์ง๋ ์ํ๋ก
์๋ก์ด ์คํธ๋ฆผ์ ์์ฑ๋๋ค.
(.debug()๋ฅผ ํตํด ํ์ธ!)
๋๋ฒ๊น
์ ์ฐ์ด๋ณด์ง ์์ผ๋ฉด, ์ ์ ์์๋ ๋ฌธ์ ....
๋์ํ๋๋ฐ์๋ ๋ฌธ์ ๋ ์์ง๋ง, 
์ด๋๋ก ๊ณ์ ์คํธ๋ฆผ์ด ์์ธ๋ค..? ๋ฉ๋ชจ๋ฆฌ๊ฐ ํด์ ๋์ง ์๋๋ค..?
์ด๊ฒ์ด ๋ฌธ์ .....
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์๋ ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์
๋คํธ์ํฌ ํต์ ์ ์ฑ๊ณตํ์ ๋, ์๋์ ๊ฐ์ด complete๋ฅผ ํด์ฃผ๋ฉด ๋๋ค!
    func fetchTestData() -> Observable<TestModel> {
        return Observable.create { observer -> Disposable in
            
            AF.request(NetworkManager.testURL)
                .validate(statusCode: 200..<300)
                .responseDecodable(of: TestModel.self) { response in
                    
                    switch response.result {
                    case .success(let success):
                        observer.onNext(success)
                        observer.onCompleted() // ์ด๋ ๊ฒ!!
                    case .failure(let error):
                        observer.onError(error)
                    }
                }
            
            return Disposables.create()
        }
    }complete๋ฅผ ๋ง๋๋ฉด ์คํธ๋ฆผ์ dispose ๋๊ธฐ ๋๋ฌธ์ ์ด ๋ฌธ์ ๊ฐ ๊ฐ๋จํ๊ฒ ํด๊ฒฐ๋๋ค.
๊ทผ๋ฐ, ๋งค๋ฒ ๊ตฌํํ  ๋๋ง๋ค complete๋ฅผ ์์ฑํด์ฃผ์ด์ผํ๊ณ ,
dispose๊ฐ ์ ๋๋ก ๋๊ณ  ์๋์ง ํ์ธํ๊ธฐ ๋ฒ๊ฑฐ๋กญ๋ค๋ ์ ..!!!!
์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ฃผ๋๊ฒ ๋ฐ๋ก Single์ด๋ค!

์ ์ฝ๋๋ Sinlge์ ๊ตฌํ๋ถ ์ฝ๋์ด๋ค.
ํ์ํ ๋ถ๋ถ์ ๋ณด๋ฉด, ์ฑ๊ณต์ ํ  ๊ฒฝ์ฐ next ๋ค์์ complete๊ฐ ๊ตฌํ๋์ด ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
(ํ๋ํ๋ complete๋ฅผ ์ฑ๊ฒจ์ฃผ๋ ๊ฒ์ด ๊ท์ฐฎ์๋ ๊ฒ์ Single๋ก ํด๊ฒฐ ๊ฐ๋ฅํ๋ค๋ ๊ฒ!)
 
์๋ ์ฝ๋๋ Sinlge๋ก ๊ตฌํํ ์ฝ๋์ด๋ค.
    func fetchTestDataWithSingle() -> Single<TestModel> {
        return Single.create { observer -> Disposable in
            
            AF.request(NetworkManager.testURL)
                .validate(statusCode: 200..<300)
                .responseDecodable(of: JokeModel.self) { response in
                    
                    switch response.result {
                    case .success(let success):
                        observer(.success(success))
                    case .failure(let error):
                        observer(.failure(error))
                    }
                }
            
            return Disposables.create()
        }
    }์ด๋ ๊ฒ ๊ตฌํํ๋ฉด ๋ฐฉ์ถ ์ดํ์ ์คํธ๋ฆผ์ด dispose๋๋ค.
๊ทผ๋ฐ,,, ์ฌ๊ธฐ์ ๋ฌธ์ ์ ์ด ํ๋ ๋ ์๋ค!!!๐ก
๋ฐ๋ก error๊ฐ ๋ฐ์ํ์ ๊ฒฝ์ฐ์ด๋ค.
๋ฉ์๋ ํธ์ถํ๋ ํญ observable ๋ด์ ๋คํธ์ํฌ observable์ด ์๋๋ฐ,
ํญ observable์ ์ด์์๊ณ , ๋คํธ์ํฌ๊ฐ error๋ฅผ ๋ณด๋ด๋ฉด ๊ทธ ํญ๋ ์ํฅ์ ๋ฐ๋๋ค.
๊ทธ๋ฐ๋ฐ ์ฐ๋ฆฌ๋ ์์ ์คํธ๋ฆผ์ด error๋ฅผ ๋ฐฉ์ถํ๋๋ผ๋ ๋ถ๋ชจ ์คํธ๋ฆผ์ด error๋ฅผ ๋ฐ์ง ์์
dispose๊ฐ ๋์ง ์๊ณ , ์คํธ๋ฆผ์ด ์ ์ง๋๋๋ก ๊ตฌํํด์ผํ๋ค.
์ด๋ป๊ฒ ํด์ผํ ๊น?๐ค
๋ฐ๋ก 
Single<Result>๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค!
์ด ๋ฐฉ๋ฒ์ ํ์ฉํ๋ฉด, error Handling๊ณผ ๋์์ ์คํธ๋ฆผ์ ์ ์งํ  ์ ์๋ค.

๋ด๋ถ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด,
success์ failure ๋ ๊ฐ์ง ์ผ์ด์ค๊ฐ ์๋ค.
Result ํ์
์ผ๋ก ๊ตฌํํ  ๊ฒฝ์ฐ
Sinlge์์ subscribe๊ฐ ๋๊ธฐ์ง ์๋๋ก!
์คํจ ์, success๋ฅผ ๋ฐฉ์ถํ๊ณ  ๊ทธ ์์ ๋ช
์ํด ๋์ Error๋ฅผ ๋ด์์ ๋ฐฉ์ถํ๋ ๊ฒ.
enum APIError: Error {
    case invalidURL
    case unknownResponse
    case statusError
}
์ด๋ ๊ฒ Error ํ์
์ APIError Enum์ ๋ง๋ค๊ณ ,
    func fetchTestDataWithSingleResultType() -> Single<Result<TestModel, APIError>> {
        return Single.create { single -> Disposable in
            AF.request(NetworkManager.testURL)
                .validate(statusCode: 200..<300)
                .responseDecodable(of: TestModel.self) { response in
                    
                    switch response.result {
                    case .success(let success):
                        single(.success(.success(success)))
                    case .failure(_):
                        single(.success(.failure(.invalidURL)))
                    }
                }
            
            return Disposables.create()
        }
    }
์ด๋ ๊ฒ failure์ ๊ฒฝ์ฐ์๋ Sinlge๋ก ๋ํํ์ฌ success๋ก ํด๋น Error๋ฅผ ๋ด์์ ๋ณด๋ด๋ฉด ๋๋ค.
failure์์ 
let statusCode = response.response?.statusCode
		switch statusCode {
        case 400:
             observer(.success(.failure(.missingRequiredValue)))
        case 402:
             observer(.success(.failure(.noSpacesAllowed)))
        case 409:
             observer(.success(.failure(.alreadySignedUp)))
        default:
             break
        }์ด๋ ๊ฒ ํ์ํ statusCode๋ฅผ Switch๋ฌธ์ ํตํด ๋ฐฉ์ถํ  ์๋ ์๋ค.
Result ํ์
์ผ๋ก ํธ๋ค๋งํ๋ ๋ฐฉ๋ฒ ์ด์ธ์๋ flatMap ๋ด๋ถ์์ catch๋ฌธ์ ํตํด ์ฒ๋ฆฌ๋ ๊ฐ๋ฅํ๋ค.
(์ด ๋ฐฉ๋ฒ์ ์ถํ์ ์ด์ด์ ์ ๋ฆฌํ  ์์ ์ด๋ค.)
'RxSwift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [RxSwift] BehaviorSubject, PublishSubject, ReplaySubject, AsyncSubject (0) | 2024.06.26 | 
|---|---|
| [RxSwift] Observable & Observer (just, of, from, create) (0) | 2024.06.24 |