킹의 개발일지
쏙쏙 들어오는 함수형 코딩 39일차 본문
39일차 <동시성 기본형>
지금까지 타임라인끼리 공유 자원을 줄이는 방향을 배웠다. 저자또한 자원을 공유하지 않는 타임라인이 가장 좋다고 말한다.
하지만 자원 공유가 필요한 경우가 있는데, 이때 자원을 안전하게 공유하기 위한 동시성 기본형(concurrency primitive)이라는, 재사용 가능한 코드를 만드는 방법을 알아보자.
그럼 '안전하게 공유한다' 이 말은 무엇일까, 저자는 '올바른 순서대로 자원을 쓰고 돌려준다' 라고 말한다. 저번 파트에서 만들어본 타임라인 예시를 통해서 안전하게 자원을 공유하는 방법을 알아보자.
저번 파트에서 작성한 타임라인에는 DOM을 공유한다는 문제점이 있다. 저번 파트에서 그린 타임라인을 보면 두 타임라인 모두 마지막에 DOM을 업데이트한다.

이는 잠재적인 문제를 안고 있는데, 첫 번째 DOM 업데이트 액션이 두 번째 보다 나중에 실행되면 올바른 결과를 두 번째 결과가 덮어써버리는 문제를 가진다.
물론 첫 번째 결과를 DOM에 업데이트하고 두 번째 결과로 DOM을 업데이트한다면 문제가 발생하지 않는다. 하지만 두 타임라인에 대한 실행 결과는 예측할 수 없기에 첫 번째 DOM 업데이트가 무조건 먼저 실행 되도록 해결해야한다.
실행순서를 보장한다... '순서' 이 단어를 보면 자료구조를 잘 배우신 분들은 queue가 떠오를 것이다.
맞다. 실행순서 보장을 위해서 저자가 제시하는 방법은 Queue를 사용하는것 이다. queue는 넣은 순서대로 항목을 꺼낼 수 있는 데이터 구조다. 큐를 타임라인 조율에 사용한다면 '동시성 기본형' 이라고 부른다.
이제 저번 파트에서 만들어둔 코드를 토대로 동시성 기본형을 적용해보자.
# 현재 코드
function add_item_to_cart(name, price, quantity) {
cart = add_item(cart, name, price, quantity);
calc_cart_total(cart, update_total_dom);
}
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);
});
});
}
# 새로운 코드
// queue_items, working 변수를 지역변수로 만들기 위해 함수 안에서 큐와 종료조건을 선언.
function Queue() {
var queue_items = [];
var working = false;
function runNext() {
if (working) return; // 두 타임라인이 동시에 실행되는 것을 막음
if (queue_items.length === 0) return; // queue가 비었다면 종료
working = true;
var cart = queue_items.shift(); // queue에서 첫 번째 액션 제거
calc_cart_total(cart, function(total) {
update_total_dom(total);
working = false;
runNext();
});
}
return function(cart) {
queue_items.push(cart);
setTimeout(runNext, 0);
};
}
function update_total_queue(cart) {
queue_items.push(cart);
setTimeout(runNext, 0); // 자바스크립트 이벤트 루프에 작업을 추가
}
var update_total_queue = Queue(); // 리턴된 함수를 원래 함수처럼 쓸 수 있다.
update_total_queue(cart);
// update_total_queue는 작업 큐에 액션을 넣고 순차적으로 실행 시킬 수 있는 함수가 된다.
자, 이제 작성한 코드에 대해서 알아보자.
우선 액션을 넣어줄 '큐 queue_items' 를 둔다. 그리고 setTimeout 메서드를 통해서 이벤트 루프에 DOM 업데이트 작업을 추가한다.
두 타임라인이 동시에 실행되는 것을 막기위해 working이라는 변수를 두어, working이 false일 때만 DOM을 업데이트 할 수 있게 해준다. ( 화장실 들어가서 볼일보기 전에 남이 들어오는걸 막기위해 문을 잠구는 행위라 보면 된다! )
이렇게 하면 콜백으로 넘긴 update_total_dom 작업이 끝난후에 다음 큐에 있는 액션이 실행됨을 보장할 수 있다. (update_total_dom 이 끝난후 working을 false로 둠으로써..)
이번 파트에서는 순서대로 액션이 실행 되도록하는 Queue 함수를 만들어보았다. 다음 파트에서 add_item_to_cart 메서드에서 어떻게 클릭 이벤트를 큐에 넣을지 알아보도록 하자.
타임라인 공유를 안전하기 위해 큐를 쓰는 것을 보고 뒤통수를 한대 탁 맞은 느낌이다. 구현한 코드가, 운영체제의 스케쥴링과 비슷한 느낌을 받았다.
스케쥴러를 구현 할 때도, queue에 작업을 넣고 매 틱마다 cpu가 비었는지 확인하고 비었다면 작업을 실행하고, lock을 걸어 다른 작업이 끼어들지 못하도록 하는 과정이 이번 파트에서 배운것과 다를바가 없었다. 이래서 cs의 중요성을 강조하는거구나 싶었다! (cs 공부도 열심히 해야지ㅠㅠ)
'독서 > 책너두 챌린지' 카테고리의 다른 글
| 쏙쏙 들어오는 함수형 코딩 41일차 (0) | 2023.09.23 |
|---|---|
| 쏙쏙 들어오는 함수형 코딩 40일차 (0) | 2023.09.23 |
| 쏙쏙 들어오는 함수형 코딩 38일차 (0) | 2023.09.20 |
| 쏙쏙 들어오는 함수형 코딩 37일차 (0) | 2023.09.20 |
| 쏙쏙 들어오는 함수형 코딩 36일차 (0) | 2023.09.18 |