RxSwift에 대해(1)

JinSeok Hong·2021년 7월 1일
0

RxSwift


RxSwift란?

An API for as asynchronous programming with observable streams.

즉 observable streams을 이용하여 비동기 프로그래밍을 하기 위한 API이다. 이게 무슨 말인가 싶을 수 있는데 하나씩 살펴보도록 하자.


비동기

모바일 개발은 하면서 비동기 방식은 정말 필수적이다. 만약 핸드폰에서 어떠한 데이터를 불러올때마다 화면이 멈춰버린다면 정말 최악일 것이다.
보통 서버에서 이미지, 동영상 등 큰 파일을 가져올 때 main thread에서 동기적으로 수행시키려할 때 이러한 문제가 발생한다.
이를 극복하기 위해 보통 Grand Central Dispatch (GCD)를 통해 멀티스레드를 이용하여 비동기 기법을 사용하곤 한다.


왜 RxSiwft를 쓰는가?

이미 비동기 프로그래밍을 하게 해주는 것들이 있음에도 불구하고 RxSwift를 쓰는 이유는 쉬운 사용성 때문일 것이다.
Observable한 객체의 형태로 비동기적 작업과 데이터 스트림을 쉽게 구성할 수 있고 복잡한 Call-back에서 벗어나도록 한다.
또한 Operator들을 이용하여 여러 연산들을 쉽게 처리하기도 한다.

우선 ReactiveX 공식 홈페이지를 가면 크게
Observable, Operators, Single, Subject, Scheduler 총 5개로 나누어 소개한다.

이 중 오늘은 Observable, Operators에 대해 알아보자.


Observable

RxSwift의 가장 기본이 되는 것이 Observable이다.
Observable에서 들어오는 데이터를 어떠한 메커니즘에 따라 줄세워서 순서대로 처리하는데 이러한 것을 stream이라고 한다.
처음 공부할 때 Observer와 Observerable이 헷갈렸는데 쉽게 이렇게 생각하면 될 것 같다.

Observable입장 : 해당 Event를 방출(emit)하여 Observer에게 전달하고 Observer에서 처리
Observer 입장 : Observerable을 구독(subscribe)하고 데이터를 받아 처리

물론 Observable은 관찰 가능한 상태이기 떄문에 비동기 처리 방식이 가능한 것이다.
subscribe는 operator들을 거치고 stream이 다 흐른 뒤 원했던 최종 값을 사용할 때 이용한다고 생각하고 handling 할 수 있는 방법은 크게 next, error complete 3가지 이다.

  • self.asObservable().subscribe(observer)

// MARK: - Observable 생성 1

let ob_just  = Observable<Int>.just(1) //하나의 요소를 포함하는 Sequence 생성
let ob_of1 = Observable.of(1,2,3) // type을 추론해 Sequence 생성
let ob_of2 = Observable.of([1,2,3]) // 단일요소인 Array 이용 가능
let ob_from = Observable.from([1,2,3]) // .from은 오직 Array 타입만 처리해서 사용 
let ob_range = Observable<Int>.range(start: 1, count: 10) //순차적인 요소를 갖는 Sequence 생성
 
// MARK: - Observable 생성 2

Observable<String>.create { o in
   o.onNext("create")
   o.onCompleted()
   o.onError(MyError.myerror)
   return Disposables.create() // 커스텀하게 생성 가능 
   
   }.subscribe(//addObserver와 비슷
   onNext: {n in print(n)},
   onError: {e in print(e)},
   onCompleted: {print("completed")},
   onDisposed: {print("disposed")}
   ).disposed(by: disposeBag)
}
   //onComplete, onError, dispose 부분 제거하면 memory leak

여기서 Disposable은 Observable의 명시적인 중단을 위해 사용되며 생성한 subscription들을 하나의 disposeBang에 넣어 효율적으로 사용해주면 좋을 거같다. memory leak 발생 문제를 해결해주기도 하는데 어차피 깜빡하고 안써도 경고를 주니 참고하고 있자!


Operators란?

쉽게 Observable을 생성하고 변형하고 합치는 등 다양하게 연산을 할 수 있도록 도와주는 역할을 하며 이것이 RxSwift를 강력하게 만들어준다고 생각한다.

굉장히 많은 operators들이 있는데 경우에 따라 어떤 것을 사용할지는 문서에서 잘 설명해주기 때문에 외우지는 않고 그때 필요한대로 찾아 사용하자.
-> Operators 종류

이제 몇 가지 Operators에 대해 알아볼텐데 혹시 Operators들의 흐름에 대해 알고 싶으면 이곳을 참고하면 좋을거같다.
-> Operators 다이어그램


just

  • 하나의 element를 observable로 만드는 역할
  • 넣으면 한번에 다음번으로 그대로 출력
func exJust1() {
	Observable.just("Hello World")
    	.subscribe(onNext: { str in
        	print(str)
       	})
        .disposed(by: disposeBag)//complete-> disposableBag에서 사라짐
}

// --- 출력 ---
Hello World
//배열을 넣는다면 배열 자체가 그대로 한번에 출력

from

  • array, dictionary, set 등 자료구조 형태를 observable sequence로 만드는 역할
  • 한 개씩 다음번으로 출력
  • of는 from과 비슷하지만 같은 타입의 여러개의 parameter받을 수 있다.
func exFrom1() {
	 Observable.from(["RxSwift", "In", "4", "Hours"])
	subscribe(onNext: { str in
     	 print(str)
	})
    	.disposed(by: disposeBag)
}

// --- 출력 ---
RxSwift
In
4
Hours

map

  • 위에서 내려온 데이터를 가공하는 역할
  • 전달되어 온 인자들을 매핑하여 출력
func exMap1() {
    print("\nexMap1()")
    Observable.just("Hello")
        .map { str in "\(str) RxSwift" }
        .subscribe(onNext: { str in
            print(str)
        })
        .disposed(by: disposeBag)
}

// --- 출력 ---
Hello RxSwift

filter

  • 위에서 내려온 데이터를 선별하는 역할
  • 필터해서 출력
func exFilter() {
    print("\nexFilter()")
    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

Range

  • 정해진 범위에 따른 Integer를 방출
let disposeBag = DisposeBag()

Observable.range(start: 1, count: 3).subscribe { 

    print($0) 
    
}.disposed(by: disposeBag)

// --- 출력 ---
// next(1)
// next(2)
// next(3)
// complete

Flatmap

  • 이전에 배운 map과 같은 Transforming Operators에요.
  • Observable안에 또 다른 Observable이 있는 경우 새로운 Observable를 만들 때 사용한다.
  • 여러 개의 Observable Sequence로 만들어진 하나의 Observable Sequence로 만들어 방출한다.

let disposeBag = DisposeBag()
let sequence1  = Observable<Int>.of(1,2)
let sequence2  = Observable<Int>.of(1,2)

let usingFlatMap = Observable.of(sequence1,sequence2)

usingFlatMap.flatMap{ 

    return $0 
    
}.subscribe(onNext:{

    print($0)
    
}).disposed(by: disposeBag)

// --- 출력 ---
// 1
// 2
// 1
// 2

마지막으로 지금까지 배운 것을 바탕으로 위 코드를 보자면
우선 어떠한 Observable의 streams(흐름)을 나타낸 것이다.
이 흐름 속에서 데이터는 가공되고 필러링 되고 있는데 주목할 점은
operator들이 main thread에서 동기적으로 작동하는 것을 비동기적으로 바꿔주기 위해 비교적 시간이 소요되는 .map{UIImage(data :$0)}
앞에 다른 스케줄러로 지정해주는 것이다.
-> .subscribeOn(~)
스케줄러의 최소 단위는 thread이기 때문에 multi-thread로 비동기적인 실행이 가능해지는 것이다.

다음에는 Scheduler, Single, Subject에 대해 공부해보자!

0개의 댓글