RxSwift

[RxSwift] Single

yeggrrr๐Ÿผ 2024. 8. 21. 12:58
728x90

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๋ฌธ์„ ํ†ตํ•ด ์ฒ˜๋ฆฌ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.
(์ด ๋ฐฉ๋ฒ•์€ ์ถ”ํ›„์— ์ด์–ด์„œ ์ •๋ฆฌํ•  ์˜ˆ์ •์ด๋‹ค.)






728x90

'RxSwift' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[RxSwift] BehaviorSubject, PublishSubject, ReplaySubject, AsyncSubject  (0) 2024.06.26
[RxSwift] Observable & Observer (just, of, from, create)  (0) 2024.06.24