[RxSwift] 3. Observable - Subscription, Dispose, DisposeBag

Hoojeong Kim·2022년 9월 1일
0
post-thumbnail

지난 게시글에서 Obsevable에 대해 다음과 같이 정리했다.

  • Rx의 심장.. ✨
  • Observable = Observable Sequence = Sequence
  • 비동기적(asynchronous)
  • Observable은 일정 기간 동안 계속해서 이벤트를 생성 (emit)
  • marble diagram: 시간의 흐름에 따라서 값을 표시하는 방식

그리고 이러한 생명주기를 갖는다.

  • onNext : Observable은 어떤 구성요소를 가지는 next 이벤트를 계속해서 방출할 수 있다.
  • onError : Observable은 error 이벤트를 방출하여 완전 종료될 수 있다.
  • onCompleted : Observable은 complete 이벤트를 방출하여 완전 종료 될 수 있다.

이번 시간에는 Observable의 사용법(?)에 대해 알아보자.


Observable 사용하기

Observable은 다음과 같은 방식으로 선언할 수 있다.

Observable<타입>.연산자

다양한 연산자를 사용해 여러 동작들을 수행할 수 있다.
이때 타입을 추론할 수 있기 때문에, 타입을 정의하지 않아도 된다.


💡 이벤트가 방출되었는지 확인하기 위해서는 어떻게 해야할까?

이벤트가 방출되기 전까지, Observable은 단순한 정의에 불과하다.

예를 들어 유튜브를 생각해보자.
유튜브는 유튜버가 동영상을 업로드했을 때 알림을 받을 수 있다. 하지만 구독자가 없으면 굳이 알림 기능이 필요할까?

Observable도 마찬가지이다. 이벤트를 정의하더라도, 이를 아무도 구독하지 않으면 이벤트를 확인할 필요가 없다.
따라서, 이벤트의 방출을 위해서는 subscribe를 해야한다.


Subscribe

subscribe 메서드를 사용하여 특정 Obsevable을 구독할 수 있다.

let observable = Observable.of(1, 2, 3)

observable.subscribe { event in
	print(event)
}
next(1)
next(2)
next(3)
completed

onNext 파라미터를 사용할 수도 있다.

observable.subscribe(onNext: { event in
	print(event)
})
1
2
3

위의 두 경우의 차이점은 출력 결과를 통해 알 수 있다.

앞서 Observable의 생명주기 onNext, onCompleted, onError에 대해서 언급했다.

첫 번째의 경우는 Observable의 생명주기를 각각 구분해서 받지 않는다. 즉, onNext일 때만 동작하는 것이 아니라, onCompleted일 때도 동작한다.

반면, 두 번째의 경우는 onNext일 때만 동작한다.


💡 그럼 아무거나 써도 상관 없네유?

❌ 절대 아님 ❌

이유가 궁금하다면, 아래의 글을 참고하자.
RxSwift - subscribe시 onNext를 명시해줘야 하는 이유


Dispose

subscribe 를 사용해 Observable을 구독한다면, 반대로 dispose 를 사용해 구독을 취소할 수 있다.

Observable은 subscrption 하기 전까지 아무 일도 하지 않는다.
subscrption을 했을 때 비로소 이벤트를 발생시키고, complete 또는 error가 발생할 때까지 계속해서 next 이벤트를 발생시킨다.

이 말은 즉슨, complete 또는 error가 발생하지 않는다면 종료되지 않는 것을 의미하며, memory leak를 발생시킬 수 있다.
이러한 경우, subscrption을 중단하기 위해서 dispose 를 사용한다.

observable.dispose()

dispose()를 호출하면 subscrption이 중단되어, 더이상 이벤트가 발생하지 않는다.


DisposeBag

만약 subscription을 해제해야 하는 Observable이 여러 개라면 어떻게 해야할까?
각각의 Obsevable마다 dispose()를 호출해야 할까?

이러한 경우에는 편의성을 위해 모든 subscription을 배열에 넣어서 dispose() 할 수 있을 것이다.

이게 바로 DisposeBag이다.

let diposeBag = DisposeBag()

observable.dispose(by: disposeBag)

subscribe()는 기본적으로 disposable을 반환하는데, 이는 메모리 관리를 도와주는 객체이다.

DisposeBag은 subscribe()가 반환한 disposable을 배열에 담아두고, disposeBag이 해제될 때 disposable 배열을 dispose()한다.

profile
나 애기 개발자 👶🏻

0개의 댓글