observeOn(_ scheduler: ImmediateSchedulerType )

rxSwift의 scheduler는 stream 속의 연산들을 어느 스레드에서 동작하게 해 줄지 rxSwift에서 결정해주는 역할을 하고 있다.

observeOn() 오퍼레이터를 통해 결정해줄 수 있으며, 매개변수로 schedular를 입력받는다. observeOn() 오퍼레이터의 다음 연산부터 지정된 스레드로 연산을 수행한다.

@IBAction func exMap3() {
    Observable.just("800x600")
        .observeOn(ConcurrentDispatchQueueScheduler(qos: .default))    //ConcurrentDispatchQueueScheduler 동작
        .map { $0.replacingOccurrences(of: "x", with: "/") }    
        .map { "https://picsum.photos/\($0)/?random" }          
        .map { URL(string: $0) }                                
        .filter { $0 != nil }
        .map { $0! }                                            
        .map { try Data(contentsOf: $0) }                       
        .map { UIImage(data: $0) }                              
        .observeOn(MainScheduler.instance)    //MainScheduler 동작
        .subscribe(onNext: { image in
            self.imageView.image = image
        })
        .disposed(by: disposeBag)
}

url을 통해 이미지를 불러오는 함수다. 요청과 응답의 대기시간이 있기에, 스레드를 분리해서 작업해야 응답 대기시간 동안에 대기하는 동작을 막을 수 있다. 첫 번째 observeOn() 오퍼레이터를 통해서 concurrent 큐에서 요청 작업을 하게 된다. 응답에 대한 데이터를 UIImage 형태로 변환 후 이미지를 사용자에게 보여주기 위한 UI작업은 두 번째 observeOn( )을 통해 MainScheduler로 전환하여 작업하게 된다.


subscribeOn(_ scheduler: ImmediateSchedulerType )

observeOn() 오퍼레이터의 경우 Observable이 생성된 이후부터 적용할 수 있다. Observable이 생성되는 부분부터 특정 스레드를 지정하고 싶다면, subscribeOn() 오퍼레이터로 해결이 가능하다.

.subscribeOn(_ scheduler: ImmediateSchedulerType)
//Wraps the source sequence in order to run its subscription and unsubscription logic on the specified scheduler.
특정 스케줄러에서 구독 및 구독취소 로직을 실행하기 위해 소스 시퀀스(스트림)를 감쌉니다.

 

 

설명을 이해하기 전에 우선 Observable에 대해 알아두어야 할 점이 있다.

 

 

GitHub - ReactiveX/RxSwift: Reactive Programming in Swift

Reactive Programming in Swift. Contribute to ReactiveX/RxSwift development by creating an account on GitHub.

github.com

Observable just defines how the sequence is generated and what parameters are used for element generation. Sequence generation starts when subscribe method is called.

rx의 공식문서에 따르면 Observable은 subscribe()가 호출되는 순간에 생성된다. subscribe()가 호출되기 전까지는 스트림 생성에 관한 요소들을 정의하는 것일 뿐, 실제로 Observable은 생성된 상태가 아닌 것이다.

 

요약을 하자면 Observable의 생성은 subscribe()가 호출되는 순간이고, Observable이 어떤 스레드에서 생성될지를 결정해주는 것이 바로 subscribeOn(_ scheduler) 오퍼레이터라는 것이다. 

subscribeOn(_ scheduler) -> Observable을 생성할 스레드를 지정
ObserveOn(_ shcedular) -> Observable이 생성된 이후 스레드 변경

 

let observable = Observable<Int>.create { observer in
    observer.onNext(1)
    observer.onNext(2)
                                                
    print("[.create] in mainThread? \(Thread.isMainThread)")

    observer.onCompleted()
    return Disposables.create()
}
.observeOn(MainScheduler.instance)
.map{ next -> Int in
    print("[.map]",next, "in mainThread? \(Thread.isMainThread)")
    return next*2
}

print("[subscribe start]")    //구독시작
observable
    .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
    .subscribe(onNext: { event in
    print("[.subscribe] onNext \(event) in mainThread? \(Thread.isMainThread)")
}, onDisposed: {(
    print("[.disposed] in mainThread? \(Thread.isMainThread) \n---------------------------")
)})
.disposed(by: disposeBag)

//[subscribe start]
//[.map] 1 in mainThread? true
//[.create] in mainThread? false
//[.subscribe] onNext 2 in mainThread? true
//[.map] 2 in mainThread? true
//[.subscribe] onNext 4 in mainThread? true
//[.disposed] in mainThread? true 
//---------------------------
//[subscribe start]
//[.map] 1 in mainThread? true
//[.subscribe] onNext 2 in mainThread? true
//[.map] 2 in mainThread? true
//[.subscribe] onNext 4 in mainThread? true
//[.create] in mainThread? false
//[.disposed] in mainThread? true 
//---------------------------

두 번 수행한 출력 결과를 보면 알 수 있듯이 create 영역의 출력은 subscribe() 오퍼레이터가 호출된 이후에 등장하며, concurrent Queue에서 작업이 실행되기 때문에 mainThread 와의 출력 순서를 보장하지 않는다. 반면 ObserveOn() 오퍼레이터 이후에는 mainThread로 변경되어 동작하기에 출력 순서가 보장되는 모습을 확인할 수 있다.

 

subscribeOn()의 경우 다음 라인부터 영향을 주는 observeOn()과 달리 스트림 속 아무 라인에 적어놓아도 관계없이 적용되며, 여러 번 작성하더라도, 가장 첫 번째 subscribeOn()으로만 적용이 된다고 한다.

 

참고 영상 및 블로그

[유튜브] 곰튀김 rxswift 4시간에 끝내기 - 8    

[블로그] 이승연 님 글 [RxSwift] Scheduler 제대로 알아보기

'iOS > RxSwift' 카테고리의 다른 글

next, error, complete  (0) 2022.08.19
operator  (0) 2022.07.21
subscribe, dispose  (0) 2022.06.15
Observable stream  (0) 2022.06.08
ReactiveX  (0) 2022.05.30

subscribe( on: (Event<type>) -> Void)

Rx의 여러 오퍼레이터로 이루어진 스트림의 마지막엔 subscribe()을 통해 가공된 데이터를 확인하게 된다. 여기서 Event<타입>형태의 데이터가 들어오게 되고, Event는 next, error, completed 3가지의 값을 가질 수 있다. 

Observable.from(["RxSwift", "In", "4", "Hours"])
    .subscribe({event in
        switch event{
        case .next:
            break
        case .error:
            break
        case .completed:
            break
        }
    })
    .disposed(by: disposeBag)

next

스트림에서 넘어온 자료가 있는 경우, next에 해당한다.

Observable.from(["RxSwift", "In", "4", "Hours"])
    .subscribe({event in
        switch event{
        case .next(let str):
            print("next: \(str)")    //자료 출력
            break
        case .error(let err):
            break
        case .completed:
            break
        }
    })
    .disposed(by: disposeBag)
    
// next: RxSwift
// next: In
// next: 4
// next: Hours

error

스트림에서 에러가 발생한 경우, error의 값을 가지게 된다.

Observable.from(["RxSwift", "In", "4", "Hours"])
    .single()    //하나의 데이터만 들어와야함.
    .subscribe({event in
        switch event{
        case .next(let str):
            print("next: \(str)")
            break
        case .error(let err):
            print("err: \(err.localizedDescription)")
            break
        case .completed:
            print("completed")
            break
        }
    })
    .disposed(by: disposeBag)
    
// next: RxSwift
// err: The operation couldn’t be completed. (RxSwift.RxError error 5.)

 

single()오퍼레이터의 경우 하나의 데이터만 입력을 받아야 하는데, 스트림의 앞쪽에 위치한 from() 오퍼레이터의 경우 이벤트가 여러번 발생되기 때문에 에러가 발생하게된다. 이렇게 고의로 에러를 발생시켜보면 에러의 내용이 출력되는 모습을 확인할 수 있고, completed 될 수 없다고 나온다. 즉 에러가 발생하면 completed 상태에 들어가지 않고 스트림은 마무리된다.


completed

해당 스트림이 에러없이 모든 이벤트들을 내보냈을경우 completed 값을 가지게 된다.

Observable.from(["RxSwift", "In", "4", "Hours"])
    .subscribe({event in
        switch event{
        case .next(let str):
            print("next: \(str)")
            break
        case .error(let err):
            print("err: \(err.localizedDescription)")
            break
        case .completed:
            print("completed")
            break
        }
    })
    .disposed(by: disposeBag)
    
// next: RxSwift
// next: In
// next: 4
// next: Hours
// completed

해당 코드를 실행하게되면 from에 의해 생성된 4개의 자료들이 출력되고, 마지막으로 "completed"가 출력되는 모습을 볼 수 있다. 

즉 에러가 발생하지 않는다면, 발생되는 모든 이벤트를 처리하고 마지막으로 completed 상태가 되면서 마무리가 된다.


subscribe(onNext:  , onError: , onCompleted:  , onDisposed:  )

subscibe(_ on: )의 경우, switch문을 통해 event의 모든 조건에 대한 처리를 해주어야 했다면, subscribe(onNext:  ,onError:  ,onCompleted:  ,onDisposed:  )의 경우 원하는 경우의 분기만 골라서 작성이 가능하게 해주는 오퍼레이터이다.

또 다른 차이점은 onDisposed가 추가되었다는 점이다. 

Observable.from(["RxSwift", "In", "4", "Hours"])
    .subscribe(onNext: { str in
        print(str)
    })
    .disposed(by: disposeBag)
    
// RxSwift
// In
// 4
// Hours

모든 경우의 값에 대해 작성해야 하는 subscribe( _ on:  )과 달리 필요한 부분만 이벤트 처리하여 더 간결한 코드 작성이 가능하다.

Observable.from(["RxSwift", "In", "4", "Hours"])
    .single()
    .subscribe(onNext: { str in
        print(str)
    }, onError: { err in
        print(err.localizedDescription)
    }, onCompleted: {
        print("completed")
    }, onDisposed: {
        print("disposed")
    })
    .disposed(by: disposeBag)
    
// RxSwift
// The operation couldn’t be completed. (RxSwift.RxError error 5.)
// disposed
Observable.from(["RxSwift", "In", "4", "Hours"])
    .subscribe(onNext: { str in
        print(str)
    }, onError: { err in
        print(err.localizedDescription)
    }, onCompleted: {
        print("completed")
    }, onDisposed: {
        print("disposed")
    })
    .disposed(by: disposeBag)
    
// RxSwift
// In
// 4
// Hours
// completed
// disposed

예제 코드에서 알 수 있듯, 스트림은 마지막으로 disposed 되면서 마무리된다. 강의에서 말하길, 많은 개발자들이 흔히 하는 실수로 프로세스의 종료처리를 onCompleted 부분에서 작성하게 되는데, 이렇게 되면 에러 발생시에 onCompleted 상태에 들어가지 않게 되어 프로세스의 종료처리가 일어나지 않게 된다. 따라서 프로세스의 마무리 처리를 하려면 onDisposed 부분에서 작성해야 한다.

 

[참고영상]

[유튜브] 곰튀김 RxSwift 4시간에 끝내기 - 7

'iOS > RxSwift' 카테고리의 다른 글

scheduler  (0) 2022.08.31
operator  (0) 2022.07.21
subscribe, dispose  (0) 2022.06.15
Observable stream  (0) 2022.06.08
ReactiveX  (0) 2022.05.30

operator

Observable이 수행하는 메소드. Observable에서 파생되는 스트림을 구성하는 rxSwift의 핵심요소라고 할 수 있다. 

Observable에는 수행가능한 여러가지 operator가 있는데, 그중 대표적인것들에 대해서 적어보려고 한다. 

 

just()

static func just(_ element: [String]) -> Observable<[String]>
//returns an Observable sequence that contains a single element
Observable.just(_ element: )

입력 요소에 대해 그대로 반환되는 연산자이다. 예시를 통해 보자. 

@IBAction func exJust1() {
    Observable.just("Hello World")
        .subscribe(onNext: { str in
            print(str)
        })
        .disposed(by: disposeBag)
}
//Hello World!    출력

@IBAction func exJust2() {
    Observable.just(["Hello", "World"])
        .subscribe(onNext: { arr in
            print(arr)
        })
        .disposed(by: disposeBag)
}
//["Hello","World"]    출력

배열을 넣어도 배열이 통째로 출력되는 모습을 볼 수 있다.


from()

public static func from(_ array: [Element]) -> Observable<Element>
//Converts an array to an observable sequence.
Observable.from(_ array: [_])

배열의 원소들을 Observable의 형태로 리턴해준다.

@IBAction func exFrom1() {
    Observable
        .from(["RxSwift", "In", "4", "Hours"])
        .subscribe(onNext: { str in
            print(str)
        })
        .disposed(by: disposeBag)
}
//RxSwift
//In
//4
//Hours 출력

from을 통해 나오는 Observable<String>형태의 원소들이 subscribe(OnNext: )부분에서 출력이 된다.


map()

func map<Result>(_ transform: @escaping (String) throws -> Result) -> Observable<Result>
//Projects each element of an observable sequence into a new form.

swift에서의 map()과 같은 동작을 하는 operator이다. Observable에서 생성되어 내려오는 데이터들에 closure에 적힌 동작에 따라 가공하여 리턴해준다. 

@IBAction func exMap1() {
    Observable.just("Hello")
        .map { str in "\(str) RxSwift" }
        .subscribe(onNext: { str in
            print(str)
        })
        .disposed(by: disposeBag)
}
//Hello RxSwift 출력

@IBAction func exMap2() {
    Observable.from(["RxSwift", "ReactiveX"])
        .map { $0.count }
        .subscribe(onNext: { str in
            print(str)
        })
        .disposed(by: disposeBag)
}
//7
//9 출력

아마도 가장 많이 쓰게될 operator가 아닐까 생각된다.


filter()

func filter(_ predicate: @escaping (Int) throws -> Bool) -> Observable<Int>
//Filters the elements of an observable sequence based on a predicate.

swift의 filter()함수와 동일하게 동작하는 오퍼레이터이다. 서술한 조건에 맞는 경우에만 Observable을 내보낸다.

@IBAction func exFilter() {
    Observable.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
        .filter { $0 % 2 == 0 }
        .subscribe(onNext: { n in
            print(n)
        })
        .disposed(by: disposeBag)
}
//2
//4
//6
//8
//10 출력

배열요소들 중에 짝수인 요소만 출력된다.


stream

우리는 이러한 여러가지 오퍼레이터들을 통해 Observable을 가공하여 비동기 프로그래밍을 할 수 있게 된다. 앞의 글에서도 설명했지만 이러한 가공의 과정을 stream이라 부르기로 했고, 이러한 Observable을 통한 stream을 통해 비동기 프로그래밍을 할 수 있게 해주는 것이 RxSwift이다.

@IBAction func exMap3() {
    Observable.just("800x600")
        .map { $0.replacingOccurrences(of: "x", with: "/") }    //"800/600"
        .map { "https://picsum.photos/\($0)/?random" }          //"https://picsum.photos/\800/600/?random"
        .map { URL(string: $0) }                                //URL?
        .filter { $0 != nil }
        .map { $0! }                                            //URL!
        .map { try Data(contentsOf: $0) }                       //Data
        .map { UIImage(data: $0) }                              //UIImage?
        .subscribe(onNext: { image in
            self.imageView.image = image
        })
        .disposed(by: disposeBag)
}

Observable이 여러가지 오퍼레이터를 통해 어떤식으로 변화하는지 주석으로 적어놓았다. 

 

이외에도 정말 많은 오퍼레이터들이 있으며, 사용처에 따라 알맞은 오퍼레이터를 사용하면 된다. 각 오퍼레이터에 대한 상세한 내용들도 홈페이지에서 열람 가능하다.

 

[참고영상]

[유튜브] 곰튀김 RxSwift 4시간에 끝내기 - 4

[유튜브] 곰튀김 RxSwift 4시간에 끝내기 - 5

'iOS > RxSwift' 카테고리의 다른 글

scheduler  (0) 2022.08.31
next, error, complete  (0) 2022.08.19
subscribe, dispose  (0) 2022.06.15
Observable stream  (0) 2022.06.08
ReactiveX  (0) 2022.05.30

subscribe

비동기 요청을 위한 stream을 생성하기 위해 Observable을 보면 여러가지 operator가 존재하는 걸 알 수 있는데, 그중 가장 중요한 subscribe()와 dispose()를 알아보자. 

지난번 Rxswift로 작성된 코드를 보면 Subscribe()와 disposed()로 마무리가 되어있는걸 확인 할 수 있다. 

var disposebag = DisposeBag()
@IBAction func onLoadRxAsync(_ sender: Any) {
    Observable.just(self.IMAGE_URL)
        .subscribe(on: ConcurrentDispatchQueueScheduler(qos: .default))
        .map{self.loadImage(from: $0)}
        .observe(on: MainScheduler.instance)
        .subscribe(onNext: { image in
            self.imageView.image = image
        })
        .disposed(by: disposebag)
}

그렇다면 subscribe는 무엇일까? 

func subscribe(onNext: ((_) -> Void)? = nil,
	onError: ((Error) -> Void)? = nil, 
	onCompleted: (() -> Void)? = nil, 
	onDisposed: (() -> Void)? = nil) -> Disposable
The Subscribe operator is the glue that connects an observer to an Observable. In order for an observer to see the items being emitted by an Observable, or to receive error or completed notifications from the Observable, it must first subscribe to that Observable with this operator.

Observerble과 Observer사이를 연결해주는 operator라고 한다. Observer와 연결하게 되면서 Observable이 아이템을 방출하거나, 에러 혹은 완료를 알림받게 된다. 즉 Observerble이 발생시키는 이벤트들을 확인할 수 있는 operator인 것이다. 

 

Disposable

그렇다면 subscribe()의 리턴값인 Disposable은 무엇일까? 

Observable에서 구독(subscribe)받는 이벤트들은 처분(dispose)할 시점이 반드시 오게된다. 즉 Disposable은 dispose가능한 자료형의 형태로 보면된다. (먼저 구독을 해야 처분을 받을수 있으니)

이 얘기는 subscribe를 통해 작업이 일어나는 도중, 임의의 시점에 강제로 처분(dispose)이 가능하다는 얘기이다.

@IBAction func onLoadRxAsync(_ sender: Any) {
    self.imageView.image = nil
        
    let disposable = Observable.just(self.IMAGE_URL)
        .subscribe(on: ConcurrentDispatchQueueScheduler(qos: .default))
        .map{self.loadImage(from: $0)}
        .observe(on: MainScheduler.instance)
        .subscribe(onNext: { image in
            self.imageView.image = image
        })
}

즉 예시와 같이 처분가능한(disposable)형태로 담아둘수 있다는 이야기이고, 이를 전역변수에 담아두게된다면 다른 함수호출을 통해 요청취소가 가능하다는 이야기이다. 

var disposable: Disposable?
@IBAction func onLoadRxAsync(_ sender: Any) {
    self.imageView.image = nil
        
    disposable = Observable.just(self.IMAGE_URL)
        .subscribe(on: ConcurrentDispatchQueueScheduler(qos: .default))
        .map{self.loadImage(from: $0)}
        .observe(on: MainScheduler.instance)
        .subscribe(onNext: { image in
            self.imageView.image = image
        })
}

 

Disposebag()

여러개의 Disposable을 처리하기 위해 Disposablebag을 활용할 수 있다.

var disposebag = DisposeBag()
    
@IBAction func onLoadRxAsync(_ sender: Any) {
    self.imageView.image = nil
        
    let disposable = Observable.just(self.IMAGE_URL)
        .subscribe(on: ConcurrentDispatchQueueScheduler(qos: .default))
        .map{self.loadImage(from: $0)}
        .observe(on: MainScheduler.instance)
        .subscribe(onNext: { image in
            self.imageView.image = image
        })
    disposebag.insert(disposable)
}

insert메소드를 통해 추가가 가능하며, 예시처럼 단일형태의 Disposable도 가능하지만, 배열형태나, 범위의 형태로도 추가 가능하다.

추가로 같은 동작을 조금 더 간결하게 작성하는 것도 가능하다. disposable에 속해있는 disposed(by:) 메소드를 사용하면 자기자신을 Disposablebag에 추가한다.

func disposed(by bag: DisposeBag){
    //Adds self to bag
    //bag: DisposeBag to add self to.
}
var disposebag = DisposeBag()
    
@IBAction func onLoadRxAsync(_ sender: Any) {
    self.imageView.image = nil
        
    Observable.just(self.IMAGE_URL)
        .subscribe(on: ConcurrentDispatchQueueScheduler(qos: .default))
        .map{self.loadImage(from: $0)}
        .observe(on: MainScheduler.instance)
        .subscribe(onNext: { image in
            self.imageView.image = image
        })
        .disposed(by: disposebag)
}

그렇게 처음에 적힌 예시코드와 같은 형태로 완성이 된다. 

var disposebag = DisposeBag()
    
@IBAction func onLoadRxAsync(_ sender: Any) {
    self.imageView.image = nil
        
    Observable.just(self.IMAGE_URL)
        .subscribe(on: ConcurrentDispatchQueueScheduler(qos: .default))
        .map{self.loadImage(from: $0)}
        .observe(on: MainScheduler.instance)
        .subscribe(onNext: { image in
            self.imageView.image = image
        })
        .disposed(by: disposebag)
}
@IBAction func cancelRxAsync(_ sender: Any) {
    disposebag = DisposeBag()
}

Disposebag을 사용하여 작업을 취소하는 방법은 간단하다. 원하는 시점에 Disposebag을 초기화만 해주면 된다. 

취소버튼을 통해 작업을 취소하는 모습을 확인 할 수 있다.

 

참고영상

[유튜브] 곰튀김 RxSwift 4시간에 끝내기 - 3

 

'iOS > RxSwift' 카테고리의 다른 글

scheduler  (0) 2022.08.31
next, error, complete  (0) 2022.08.19
operator  (0) 2022.07.21
Observable stream  (0) 2022.06.08
ReactiveX  (0) 2022.05.30

 

sync, async

Rx에서 가장 중요한 개념인 Observable에 대해 이야기하기전에 우선 동기(sync)와 비동기(async) 프로그래밍에 대해 간단하게 설명하고자 한다. 

private func loadImage(from imageUrl: String) -> UIImage? {
        guard let url = URL(string: imageUrl) else { return nil }
        guard let data = try? Data(contentsOf: url) else { return nil }
        
        let image = UIImage(data: data)
        return image
}

 

여기 URL요청을 통해 이미지를 불러와 UIImage 형태로 리턴해주는 함수가 있다. 동기방식으로 처리할경우 이미지를 요청하고 요청에 대한 응답을 받아야만 다음처리가 가능해진다. 이에 반해 비동기방식은 요청을 하고난 후 응답을 받기 전에 다음 작업들을 이어서 처리하다가 요청에 대한 응답이 수신되면 응답에 대한 처리를 마저 하게되는 방식이다.  동기방식은 요청에 대한 응답이 올때 까지 대기. 비동기방식은 요청에 대한 응답을 대기하지 않고 다음작업들을 처리. 차이라고 보면 된다. 아래의 코드를 통해 두 방법의 차이를 확인해보자.

 

//동기방식
@IBAction func onLoadSync(_ sender: Any) {
    let image = loadImage(from: IMAGE_URL)
    imageView.image = image
}

//비동기방식
@IBAction func onLoadAsync(_ sender: Any) {
    DispatchQueue.global().async {
        let image = self.loadImage(from: self.IMAGE_URL)
        DispatchQueue.main.async {
            self.imageView.image = image
        }
    }
}

 

우측의 시간카운터를 보면 동기방식과 비동기방식의 차이를 확인할 수 있다. 

 

동기방식으로 요청을 처리할경우, 응답을 받을 때까지 아무런 작업을 할 수 없게된다. 이렇게 동기방식으로 작성된 앱은 사용자에게 큰 불편을 유발하게 된다. 하지만 위의 예시처럼 비동기 방식으로 작성하게되면 코드의 가독성이 떨어진다.

Observable stream

다음은 RxSwift로 작성된 비동기 코드를 보자.

var disposebag = DisposeBag()
@IBAction func onLoadRxAsync(_ sender: Any) {
    Observable.just(self.IMAGE_URL)
        .subscribe(on: ConcurrentDispatchQueueScheduler(qos: .default))
        .map{self.loadImage(from: $0)}
        .observe(on: MainScheduler.instance)
        .subscribe(onNext: { image in
            self.imageView.image = image
        })
        .disposed(by: disposebag)
}

처음 Rx코드를 보았을때 오히려 코드라인이 늘어나서 당황했다. 하지만 코드의 흐름을 보면 들여쓰기와 중괄호가 아닌 Observable에서 시작되는 메소드들로 흘러가는 모양을 볼 수 있고, 마지막 subscribe부분에서 UI처리를 하는 모습을 볼 수 있다. 이러한 형태가 바로 이전글에 Rx의 정의를 이해할 수 있는 좋은 예시이다.

An API for asynchronous programming
with "observable streams"

Observable에서 파생되는 stream(흐름)을 통한 비동기 프로그래밍 API. 즉 Observable에서 시작되는 반환값이 여러가지 Operator, Subject, Scheduler들로 이루어진 흐름을 통해 비동기 프로그래밍을 할 수 있는 API라고 할 수 있다. 이것이 Rx의 정의이다.

 

참고영상

[유튜브] 곰튀김 RxSwift 4시간에 끝내기 - 2

'iOS > RxSwift' 카테고리의 다른 글

scheduler  (0) 2022.08.31
next, error, complete  (0) 2022.08.19
operator  (0) 2022.07.21
subscribe, dispose  (0) 2022.06.15
ReactiveX  (0) 2022.05.30

 

 

RxSwfit. 여러 개발 블로그를 돌아다니다보면, 기술스택에 RxSwift가 적혀있는 것을 심심치않게 확인해 볼 수 있다. 볼때마다 저건 무엇일까 라는 의문만 남긴채 지나갔지만, 이번기회에 유튜브에서 곰튀김님의 "RxSwift 4시간에 끝내기" 영상을 보면서 공부한 내용을 적으려고 한다. 

What is Rx?

RxSwift는 ReactiveX의 Swift버전이라고 생각하면 된다. 그렇다면 reactiveX는 무엇일까? 공식 홈페이지에 들어가면 바로 확인이 가능하다.

An API for asynchronous programming
with observable streams

API이다. 그것도 비동기 프로그래밍을 위한. 시각적인 스트림을 통해서. 처음에는 스트림이 무엇인지 몰라 감이 안잡혔지만, 어찌되었든 결론은 ReactiveX는 비동기 프로그래밍에 사용되는 API라는 것을 알게 되었다. 

ReactiveX(이하 Rx)는 MS에서 모종의 프로젝트에 적용하기 위해 개발이 되었고, Rx를 통해 프로젝트를 진행해보니 좋았다는 피드백을 통해 여러가지 언어들에 맞게 변형되어 사용되게 된다. 홈페이지에 보면 C, java, python부터 시작하여 현대에 쓰이는 많은 언어들을 지원하는 모습을 확인 할 수 있다.

What is in Rx?

Rx에는 크게 다섯가지 요소가 있다. Observable, Operators, Scheduler, Subject, Single 이다. 서론 글을 짧게 마치고, 각 요소들에 대한 설명을 다음 글부터 이어가도록 하겠다.

 

참고영상

[유튜브] 곰튀김 RxSwift 4시간에 끝내기 - 1

'iOS > RxSwift' 카테고리의 다른 글

scheduler  (0) 2022.08.31
next, error, complete  (0) 2022.08.19
operator  (0) 2022.07.21
subscribe, dispose  (0) 2022.06.15
Observable stream  (0) 2022.06.08

+ Recent posts