- 타임라인은 적을 수록 이해하기 쉽다.
- 타임라인은 짧을 수록 이해하기 쉽다.
- 공유하는 자원이 적을수록 이해하기 쉽다.
- 자원을 공유한다면 서로 조율해야한다. 5. 시간을 일급으로 다룬다.
- 액션의 순서와 타이밍을 맞추는것은 어렵기때문에, 타임라인을 관리하는 재사용가능한 객체를 만들어 해결할수 있다. 호출 순서와 반복은 직접 다룰수있다.
- 모든 언어에는 암묵적인 모델 존재 -> 하지만 우리가 해결하려는 문제와 맞지 않기 때문에 함수형 프로그래밍으로 문제를 해결할 시간 모델 생성
장바구니 큐 동작의 최적화 진행이후, 버그 발생
function add_item_to_cart(item) {
cart = add_item(cart, item);
update_total_queue(cart);
}
function calc_cart_total(cart, callback) {
var total = 0;
cost_ajax(cart, function(cost) {
total += cost;
// 최적화 이전
// shipping_ajax(cart, function(shipping) {
// total += shipping;
// callback(total);
// });
});
// 최적화 이후
shipping_ajax(cart, function(shipping) {
total += shipping;
callback(total);
});
}
function calc_cart_worker(cart, done) {
calc_cart_total(cart, function(total) {
update_total_dom(total);
done(total);
});
}
var update_total_queue = DroppingQueue(1, calc_cart_worker);
- 액션을 확인하기
- 액션 그리기
- 다이어그램 단순화 하기
- 실행 가능 순서 분석
- 두 응답이후, DOM이 업데이트 되도록 수정
- 여러 타임라인이 끝나는 지점은 “Cut”으로 분리
- Cut은 순서를 보장해주는 역할
- Cut 아래단계 실행전, 윗 단계가 끝나야됨
- Cut을 통해 복잡한 타임라인을 분리하여, 분석할수 있다.
- 단일 스레드 환경인 자바스크립트에서만 동작하는 Cut
function Cut(num, callback) {
var num_finished = 0;
return function() {
num_finished += 1;
if(num_finished === num)
callback();
};
}
var done = Cut(3, function() {
console.log("3 timelines are finished");
});
done();
done();
done();
// console=> "3 timelines are finished"
- 문제 해결 코드 적용
function calc_cart_total(cart, callback) {
var total = 0;
var done = Cut(2, function() {
callback(total);
});
cost_ajax(cart, function(cost) {
total += cost;
done();
});
shipping_ajax(cart, function(shipping) {
total += shipping;
done();
});
}
- 비동기 웹 요청
- 결과를 합쳐야 하는 두개의 api응답
- 예측 불가능한 사용자의 액션
function JustOnce(action) {
var alreadyCalled = false;
return function(a, b, c) {
if(alreadyCalled) return;
alreadyCalled = true;
return action(a, b, c);
};
}
- 마찬가지로 멀티쓰레드 환경에서는 주의 해야함
- 타임라인이 액션을 공유하고 협력하는 방법
- 모든 언어는 암묵적으로 시간에 대한 모델 보유
- 순서와 반복
JavaScript의 시간 모델
- 순차적 구문, 순차적 실행
- 두 타임라인의 단계는 왼쪽 or 오른쪽 이 먼저 실행됨
- 비동기 이벤트는 새로운 타임라인
- 액션은 호출할때마다 실행
함수형 개발자는 요구사항에 맞는 실행 방식에 가까운 시간 모델을 만든다
- 비동기콜백의 경우, 여러 타임라인을 방지하고자, 큐를 생성
- 여러번 호출되어도 한번만 호출되는 액션 -> 즉 함수형 개발자는 시간 모델을 다룬다
- 타임라인 수를 줄입니다
- 스레드나 비동기 호출, 서버 요청을 줄여 적은 타임라인을 만들면 시스템이 단순해딘다.
- 타임라인 길이를 줄이자
- 타임라인에 있는 액션을 줄이고, 액션을 계산으로 바꾸자
- 공유 자원을 없애자
- 자원을 공유하지 않는 타임라인은 순서 문제가 생기지 않는다. 가능한 단일 스레드에서 공유자원에서 접근하자
- 동시성 기본형으로 자원을 공유한다
- 큐나 락을 사용해서 안전하게 공유할 수 있는 방법을 사용하자
- 동시성 기본형으로 조율하자
- 타임라인을 조율하기 위해, Promise나 컷과 같은 것으로 액션에 순서나 반복을 제한하자
- 두 타임라인이 협력할수 있는 동시성 기본형을 사용하여, 타임라인을 조율
- 언어가 제공하는 암묵적 시간모델 대신 새로운 시간 모델을 만들어 사용
- 타임라인을 조율하기 위해 동시성 기본형 생성, 가능한 순서를 제한해 올바른 결과가 나오도록 사용
- 타임라인을 나누는것도 타임라인을 조율하는 방법 중하나, 컷은 모든 타임라인의 작업이 끝날때 까지 기다려, 새로운 타임라인이 시작할수 있도록 도와준다.
질문 및 소감
멜리님 : 개발할 때 타임라인을 제대로 고려하지 않으면, 다양한 문제가 발생할 수 있다는 것을 알게 되었습니다. 저는 cut()이라는 걸 처음 봤는데,이게 혹시 대중적으로 사용되나요?
- 타임라인의 Cut의 역할을 사용하는 Promise.all , Rx의 zip , 코루틴 등등을 활용
마크님 : Cut 이라는 함수를 통해서 어떤 메세지를 주려고 하는건지는 알겠는데 코드 예시를 semaphore를 사용하는 나쁜 예시처럼 보여서 좀 의미가 퇴색되는 거 같네요…
신기 : 파이썬에서 cut과 같은 기능을 하는건 asyncio.gather 라는게 있습니다.(이름이 달랐던거같은데 지금 찾아보니 이거로나오네요….) https://docs.python.org/ko/3/library/asyncio-task.html#running-tasks-concurrently