관찰 대상(Observable)

리액티브(Reactive) 프로그래밍

리액티브 프로그래밍을 이해하기 위한 핵심 중 하나는 Observer(관찰자) 패턴을 이해하는 것입니다.

리액티브 프로그래밍을 간단하게 글로 풀어 쓰면 다음과 같이 표현할 수 있습니다.

관찰하고자 하는 대상을 관찰할 수 있는 형태로 만들어서 의 변화, 혹은 (=이벤트)의 발생을 감지하는 것으로 이 값들은 마치 물이 흐르듯 스트림을 통해 흐르는 것에 비유할 수 있는데, 경우에 따라서는 이들 값들을 필터링하거나 버퍼링할 수도 있으며 다른 스트림의 값을 흘려 보내는 일과 같은, 값에 대한 연산을 하는 것이 가능하다. 원하는 값이 통지되면 이 값에 대한 처리를 하며, 스트림에 값이 흐르는 동안 이 처리를 반복한다.

그러면 이제부터 Rx 프로그래밍을 위한 중요한 용어에 대해서 하나씩 살펴 보죠.

관찰대상 (Observable)

먼저 Observable의 사전적 의미를 살펴 볼까요?

  • Observable: 관찰할 수 있는

Rx에서의 Observable 객체는 사전적인 의미대로 어떤 '객체'를 관찰할 수 있는 형태로 만드는 것을 말하며 Rx에서는 Observable 객체를 생성함으로써 관찰을 시작하게 됩니다. 이 '객체'에 따라 실제 관찰하는 값(= 스트림에 흘려 보내는 값) 혹은 관찰의 대상인 사건(=이벤트)이 결정됩니다.

관찰하고자 하는 객체에 따라 Observable 객체의 생성 방법에 차이가 있기 때문에 이 부분은 따로 페이지를 할당해서 설명하는 편이 좋겠네요.

연산자(Operator)

관찰 대상이 결정되면 스트림에 값들을 방류해야 합니다. 방류하기 위해서 어떤 값을 선택(Select)해야 하거나 바로 방류하는 것이 아니라 모아서(Buffer) 방류를 해야 할 필요도 있습니다. 또 값들을 선택해서 조건(Where)에 맞는 값들만을 흘려 보내야 할 필요도 있습니다.

이렇게 스트림에 방류할 때에 값들에 대한 조작을 필요로 하는데 Rx에서 이런 일들은 연산자를 통해서 처리하게 됩니다.

Rx 프로그래밍의 개념에 익숙해진 후에 본격적인 Rx 프로그래밍을 시작하면 이들 연산자들의 조합 방법에 대해서 이해하는 것이 Rx 프로그래밍의 8할입니다.

구독(Subscribe)

구독(Subscribe)이란 원하는 값이 통지되었을 때 이 값에 대한 처리를 하는 것입니다.

Subscribe에는 값이 전달될 때 아래의 세 가지 방법 중 하나로 값의 도착을 알리는 이벤트가 통지됩니다.

  • OnNext: 원하는 값을 통지할 때 발생하는 이벤트.
  • OnError: 에러 발생시 통지되는 이벤트.
  • OnCompleted: 스트림의 종료시 통지되는 이벤트, 관찰을 종료한다.

관찰자는 값에 대한 처리를 한번으로 끝내는 것이 아니라 스트림의 값을 처리하고 나면 다음 값을 기다립니다. 특별히 관찰자를 제거하지 않는 이상, 혹은 더 이상 값을 받을 수 없는 경우로 관찰을 완료하지 않는 이상 계속해서 관찰(감시)합니다. 이처럼 원하는 값이 온 경우에 통지되는 이벤트가 바로 OnNext 입니다.

스트림에는 원하는 값만 전달되는 경우만 있는 것이 아니라 의도하지 않은 값이 전달될 수도 있는데, 이 경우에 OnError 이벤트가 통지되고 Subscribe에서 처리할 수 있습니다.

첫 번째 예제

이제 앞에서 설명한 관찰자, 연산자, 구독의 이 세 가지를 가지고 첫 번째 Rx 예제를 살펴 보도록 하죠.

첫 번째 예제는 마우스의 더블 클릭 판정을 Rx를 이용해서 처리하는 코드입니다.

var clickStream = Observable.EveryUpdate()
    .Where(_ => Input.GetMouseButtonDown(0));

clickStream.Buffer(clickStream.Throttle(TimeSpan.FromMilliseconds(250)))
    .Where(xs => xs.Count >= 2)
    .Subscribe(xs => Debug.Log("DoubleClick Detected! Count:" + xs.Count));

한 라인씩 살펴 볼까요.

var clickStream = Observable.EveryUpdate()

Observable 객체를 생성하는데 생성한 Observable 객체는 Unity3D의 MonoBehaviour의 매 Update 프레임마다 값을 관찰하는 스트림을 생성합니다.

    .Where(_ => Input.GetMouseButtonDown(0));

매 Update 함수 호출시 마우스의 왼쪽 버튼 클릭 여부를 감시하게 됩니다.

clickStream.Buffer( ...

clickStream 스트림으로 값을 바로 흘려 보내지 않고 버퍼에다 저장합니다.

Buffer 연산자는

clickStream.Throttle(TimeSpan.FromMilliseconds(250)

Throttle 연산자는 밸브를 생각하면 됩니다. TimeSpan은 일정한 시간양을 표현하기 위한 객체로, FromMilliseconds는 이 TimeSpan의 시간의 단위를 정합니다. 정리하면 250ms 동안 밸브를 열어서 이 시간동안의 값을 저장한다는 의미입니다.

    .Where(xs => xs.Count >= 2)

버퍼에 모인 값의 개수가 2개 이상인 경우를 체크하고 있는데 이 이야기는 250ms 동안 밸브를 열어 두고 이 시간에 동안 마우스 클릭이라는 값이(= 이벤트가) 2회 이상 발생했다는 의미입니다.

어떤가요? 일반적인 마우스 더블 클릭의 판정 방법과 동일하죠?

    .Subscribe(xs => Debug.Log("DoubleClick Detected! Count:" + xs.Count));

마지막으로 구독에 대한 처리입니다. 마우스 더블 클릭에 대한 감지를 하게 되면 내부적으로 OnNext 이벤트를 통지하게 되는데, 여기에서는 Buffer의 값의 개수를 Debug.Log로 콘솔에 출력하는 처리를 하고 있습니다.

results matching ""

    No results matching ""