KoreaMango 나무

[iOS] RxSwift - 기본 문법 정리 본문

iOS/RxSwift

[iOS] RxSwift - 기본 문법 정리

KoreaMango 2022. 7. 23. 15:45

⭐️ Observable

1️⃣ Observable

Reactive X에는 옵저버가 있다.

이 옵저버는 Observable을 구독해서 지켜본다.

Observable이 배출하는 하나 또는 연속된 항목에 옵저버는 반응한다.

이러한 패턴은 동시성 연산을 가능하게 한다.

그 이유는!

Observable이 객체를 배출할 때까지 그 시점을 감시하는 관찰자를 옵저버에 두고,

observable이 객체를 배출하면 관찰자는 옵저버에게 알림을 준다.

위 내용을 마블 다이어 그램으로 요약하면 다음과 같다. (직역 주의)

  1. 이것은 타임라인이다. / Observable 의 / 시간은 왼쪽에서 오른쪽으로 간다.
  2. 이것은 아이템들이다. / 생성된 / Observable에 의해
  3. 이 수직선은 나타낸다. / Observable이 성공적으로 완수했다는 것을.
  4. 이 점선과 이 박스는 나타낸다. / 변환은 적용된다. / Observable 에 / 박스안에 있는 텍스트는 보여준다. / 변환의 네이처를
  5. 만약 어떤 이유로 인해 Observable 이 비정상적으로 종료된다면 / 에러와 함께 / 수직선은 X로 대체된다.
  6. 이 Observable은 / 변환의 결과이다.

 

2️⃣ 옵저버 생성

ReactiveX 는 기본적으로 비동기와 병렬로 메소드를 호출하지만, Reactive가 아닌 일반적인 메서드 호출은 대개 다음과 같은 흐름으로 진행된다.

// 1. 메서드를 호출한다.
// 2. 메서드가 리턴한 값을 변수에 저장한다.
// 3. 결과 값을 가진 변수를 통해 필요한 연산을 처리한다.

returnVal = someMethod(itsParameters) // 메서드 호출 및 변수에 저장
// 이후 returnVal을 통해 필요한 작업을 진행한다

하지만 비동기 모델에서는 아래와 같은 흐름대로 코드가 실행된다.

// 1. 비동기 메소드 호출로 결과 리턴받고 필요한 동작을 처리하는 메서드를 정의한다. 
//    이 메서드는 옵저버의 일부가 된다.
// 2. Observable로 비동기 호출을 정의한다.
// 3. 구독을 통해 옵저버를 Observable 객체에 연결 시킨다.(또한 동시에 Observable의 동작을 초기화       
//    한다.)
// 4. 필요한 코드를 계속 구현한다. 메서드 호출로 결과가 리턴될 때마다, 옵저버의 메서드는 리턴 값 또는
//    (Observable이 배출하는) 항목들을 사용해서 연산을 시작한다.

// Observable을 정의한다.
Observable.just()
// 옵저버가 Observable을 구독한다.
.subscribe(onNext: { str in
// subscribe에 정의되어있는 옵저버의 onNext 핸들러를 사용한다.
// 코드 구현
})

 

3️⃣ onNext, onCompleted and onError

onNext : Observable은 새로운 항목들을 배출할 때마다 이 메서드를 호출한다.

onError : Observable은 오류가 발생할 경우 이 메서드를 호출한다.

onCompleted : 오류가 발생하지 않았다면 Observable은 마지막에 onNext를 호출한 후 이 메서드를 호출한다.

 

 

⭐️ Disposable

1️⃣ Dispose

disposable.dispose를 하면

실행되고 있는 Observable을 취소시킬 수 있다.

 

2️⃣ DisposeBag

disposeBag 을 초기화하면서 disposeBag을 지운다.

.dispose(by: disposeBag) 을 이용해서 마지막에 넣을 수 있다.

 

 

⭐️ Operators

1️⃣ Just

just()안에 있는 매개변수가 그대로 나오는 연산자

 

2️⃣ From

배열이 들어간 경우 : 배열에 있는 모든 요소를 한 번씩 뱉어냄

Stream 으로 뱉어낸다.

 

3️⃣ Map

고차함수에 있는 Map이랑 비슷함.

 

4️⃣ Filter

고차함수에 있는 Filter랑 비슷함.

 

9️⃣ 나머지 연산자

reactives.io의 document를 확인해보자.

뭘 써야 할지 모르겠으면 연산자 결정 트리를 확인해라.

연산자 리스트(알파벳순)에 있는 볼드체가 카테고리 목록에 나온 것들임.

 

 

⭐️ 마블 다이어그램

Operators 에서 연산자를 누르면 마블 다이어그램으로 넘어갈 수 있다.

구슬 : 데이터

화살표 : 스트림

화살표 쪽 작대기 : complete

파생되는 애들은 RxSwift에 많이 없음 RxJAVA를 봐야 함.

Rxmarbles.com 을 보면 다양한 연산을 확인할 수 있다.

 

 

⭐️ Subscribe - Next / Error / Completed

0️⃣ subscribe 와 next, error, completed 란?

Operators로 연산을 다하고 최종적으로 쓸 상황에선 마지막 스트림에 Subscribe를 사용한다.

다른 Operators는 리턴 값이 Stream(Observable)인데 Subscribe은 dispose 이다.

스트림은 Error가 나거나, Completed 되면 종료가 된다.

데이터를 전달받는 게 Next인 이유는 From인 경우 하나씩 전달하기 때문에 next이다.

 

1️⃣ subscribe()

Observable.just("Hello World")
.subscribe() // 그냥 사라짐

 

2️⃣ subscribe(on : Event<String>() -> Void)

Observable.just("Hello World")
.subscribe( event in 
	swift event { // Evnet 타입은 3가지 경우가 있다.
	case .next(let str):
		break
	case .error(let err):
		break
	case .completed:
		break
	}
}

 

3️⃣ subscribe(onNext : …, onError : …, onCompleted : …, onDisposed: …)

Observable.from(["Rx", "in", "4"])
	.subscribe(onNext : { s in 
			...
	}, onError: { err in 
			...
	}, onCompleted: {
			...
	}, onDisposed: { // disposed 된 경우에 실행함, 
			...
	})
	.disposed(by: disposeBag)
}

Error도 Dispose를 뱉어내고, Completed도 Dispose를 뱉어냅니다.

이걸 쓰는 경우는 switch 쓰기가 귀찮은 경우, 필요한 것만 사용하고 싶은 경우에 사용한다.

 

 

⭐️ Scheduler

0️⃣ 서론

스케줄러를 사용하지 않으면 앞에서 했던 것들이 다 메인 스레드에서 작동할 것이다.

그렇게 되면 UI가 멈추게 될 것이다.

메인 스레드가 아닌 콘커러시 스레드로 옮겨주기 위해 스케줄러를 사용한다.

 

1️⃣ observeOn()

Obsevable.just("800x600")
	.observeOn(ConcurrentDispatchQueueScheduler(qos: .default)) // 이 아래에 있는 코드는 전부다 Concurrent 스레드에서 돌아간다.
	.map{...}
	.map{...}
	.map{...}
	.map{...}
	.map{...}
	.observeOn(MainScheduler.instance) // 이 아래에는 main 스레드에서 돌아간다. 
	.subscribe() // 세팅하는 곳이 subscribe이니까 subscribe 전에 메인 스레드로 바꿔주야한다.
	.disposed(by: ... )

// qos 는 우선순위입니다 ^~^ 
// <https://tngusmiso.tistory.com/49>

 

2️⃣ subscribeOn

데이터 가져오는걸 Just에 넣는다면 ObserveOn이 Just에 닿을 수 없다.

그래서 첫 줄부터 스레드를 변경하고 싶다면 SubscribeOn을 사용한다.

SubscribeOn은 아무 데나 넣어도 상관없다.

왜냐하면 subscribe 쓰는 순간 전부다 subscribeOn으로 돌리겠다는 뜻이다.

Obsevable.just("800x600")
	.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .default))
	.map{...}
	.map{...}
	.map{...}
	.map{...}
	.map{...}
	.observeOn(MainScheduler.instance) // 이 아래에는 main 스레드에서 돌아간다. 
	.subscribe() // 세팅하는 곳이 subscribe이니까 subscribe 전에 메인 스레드로 바꿔주야한다.
	.disposed(by: ... )

 

3️⃣ 요약

기본적으로, Observable과 연산자 체인은 이처럼 스케줄러를 통해 동작하고 Subscribe 메서드가 호출되는 스레드를 사용해서 옵저버에게 알림을 보낸다. SubscribeOn 연산자는 다른 스케줄러를 지정해서 Observable이 처리해야 할 연산자들을 실행시킨다. 그리고, ObserveOn 연산자는 Observable이 옵저버에게 알림을 보낼 때 사용할 스케줄러를 명시한다. - ReactiveX.io

https://reactivex.io/documentation/ko/scheduler.html

그리고 Observable은 스트림이기 때문에 subscribeOn으로 첫 스케줄러를 정해줘도 이후 ObserveOn에 의해서 스케줄러가 변경될 수 있다.

 

4️⃣ 사이드 이펙트

함수 내에서 그치는 게 아니라 외부에 영향을 주는 것을 사이드 이펙트라고 하는데,,,

이 사이드 이펙트를 허용해주는 곳이 2개가 있다.

  1. Subscribe() : 이미지 뷰 연결하거나 등등…
  2. do() : 서브스크라입이랑 비슷한데 스트림에서 쓱 지나가면서 사용하는 느낌

 

 

Ref

https://www.youtube.com/watch?v=w5Qmie-GbiA&list=PL03rJBlpwTaAh5zfc8KWALc3ADgugJwjq&index=1

https://reactivex.io/documentation/ko/observable.html

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

[iOS] RxSwift - 응용해보기  (0) 2022.07.23