기어가더라도 제대로
RxSwift 용어 정리 -3- (share, withUnretained) 본문
참고 : https://jusung.github.io/shareReplay/ (너무 좋습니다.)
위 블로그 내용 이해하기 위해 필기본입니다. 위에 링크를 보세요.
[RxSwift] Share(replay:)
anObservable.share(replay:1) 같은 코드를 보신적 있으실 겁니다. Share 연산자는 언제 써야하는 걸까요?
jusung.github.io
1. RxSwift Subscribe()
Observable 은 선언해 놓아도, Subscribe() 되기 전에는 이벤트를 방출하지 않는다. 이는 Observable 에 아무리 많은 연산자를 걸어놓아도, subscribe() 가 호출되기 전까진 아무 동작도 하지 않는다는 뜻이다.
좀더 정교하게 말하면 Observable 은 subscribe 될 때마다 create 클로저를 호출해 Observable을 생성합니다.
Observable 을 subscribe 할 때마다 새로운 Observable 시퀀스가 생성된다.
2. Share()
bind(to:) 는 subscribe() 의 일종인데, subscribe() 가 실행할 수 있는 onEvent의 종류는 3가지(onNext(), onCompleted(), onError) 인 반면에, bind(to:) 는 onNext() 하나의 이벤트만 다룰 수 있다. 결국 bind(to) 를 하면 subscribe().onNext(to:) 를 한 것과 같은 효과가 나는데, subscribe를 할 때마다 새로운 Observable 시퀀스가 생성된다는 말은 API 요청을 할 경우가 있다면 subscribe() 횟수만큼 요청을 한다는 이야기이다. 이 때 share() 를 사용하면 그런 일을 방지 할 수 있다.
- share()는 subscribe()가 처음 호출될 때 (Subscriptoin횟수가 0 -> 1 일때)만 Subscription을 생성
- 두번째 세번째로 subscribe()가 호출되면 새로운 Subscription을 생성하는 것 대신 이미 만들어진 Subscription을 이후 subscribe()를 호출한 곳에 공유해 사용
- share() 에 subscribe() 한 Subscription 이 모두 disposed 되면 share() 는 공유했던 Subscription 을 dispose 시킨다.
- 이후 다른 subscribe() 가 호출되면 share() 는 새로운 subscription 을 생성한다.
Replay
share(replay: ) 에 들어가는 인자를 뜻한다. 이는 buffer 의 크기이다. 버퍼는 item 이 담길 수 있는 메모리 주소의 크기라고 보면 좋다.
- 다른 시퀀스에서 share() 된 Observable 을 구독했을 때
- 가장 최근 방출했던 아이템을 버퍼의 크기만큼
- 새로운 구독 시퀀스에 전달
public func share(replay: Int = 0, scope: SubjectLifetimeScope = .whileConnected)
share() 의 정의이다. replay 는 위에서 다뤘고, scope 는 buffer 의 생명주기에 관한 인자입니다. 기본으로 .whileConnected 가 들어갑니다.
buffer 생명주기 정책 2가지
- .forever: subscription 이 0 이 되더라도 버퍼가 유지된다.
- 그래서 새로운 Subscription 은 subscribe() 를 하면 마지막에 버퍼에 남아있던 replay 개수 만큼의 값을 수신하게 됩니다.
- .whileConnected : 1개 이상의 subscriber 가 존재하는 동안만 버퍼가 유지
- subscription 이 0 이 되었다가 새로운 subscription 이 등록되면 새값을 요청해 수신하게 됩니다.
share() 는 속에선 어떨까?
사실 Rx 공홈에서 Share 항목을 검색해서 찾아들어가면 바로 refCount 항목으로 이동합니다.
사실은 이렇습니다. anObservable.share() 는 anObserable.publish().refCount() 입니다.
- publish() : 이 연산자는 보통의 Observable 을 ConnectableObservable 로 변환해줍니다.
- ConnectableObservable : subscriber 가 있어도 해당 Observable 의 connect() 메서드를 호출하기 전까지는 아이템을 방출 하지 않습니다.
- refcount() : ConnectableObservable 에 Connect와 Disconnect를 자동으로 담당하고, ConnectableObservable 을 보통의 Observable 처럼 사용할 수 있게 해줍니다. Subscription count를 계속 세고 있다가 Subscription 의 개수가 0 -> 1 개가 되는 시점에 connect() 를 수행하고, subscription 이 0 이되면 disconnect() 를 수행합니다.
withUnretained()
비동기 콜백 핸들러를 사용할 때 클로저로 되어 있어서 자기 자신 객체를 찾게 될 일이 있을 경우, self 라는 키워드를 사용한다. 근데 이렇게 self 를 사용할 경우 메모리 누수의 위험이 있어서 보통은
이런 식으로 사용을 한다. 이걸 rx swift 에서 깔끔하게 정리하기 위해서 withUnretained() 라는 오퍼레이터를 준비해주었다.
사용법
'Swift - 기초' 카테고리의 다른 글
[1일차] 100일의 SwiftUI - 스트링, 숫자, Decimal (2) | 2022.09.27 |
---|---|
Swift Package Manager 기초 (1) | 2022.05.28 |
RxSwift 용어 정리 - 2 - (0) | 2022.05.12 |
RxSwift 용어 정리 - 1 - (0) | 2022.05.09 |
객체간 데이터 전달하는 방법 4가지 (0) | 2022.05.08 |