[UniRx 입문 강좌 3] IObserver 메세지 종류와 스트림의 수명 관리
본문 바로가기
프로그래밍/Unity

[UniRx 입문 강좌 3] IObserver 메세지 종류와 스트림의 수명 관리

by [아마군] 2019. 9. 30.
반응형

[UniRx 입문 강좌 1] 개념 및 기본 사용법 소개
[UniRx 입문 강좌 2] UniRx 의 핵심, Subject 와 Observable 사용 방법

[UniRx 입문 강좌 4] Operator 활용(1) - Where & Select & SelectMany 사용법

[UniRx 입문 강좌 5] Operator 활용(2) - 다양한 오퍼레이터 소개

[UniRx 입문 강좌 6] 코루틴(Coroutine) 과 UniRx 연동


1. IObserver & IObservable 인터페이스

지난 강의에서 Subject 에 대해 설명하면서 IObserver 인터페이스를 구현하는 과정에서 아래 참고 이미지를 사용했었다.

이번 강좌에서는 IObserver 의 인터페이스인 OnNext 와 OnError, OnComplete 에 대해 좀더 자세히 짚고 가겠다.

 

그만큼 UniRx 를 사용하면서 자주 보게 될 메세지 들이기 때문이다.

 

실제 IObserver 와 IObservable 인터페이스 클래스 소스 코드를 보면 위 도표와 똑같이 각각 3개, 1개의 메소드만 정의 되어 있다.

 

 

UniRx 에서 사용되는 이벤트 메세지는 이 3가지를 이용해 처리 된다.

 

  • OnNext : 일반적인 이벤트 발생 시 통지
  • OnError : 스트림 처리 중 예외(Exception)발생 시 통지
  • OnComplete : 스트림 종료 통지

Subscribe 메서드는 이 메세지들 중 원하는 것만 받아서 처리할 수 있게각 상황별로 오버로드 되어 있다.

 

Subscribe 오버로드 기능
Subscribe(IObserber observer) 기본형
Subscribe() 모든 메시지를 무시한다
Subscribe(Action onNext) OnNext 만 처리
Subscribe(Action onNext, Action onError) OnNext & OnError
Subscribe(Action onNext, Action onCompleted) OnNext & OnCompleted
Subscribe(Action onNext, Action onError, Action onCompleted) OnNext & OnError & OnCompleted

 

자, 그럼 이 메세지 들이 어떻게 동작하는지 살펴 보자.


2. OnNext

UniRx 에서 이벤트를 통지할 때 대부분 이 OnNext 메세지를 사용하게 될 것이다.

 

기본 사용에 있어서는 이 OnNext 만 사용해도 큰 문제가 없다.

 

예제와 같이 OnNext 가 호출 될 때마다 정수형 이벤트를 Subscibe 에 통지해 준다.

 


3. OnError

OnError 메세지는 위에서 설명했듯이 스트림 처리 중 예외(Exception) 이 발생하면 통지된다.

 

에러 처리가 필요 없다면 OnNext 와 달리 생략도 가능하다.

 

또한 OnError 메세지가 Subscribe 에 도달한다면 이 스트림은 그 시점에서 바로 구독이 종료 된다는 점을 명심하자.

 

간단한 샘플 코드를 살펴보자.

 

 

스트림을 처리하는 중에 예외가 발생하자 Subscribe에 OnError 메세지가 통지 되고 스트림의 구독이 종료 되어 이후에 발생한 OnNext("4") 는 처리 되지 않았다.

 

만약 예외가 발생한 경우 그에 대한 처리를 해주고 다시 구독을 이어나가고 싶다면 어떻게 해야 할까.

 

이전 예제와 달리 예외가 발생해도 마지막 까지 Subscribe 에 통지를 진행한다.

 

다른 점은 예외가 발생한 Select 와 Subscribe 사이에 OnErrorRetry 가 추가된 점인데 이 OnErrorRetry 는 예외를 중간에서 Catch 한 후 스트림을 재구축 (Subject 에 IObserver 를 다시 등록) 하여 구독을 계속 이어가게 해준다.

 

이로 인해 Subscribe 의 OnError 가 발생하지 않게 되는 것이다.

 

이 예외 처리와 관련한 몇개의 오퍼레이터가 있다.

 

Operators 기능
Retry OnError 발생 시 다시 Subscribe 한다
Catch OnError 발생 시 예외 처리 후 다른 스트림으로 대체한다
CatchIgnore OnError 발생 시 예외 처리 후 OnError 를 무시하고 OnCompleted 로 대체한다
OnErrorRetry OnError 발생 시 예외 처리 후 Subscribe 한다 (시간 지정 가능)

4. OnCompleted

OnCompleted 는 스트림이 완료 되었으므로 이후로는 메세지를 발행하지 않는다 라는 사실을 통지하는 메세지이다.

 

OnError 와 마찬가지로 Subscribe 에 OnCompleted 가 통지되면 해당 스트림은 바로 구독이 종료 된다.

 

이를 이용해 스트림을 파기하려는 시점에 OnCompleted 를 발행하여 구독을 종료 시킬 수 있다.

 

이렇게 구독이 종료된 Subject 는 재사용이 불가능 하며 Subscribe 를 호출해도 바로 onCompleted 가 발생하게 된다.

 

OnCompleted 를 발생 시키면 스트림의 구독이 완전히 중단되는 것을 확인 할 수 있다.

 


5. Dispose

위의 IObserver 의 OnNext, OnError, OnCompleted 와 마찬가지로 Subject 가 구현하고 있는 IObservable 의 "IDispose" 에 대해 알아보자.

 

Subscribe 의 반환값인 IDisposable 은 가비지컬렉터가 관리하지 않는 리소스를 해제해 주기 위한 C#의 기본 인터페이스이다. (IDisposable.Dispose() 로 해제)

 

Subscribe 가 완료 될 때 이 IDisposable 을 반환 한다는 것은 곧 이 IDisposable 의 Dispose 를 실행하면 스트림의 구독이 종료 된다는 뜻이다.

 

간단한 사용예를 보자.

 

이와 같이 Dispose 를 호출하여 이 스트림의 구독을 중단 할 수 있다.

 

단, OnCompleted 이벤트가 아니라 Dispose() 로 구독을 종료했을 경우 OnCompleted 를 전달하지 않는다는 점을 주의해야 한다.

 

또 한가지, OnCompleted 는 호출하는 Subject 의 모든 스트림의 Subscribe 가 중단 되지만 Dispose 는 Subject 의 스트림 중 원하는 한개의 스트림만 구독을 중단 할 수 있다.

 

아래 샘플을 참고하자.

 


6. 스트림의 라이프 사이클(Life Cycle)

스트림은 편리하게 사용할 수 있지만 객체의 잦은 생성과 삭제가 퍼포먼스에 큰 영향을 미치는 유니티 특성 상 특히 수명 관리에 신경을 써야 한다.

 

기본적으로 스트림은 Subject 에 포함 되는 일부 또는 그 자체 라고 볼 수 있으며 Subject 가 Destory 되면 스트림도 파기 된다.

 

하나하나의 스트림은 Subscribe 가 끝단에 위치하여 흘러온 데이터를 처리하게 되며 이 각각의 스트림 들은 Subject 에 등록 되어 있다.

 

즉, Subject 가 파기되지 않고 남아있다면 각각의 스트림들도 살아있다는 뜻이 된다.

 

때문에 스트림이 참조하고 있는 오브젝트가 스트림보다 먼저 Destory 되어 버리면 해당 스트림의 처리는 정상적으로 이루어질 수 없음에도 여전히 살아남아 NullReferenceException 을 일으키거나 메모리릭 등 성능 저하와 치명적인 오류를 발생하는 원인이 될 수 있다.

 

하지만 사용될 오브젝트가 런타임에서 결정되거나 파기 타이밍을 매번 코딩하는 단계에서 확인하기 힘든 경우가 많기 때문에 스트림에서 일일이 오브젝트를 검사하는 것도 쉽지 않은 일이다.

 

이런 경우 가장 손쉽게 처리할 수 있는 방법은 AddTo 오퍼레이터를 사용하는 것이다.

 

AddTo 오퍼레이터에 GameObject 의 인스턴스를 지정하면 해당 인스턴스가 Detroy 되는지를 감시하여 자동으로 Dispose 를 호출하여 구독을 중단 시켜 준다.

 


[UniRx 입문 강좌 4] Operator 활용(1) - Where & Select & SelectMany 사용법

 

 

[UniRx 입문 강좌 4] Operator 활용(1) - Where & Select&SelectMany 사용법

[UniRx 입문 강좌 1] 개념 및 기본 사용법 소개 [UniRx 입문 강좌 2] UniRx 의 핵심, Subject 와 Observable 사용 방법 [UniRx 입문 강좌 3] IObserver 메세지 종류와 스트림의 수명 관리 1. 오퍼레이터(Operator..

skuld2000.tistory.com

 

반응형

댓글