https://jpub.tistory.com/1265, Chapter 18. 반응형 아키텍처
우리가 살펴본 예제에서 전역 상태는 장바구니 뿐입니다.
원래 코드
function ValueCell(initialValue) {
var currentValue = initialValue;
return {
val: function() {
return currentValue;
}
update: function(f) {
var oldValue = currentValue;
var newValue = f(oldValue);
currentValue = newValue;
}
}
}
function ValueCell(initialValue) {
var currentValue = initialValue;
var watchers = [];
return {
val: function() {
return currentValue;
}
update: function(f) {
var oldValue = currentValue;
var newValue = f(oldValue);
if(oldValue !== newValue) {
currentValue = newValue;
forEach(watchers, function(watcher) {
watcher(newValue);
}
}
},
addWatcher: function(f) {
watchers.push(f);
}
}
}
watcher 개념은 다른 이름으로 사용되기도 합니다. 다음은 감시자의 다른 이름입니다.
- watcher
- observer
- listener
- event handler
- callback
- subscriber
모두 같은 개념을 나타내는 이름입니다. 어떤 것이 도 올바른 이름이라고 할 수는 없습니다.
function FormulaCell(upstreamCell, f) {
var myCell = ValueCell(f(upstreamCell.val()));
upstreamCell.addWatcher(function(newUpstreamValue) {
myCell.update(function(currentValue) {
return f(newUpstreamValue);
});
});
return {
val: myCell.val,
addWatcher: myCell.addWatcher
}
}
일반적인 아키텍쳐에서는 장바구니를 바꾸는 모든 UI 이벤트 핸들러에 같은 코드를 넣어줘야 합니다. 제품 추가를 클릭하면 배송 아이콘을 갱신해야 합니다. 또 제품 삭제나 장바구니 비우기를 클릭해도 마찬가지로 배송 아이콘을 갱신해야 합니다. 버튼 클릭이라는 원인과 그로 인해 발생하는 배송 아이콘 갱신이라는 효과가 결합되어 있습니다. 반응형 아키텍처를 사용하면 원인과 효과가 결합한 것을 분리할 수 있습니다.
파이프라인은 반응형 프레임워크를 사용해 구현하기도 합니다. 자바스크립트를 사용한다면 Promise로 액션과 계산을 조합해 파이프라인을 구현할 수 있습니다. Promise는 단일값을 전달할 수 있기 때문에 파이프라인 단계 간 데이터를 전달할 수 있습니다.
단일 이벤트 대신 이벤트 스트림이 필요하다면 ReactiveX(http://reactive.io/) 라이브러리를 사용해 보세요. 스트림에 map이나 filter를 사용할 수 있고 다양한 언어로 구현되어 있습니다. 자바스크립트 구현체는 RxJS입니다.
Kafka나 RabbitMG와 같은 외부 스트림 서비스로 파이프라인을 구현할 수 있습니다. 스트림 서비스를 사용하면 반응형 아키텍처를 더 큰 범위에 적용할 수 있습니다. 액션과 계산 단위가 아닌 서비스 관점에서 서로 분리할 수 있습니다.
만약 여러 단계가 있지만 데이터를 전달하지 않는다면 이 패턴을 사용하지 않는 것이 좋습니다. 데이터를 전달하지 않으면 파이프라인이라고 볼 수 없습니다. 따라서 올바른 반응형 아키텍처가 될 수 없습니다.
당신은 언제 aws의 sqs 혹은 sns를 필요로 하십니까?
위 그림의 첫번째 그림과 같인 1줄로 이어지는 구조(1:1)보다 이 글의 첫번째 그림인 장바구니 처럼 1:n인 상황에 Reactive가 더 적합한 것 같다.
핵심은 여러 군데서 조작하고 싶고, 여러 군데서 변화를 인지하고 싶은 대상(여기서는 장바구니)을 RDB instance, Redis instance와 같이 큰 단위이 아니라, 작은 단위로 모델링 할 수 있느냐가 아닐까 싶은데, 이에 대한 언급은 책에 없다.
위의 ValueCell
과 FormulaCell
를 이용하여, 다음과 같이 코딩 했을때,
var shopping_cart = ValueCell({});
var cart_total = FormulaCell(shopping_cart, calc_total);
shopping_cart.addWatcher(update_shipping_icon);
cart_total.addWatcher(set_cart_total_dom);
cart_total.addWatcher(update_tax_dom);
shopping_cart.watchers
와 cart_total.myCell.watchers
는 어떤 상황일까요?