Push 시스템과 Pull 시스템에서의 Producer 역할에 관한 고찰

seop·2022년 4월 10일
0

고찰(Consideration)

목록 보기
1/5
post-thumbnail

반환값의 갯수에 따른 객체 분류

SINGLEMULTIPLE
PullFunctionIterator
PushPromiseObservable

Producer 와 Consumer 의 차이점

PRODUCERCONSUMER
PullPassive: produces data when requested.Active: decides when data is requested.
PushActive: produces data at its own pace.Passive: reacts to received data.

Producer 는 데이터를 생산하는 주체이고, Consumer 는 데이터를 사용하는 주체입니다. 우리가 흔히 사용했던 함수의 관점에서 생각해보자면, 함수를 호출하는 호출자(Caller)가 Consumer 이고, 호출된 함수(Callee)가 Producer 라고 말할 수 있습니다.

우리가 일반적으로 겪어왔던 Pull 시스템에서는, Consumer 가 데이터를 언제 받는지 결정할 수 있고 Producer 는 요청을 받아 데이터를 생산하는 수동적인 역할을 할 뿐입니다. 반면 Promise 와 Observable 을 이용한 Push 시스템에서는 Producer 가 자신이 원하는 때에 데이터를 생산하고 전달할 수 있으며, Consumer 는 그 데이터에 반응할 뿐입니다.

이론적으로는 납득이 갔지만, 실제 코드가 어떨지 구체적으로 예시를 생각해 보니 헷갈리는 부분이 있었습니다. 바로 Pull 시스템 에서의 Function과 Push 시스템 에서의 Observable 에 관한 설명입니다.

먼저 Function 의 경우를 생각해 보자면, Consumer 가 데이터를 언제 받을 수 있는지 결정 할 수 있고 Function 은 요청된 데이터를 생산할 뿐이라는 점. 이 부분은 매우 당연합니다.

하지만 Push 시스템에서 Observable 은 이론이 제대로 대입되지 않았습니다. 아래의 코드 예시를 살펴봅시다.

const observable = new Observable(function subscribe(subscriber) {
  subscriber.next(1);
})

observable.subscribe(x => console.log(x));

observable 에서 1 이라는 값을 notification 받아서 콘솔에 1을 출력하는 코드 입니다. 저는 이 부분에서,

  • "저것은 호출하고 값을 받는다는 점에서 일반 함수 호출과 다를바가 없는데?"
  • "도대체 어떤 점에서 Producer 가 데이터를 능동적으로 생산한다는 것이지? subscribe() 메서드에 의한 lazy push 는 오히려 수동적인거 아닌가?"

라고 생각했었습니다.

그러나 이는 곧,
1. Producer 와 Consumer 의 주체가 누구인지 명확히 함과 동시에
2. subscribe() 메서드의 역할이 무엇인지 API Documentation 에서 다시한번 읽음으로써
해결되었습니다.

Observable Push 시스템에서의 Producer 와 Consumer 의 주체

아까의 예시를 다시 가져와보겠습니다.

const observable = new Observable(function subscribe(subscriber) {
  subscriber.next(1);
})

observable.subscribe(x => console.log(x));

이 예시를 보면, 제가 일부러 Observable 생성자에 전달되는 콜백에 subscribe 라는 이름을 붙여서 전달한 것을 볼 수 있습니다. 저 subscribe 함수가 데이터를 생산하는 Producer 입니다. 그리고 observable.subscribe(x => console.log(x)) 에서 전달되는 x => console.log(x) 콜백함수가 데이터를 받아쓰는 Consumer 입니다.

subscribe() 메서드의 역할

제가 아까 Observable 함수에 전달되는 subscribe 콜백함수가 Producer 라고 했습니다. observable.subscribe() 에서도 subscribe 라는 메서드를 호출합니다. 네, 이것은 같은 것입니다. 공식문서 에서도 Practical purpose 에서 는 두개가 같다고 봐도 무방하다고 설명되어 있습니다.

즉, observable.subscribe() 를 한다는 것은 Observable 에 전달된 콜백함수를 실행시킨다는 의미와 일맥상통하며, Producer 가 직접 실행함으로써 Consumer 에게 자신이 생산한 데이터를 전달한다는 자연스러운 스토리가 형성됩니다.

https://rxjs.dev/api/index/class/Observable 문서에서도, subscribe() 메서드는 Observable 의 실행을 invoke 한다고 설명돼 있습니다.

쐐기를 박아보자

Observable Push 시스템에서 Producer 와 Consumer 가 누구인지 정확히 알게되어 궁금증이 해결되었습니다. 하지만 'lazy computation' 이라는 부분이 무언가 수동적인 느낌을 주는듯한 느낌이 아직 가시지 않았습니다.

저는 그래서, lazy = 수동 이라는 명제는 성급한 일반화의 오류라는 것을 다시 한번 상기시키려고 합니다. lazy 하지만 분명히 능동적이고 주체적일 수가 있으니까요.

마지막으로 예제를 하나 작성하여 여운을 남기고 마무리 하겠습니다.

function passiveProducer() {
  setTimeout(() => {
    return 'seop'; // X. Already in Task Queue
  }, 5000);
  
  const producedValueJustPassively = 'seop';
  
  return producedValueJustPassively;
}

const value = passiveProducer();

// -------------------------------------------------------------

const lazyButActiveObservable = new Observable((subscriber) => {
	setTimeout(() => {
      subscriber.next('seop');
    }, 5000);
})

lazyButActiveObservable.subscribe(x => console.log(`${x} value is absolutely emitted by Producer's own pace`))

P.S. 이벤트루프 에서까지 책임을 다 하는 Observable..

profile
지식을 주도하는 법을 터득하는중..

0개의 댓글