기본 콘텐츠로 건너뛰기

cycle.js driver에 대한 정리.

cyclejs는 observable을 logic, subscribe를 effect로 각각 분리하고 서로 순환하는 구조인 full reactive framework 이다.

예를 들면 1초(1000ms)마다 스트림을 발산하는 text$는 매번 fold(reduce)하여 1씩 증가하고 "Second elapsed xx"로 map하는
text$=xs.periodic(1000)
  .fold(prev=>prev+1,0)
  .map(i=>`Second elapsed ${i}`)
를 logic.
이를 subscribe 하여 #app element의 텍스트로 넣는 것을
text$.subscrbie({
  next: str => document.querySelector('#app').textContent = str
})
를 effect로 볼 수 있다.

이를 각각 함수로 구분하여
const sink = ()=> xs.periodic(1000)
    .fold(prev=>prev+1,0)
    .map(i=>`Second elapsed ${i}`);
const domDriver = text$ => text$.subscribe({
  next: str => document.querySelector('#app').textContent = str
});
domDriver(sink);
이와 같이 재정의 할 수 있다.
같은  logic에 대해 DOM 렌더링과 log를 분리하려면 logDriver를 아래와 같이 추가하여
const logDriver = msg => console.log(msg);
logDriver(sink);
하여도 마찬가지.
subscribe한 객체의 observable만 있으면 DOM이건 console이건 canvas건 websocket이건 어느쪽이든 effect를 만들어 낼 수 있다.

만일 위의 예에서 logDriver와 domDriver가 다른 logic을 수행한다면 어떨까?
const sinks = ()=> ({
  DOM: xs.periodic(1000)
    .fold(prev=>prev+1,0)
    .map(i=>`Second elapsed ${i}`),
  log: xs.periodic(1000)
    .fold(prev=>prev+1,0)
})
domDriver(sinks.DOM);
logDriver(sinks.log);
이와 같이 sinks로 만들고 각각의 driver들이 sinks의 키를 가져오면 될 것이다.

이걸 일반화해보자. n개의 driver들이 있고 우리는 이걸 한번에 묶어서 실행하는 runner를 만들고 싶다.
const runner = (sinks, drivers)=> {
  for (idx in drivers) {
    drivers[idx] && drivers[idx](sinks[idx]);
  }
}
runner(sinks, {
  DOM: domDriver,
  log: logDriver
});
이와 같이 정리할 수 있다.

여기서 좀 더 runner를 유연하게 해보자.
만일 domDriver 에서 하드코드로 "#app"인 element를 지정하는게 아니라 인자로 받게 하면 어떨까?
runner(sinks, {
  DOM: domDriver("#app"),
  log: logDriver
});
가령 이런 식으로 말이다.
그렇다면 function을 반환하는 함수를 "실행"해야한다.
그런 driver를 makeDomDriver라고 하고 구현해보자.
const makeDomDriver = target =>
  text$ => text$.subscribe({
    next: str => document.querySelector(target).textContent = str
  });
그러면, 인자를 받아도 여전히 text$를 인자로 하는 무기명 함수를 지정한다.
logDriver도 같은 방식으로 정리하고 모아보면
const makeLogDriver = ()=>
  msg => console.log(msg);
runner(sinks, {
  DOM: makeDomDriver("#app"),
  log: makeLogDriver()
});
이와 같은 형태로 만들 수 있다.

이것이 cycle.js의 근간을 이루고 있는 아이디어이며.
요컨데 logic으로 effect를 만드는 함수를 driver라고 한다.

댓글