Sugar

[Unity] UniRX - 3 IObserver 메세지 종류

by Sugar0810

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

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

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

using System;

namespace UniRx
{
    public interface IObserver<T>
    {
        void OnNext(T value);
        void OnError(Exception error);
        void OnCompleted();
    }
}

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

 

.OnNext

var intTest = new Subject<int>();

intTest.Subscribe(x => Debug.Log(x));
intTest.OnNext(2);
intTest.OnNext(50);
intTest.OnNext(100);

// Result
2
50
100
  • UniRx에서 이벤트를 통지할 때 대부분의 상황에서 사용됨
  • 이 OnNext만 사용해도 큰 문제없음
  • OnNext가 호출될 때마다 정수형 이벤트를 Subcribe에 통지해 준다.

 

.OnError

  • 스트림 처리 중 예외(Exception)가 발생하면 통지
  • 에러 처리가 필요 없다면 OnNext와 달리 생략해도 된다.
  • OnError 메시지가 Subcribe에 도달한다면 이 스트림은 그 시점에서 바로 구독이 종료된다.
var stringSubject = new Subject<string>(); 

void Start()
{
    // 문자열을 스트림 중간에서 정수로 변환한다
    stringSubject 
        . Select(str => int.Parse( str ))  // int 형이 아닌 경우 int.Parse 메소드에서 예외가 발생 
        . Subscribe( 
            // OnNext 시 처리
            x  =>  Debug.Log("성공 : "  +  x),
            // OnError시 처리. 생략하면 예외 처리 안함
            ex  =>  Debug.Log("예외 : "  +  ex)  
        );  //Subscribe의 오버로드 중 Subscribe(OnNext, OnError) 

    stringSubject.OnNext("1"); 
    stringSubject.OnNext("2"); 
    stringSubject.OnNext("Hello");  // 문자열을 넣으므로 Select 구문의 int.Parse에서 예외 발생
    stringSubject.OnNext("4"); 
}

// Result
성공 : 1
성공 : 2
예외 : System.FormatException : Input string was not in the correct format

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

 

var stringSubject = new Subject<string>();

void Start()
{
    // 문자열을 스트림 중간에서 정수로 변환한다
    stringSubject
        .Select(str => int.Parse(str)) // int 형이 아닌 경우 int.Parse 메소드에서 예외가 발생 
        .OnErrorRetry((FormatException ex) => // 예외 정보의 필터링 가능
        {
            Debug.Log("에외 발생하여 다시 실행");
        })
        .Subscribe(
            // OnNext 시 처리
            x => Debug.Log("성공 : " + x), 
            //OnError 시 처리. 생략하면 예외 처리 안함
            ex => Debug.Log("예외 : " + ex) 
        );  // Subscribe 의 오버로드 중 Subscribe(OnNext, OnError) 

    stringSubject.OnNext("1");
    stringSubject.OnNext("2");
    stringSubject.OnNext("Hello");
    stringSubject.OnNext("4");
    stringSubject.OnNext("5");
}

// Result
성공 : 1
성공 : 2
예외 발생하여 다시 실행
성공 : 4
성공 : 5

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

 

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

 

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

 

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

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

 

.OnCompleted

  • '스트림이 완료되었으므로 이후로는 메시지를 발행하지 않는다.'라는 사실을 통지하는 메시지
  • OnError와 마찬가지로 Subscribe에 OnCompleted가 통지되면 해당 스트림은 바로 구독 종료된다.
    • 이를 이용하여 스트림을 파기하려는 시점에 OnCompleted를 발행하여 구독을 종료시킬 수 있다.
    • 이렇게 구독이 종료된 Subject는 재사용이 불가능하며 Subcribe를 호출해도 바로 OnCompleted가 발생
var subject = new Subject<int();
subject.Subscribe(
    x => Debug.Log(x),
    () => Debug.Log("OnCompleted")
);  // ubscribe 의 오버로드 중 Subscribe(OnNext, OnCompleted) 

subject.OnNext(1);
subject.OnNext(2);
subject.OnCompleted();
subject.OnNext(4);
subject.OnNext(5);

// Result
1
2
OnCompleted

 


 

📚 참고사이트

https://skuld2000.tistory.com/35

블로그의 정보

Sugar

Sugar0810

활동하기