기본 콘텐츠로 건너뛰기

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라고 한다.

댓글

이 블로그의 인기 게시물

세상 간단한 https(+secured websocket): Caddy

nginx, apache2 같은 걸로 매번 certbot 연동을 통해 https 하는게 지겨워서 알아보니 Caddy라는게 있더라. 설치법은 강하게 크기 위해 알아서 해본다. # cat /etc/caddy/Caddyfile your.shitty.site:8123 {   proxy / localhost:9123 {     websocket     transparent   } } 이건 외부에서 8123으로 들어오는 걸 내부적으로 9123로 맞춰서 https 맞춰주는 reverse proxy. 만일 port를 생략하면 # cat /etc/caddy/Caddyfile your.shitty.site {   proxy / localhost:9123 {     websocket     transparent   } } 기본포트인 443으로 되어 https://your.shitty.site 로 접속이 된다. 요새 말썽이던 cloudflare 버리고 netlify domain이랑 caddy를 쓰니까 앓던 이가 빠진 느낌. 이 조합은 당분간 계속 써야겠다 싶다.

LG G Pro 2 Custom Rom +Rooting 기록

선 루팅 https://forum.xda-developers.com/lg-g3/general/guide-root-lg-firmwares-kitkat-lollipop-t3056951 1.2버전 스크립트 모드로. echo Looking for LG serial port.. echo. adb.exe wait-for-device 여기에서 정체 상태여서 강제로 adb kill-server 했더니 알아서 재부팅하심. 폰에선 "펌웨어 업데이트"화면이 나오고 Phone found at COM5! Rooting phone.. If you don't see the SuperSu installer script runs within about a minute, then the root failed. Author : blog.lvu.kr SPECIAL COMMAND : ENTER, LEAVE ## 이런 상황이 됨. #이 느린 속도로 하나씩 증가하고 있음. 한 시간 기다려도 성과없음. 뭐 몇번해봐도 안되고 결국 불안하긴 하지만 kingroot.net  로 설치 롤리팝이니까  https://drive.google.com/file/d/0B4kfGU1z_PClQ3AyM2lKOGR1S3M/view  이걸 받아서 압축 풀기. d838recovery.bat 만 있어서 당황스럽긴한데 실행하고 1번 하니까 리커버리 모드 진입까진 잘 되는 듯. adb sideload 라는게 있어서 해봄. Advance에서 adb sideload 선택하고 USB연결한 PC에서 adb sideload RR-N-v5.8.5-20171010-d838-Final.zip 하니까 착착 잘 진행됨. 이제 흉측한 U+LTE 가 없어짐. ㅇㅋ 군더더기 없고 깔끔한데 남은 건 gapps 를 설치해야함. http://opengapps.org/  를 권해줘서 갔는데 지옥 느림. ARM + 7.1 + stock 이 기본이...