UniRx

One·2022년 8월 21일
0

Unity

목록 보기
9/9
post-thumbnail

UniRx 소개

UniRx ?

Unity에서 Reactive Programming을 쉽게 구현할 수 있게 만든 라이브러리이다. .NET에도 Rx 라이브러리가 있지만 Unity에 최적화되어 있지 않다. UniRx는 Unity에 최적화되어 만들어졌다.

Reactive Programming

데이터 또는 이벤트의 변경이 발생하면 이에 반응해 처리하는 프로그래밍 기법이다.

UniRx의 장점

일반적으로 유니티의 네트워크 운영은 WWW와 코루틴을 사용해야 한다. 그렇지만 아래와 같은 이유로 코루틴을 사용하는 것은 비동기 연산에 좋은 방법이 아니다

  1. 코루틴은 다른 값을 반환할 수 없고 오직 IEnumerator를 반환해야 한다.
  2. 코루틴은 예외 처리를 할 수 없다. 왜냐하면 yeild return 문은 try-catch로 감쌀 수 없기 때문이다.

UniRx의 동작 과정

  1. 스트림(Stream)을 생성한다.

  2. 오퍼레이터를 사용하여 스트림을 가공한다.

  3. 가공된 스트림을 구독하여 사용한다.

💡 스트림(Stream)은 연속되는 이벤트(메시지)가 발생되어 구독자에게 도달하기까지의 흐름이다. 스트림은 나누어지거나 합쳐지는 것이 가능하고 IObservable을 통해 구독이 가능하다

Subject와 Observable

Subject

ISubject 클래스는 IObserver와 IObservable 인터페이스를 구현하고 있다.

namespace UniRx
{
    public interface ISubject<TSource, TResult> : IObserver<TSource>, IObservable<TResult>
    {
    }

    public interface ISubject<T> : ISubject<T, T>, IObserver<T>, IObservable<T>
    {
    }
}

IObserver와 IObservable에는 각각 OnCompleted, OnError, OnNext와 Subscribe 함수가 정의되어 있다.

namespace System
{
  public interface IObserver<in T>
  {
    void OnCompleted();

    void OnError(Exception error);

    void OnNext(T value);
  }
}
namespace System
{
  public interface IObservable<out T>
  {
    IDisposable Subscribe(IObserver<T> observer);
  }
}

Subscribe

이벤트를 받기 위해 구독하는 함수 이벤트 발생시 실행할 로직을 등록한다.

private Subject<string> subject = new Subject<string>();

subject.Subscribe(x => Debug.Log(x));

OnNext

구독자에게 이벤트를 통지한다.

private Subject<string> subject = new Subject<string>();

subject.Subscribe(x => Debug.Log(x));

...

subject.OnNext("Hello");

// Result
// Hello

OnCompleted

스트림이 완료되었을때 통지된다. OnComplete이 통지되면 해당 스트림은 종료되며 종료된 Subject는 재사용이 불가능하다. 종료된 Subject에 Subscribe를 호출할 경우 OnComplete가 실행된다.

private Subject<string> subject = new Subject<string>();

subject.Subscribe(x => Debug.Log(x), () => Debug.Log("Complete"));

...

subject.OnNext("Hello");
subject.OnComplete();
subject.OnNext("World!");

subject.Subscribe(x => Debug.Log(x), () => Debug.Log("Complete"));
subject.OnNext("Bye");

// Result
// Hello
// Complete

// Complete

OnError

스트림 진행중 오류가 발생했을 때 통지된다. 에러 처리가 필요할 경우 작성하고 생략도 가능하다. OnError가 통지될 경우에도 해당 스트림은 종료된다.

private Subject<string> subject = new Subject<string>();

subject.Select(x => {
    if (x.Length > 5) {
        throw new Exception("String Length is more than 5");
    }

    return x;
}).Subscribe(x => { Debug.Log(x); },
    ex => Debug.Log("Error : " + ex.Message),
    () => Debug.Log("Complete"));

subject.OnNext("ABCD");
subject.OnNext("EFGHIJ");

// result
// ABCD
// Error : String Length is more than 5

Dispose

IObservable 인터페이스의 Subscribe 함수는 IDisposable를 반환하기 때문에 Dispose 함수를 이용하여 메모리 해제를 할 수 있다. 이때 OnComplete는 실행되지 않는다.

private Subject<string> subject = new Subject<string>();

subject.Subscribe(x => Debug.Log(x), () => Debug.Log("Complete"));

subject.OnNext("ABC");
subject.OnNext("DEF");
subject.Dispose();

subject.OnNext("GHI"); // ObjectDisposedException 예외 발생

// result
// ABC
// DEF

OnComplete는 모든 구독 상태를 완료시키지만 Dispose를 이용하면 해당 구독만 해제할 수 있다.

private Subject<string> subject = new Subject<string>();

var disposable_1 = subject.Subscribe(x => Debug.Log(x), () => Debug.Log("Complete"));
var disposable_2 = subject.Subscribe(x => Debug.Log(x), () => Debug.Log("Complete"));

subject.OnNext("ABC");
subject.OnNext("DEF");

disposable_1.Dispose();

subject.OnNext("GHI");
subject.OnCompleted();

// result 
// ABC
// ABC
// DEF
// DEF

// GHI

// Complete
profile
Unity Developer

0개의 댓글