# 강남_M_Day14 리뷰 레포트 ### 참석자 - 나영균, 우연서, 이상아, 한혜경 ## 1. 코드 동작 이해 - index.js가 Manager에게 주문과 바리스타 명수를 전달한다. - Manager가 바리스타를 명수대로 고용하고 각각의 바리스타에 주문을 차례대로 할당하고 완료되면 어떤 행위를 할지 설정한다. - 각각의 바리스타가 주문을 완료할 시 index.js는 주문을 html 요소를 만들어 append한다. - 주문이 완료될때마다 매니져는 마지막 주문인지 확인하여 완료된 주문을 넘길시 index.js에게 마지막 주문 여부를 함께 넘겨준다. - index.js는 마지막 주문시 manager를 terminate해준다. - manager.js와 worker.js를 모두 만들었지만 manager.js에서 worker를 embed형식으로 구현할 수 도 있다. - DOMContentLoaded 이벤트를 사용하여 코드를 로드시킬 수 있다. ## 2. 코드 동작 개선 ### 나영균 - import와 export를 이용하여 utils.js를 이용하는 방법으로 개선해야 하겠다. - 설계에 더 신경써서 모듈화가 조금 더 의미를 가지는 모듈화를 진행해봐야 겠다. - manager가 terminate되는 방식으로 바리스타를 퇴근시키는데 만약 큐가 다 비워지면 차례대로 close()하는 방법또한 고려해 볼 수 있겠다. ### 우연서 - 매니저가 일을 배분하는 부분에서 함수를 더 나누어서 진행 할 수 있을 것 같다. - 메뉴 증가의 경우 어떻게 처리할 것인지 생각해보면 좋을 것 같다. ### 이상아 - manager가 barista에게 일을 시킬 때, barista의 status(idle/busy)를 보고 판단하면 보다 직관적일 것 같다. - barista list를 미리 만들어놓고, 일을 시킬 때 재할당을 하는데, 이 부분을 재사용하도록 구현하면 좋을 것 같다. ### 한혜경 - manager worker를 따로 안 만들고 order 리스트를 반복하면서 barista worker에 할당했다. worker를 이용해서 모든 order 리스트를 manager에 넘기고 worker끼리 작업을 주고 받고 하도록 작업한 뒤 마지막 작업에 대한 체크를 해주면 좀 더 수월하게 음료 주문 완료에 대한 문제를 해결할 수 있었을 것 같다. 클래스로 짜거나 함수를 더 세밀하게 쪼개서 코드를 정리하는 것도 필요하다. --- ### 나영균 - 스스로 확인할 사항 - **멀티 스레드 스케줄링 방식에 대해 학습한다.** - 스레드 스케줄링 - 스레드의 개수가 코어의 수보다 많을 경우, 스레드를 어떤 순서에 의해 동시성을 실행할 것인가를 결정해야하는데 이것을 스레드 스케줄링이라 부른다. - **스레드 스케줄러**에 의해 여러 스레드들이 아주 짧은 시간동안 번갈아가면서 작업한다. - 스레드 스케줄링 방식 - **선점형 스레드 스케줄링** 방식은 스레드들이 우선권을 가지고 우선순위가 높은 스레드가 먼저 수행하는 방식이다. - **순환할당**(Round-Robin)방식은 시간 할당량을 정해서 하나의 스레드를 정해진 시간만큼 실행하고 다시 다른 스레드를 실행시키는 방식이다. 모두가 같은 할당량을 받기때문에 코드로 우선순위를 제어할 수 없다. - **협력형 스레드 스케줄링** 방식은 실행중인 스레드가 CPU 사용권을 다른 스레드에게 넘길때 까지 기다리는 방식이다. - 스레드 스케줄러 - 멀티 스레드가 수행될 때 어떤 스레드가 먼저 수행 될지는 스레드 스케줄러가 정한다. - 동일한 작업을 하는 스레드의 작업비교 |구분|설명| |---|---| |싱글코어|싱글코어에서 동시성으로 실행할 경우 우선순위가 높은 스레드가 더 많은 실행기회를 가지기 때문에 우선순위가 낮은 스레드보다 먼저 계산 작업을 종료하게 됩니다.| |n코어|멀티코어에서 작업할 경우 n개의 스레드가 병렬성 작업을 수행하기 때문에 n개 이하의 스레드를 실행할 경우 우선순위에 크게 영향을 받지 않는다. 최소한 5개 이상의 스레드가 실행되어야 우선순위의 영향을 받는다.| - **스레드 동작 방식과 바리스타 작업 방식에 대해 비교한다.** - 실제 스레드 동작에는 우선순위가 높은 스레드가 존재하며 그것이 더 많이 실행 될 수 있다. - 미션에서는 바리스타의 작업은 우선순위가 존재하지 않는다. - 큐에 쌓여있는 순서가 우선순위를 의미할 수 있겠다. - 스레드 스케줄러가 스레드를 할당하는 것은 매니져가 바리스타에게 일을 할당하는 것과 비교해볼 수 있다. - 미션에서 구현한 것은 Round Robin 방식이 아니라 작업이 끝날때까지 실행되는 방식이다. - **Web Worker(또는 Worker Thread)에서 사용하지 않은 기능에 대해 학습한다.** - importScripts() - 전역의 함수들에 대한 엑세스를 가질 수 있다. - 이를 이용해 JSONP요청을 할 수 있다. ```javascript importScripts('foo.js'); importScripts('foo.js', 'bar.js'); importScripts('//example.com/hello.js'); // Anti example ``` - embedded workers - 따로 js파일을 생성하지 않고 worker 생성하는 방법 ```javascript function fn2workerURL(fn) { var blob = new Blob(['('+fn.toString()+')()'], {type: 'application/javascript'}) return URL.createObjectURL(blob) } ``` - Checking availability - 브라우저가 web worker를 지원하는지 체크한다. ```javascript if ( !!window.Worker ) { ... // 브라우저가 지원한다면 구현 } ``` - Stop worker internally - 외부에서 worker.terminate()도 가능지만 worker 내부에서 close()도 가능하다. - Error Handling - worker에서 발생한 에러를 외부에서 처리할 수 있다 ```javascript worker.onerror = function(err){ err.filename // 파일이름 err.lineno // 에러 발생 라인 넘버 err.message // 에러 메세지 } ``` - **setTimeout 내부 동작 방식에 대해 학습한다.** - setTimeout은 처음 실행되면 callstack에 등록되어 callback을 Timer API에 보내고 바로 callstack에서 내려온다. - Timer API는 설정된 시간이 지나면 callback을 Event Queue에 등록해준다. - 시간을 재는 행위는 비동기로 이루어진다. - Event Loop은 callstack이 모두 비게 되면 Event Queue의 task들을 하나씩 callstack에 등록하여 실행하는데 이때 setTimeout이 등록한 callback을 실행하게 된다. ### 우연서 - 스스로 확인할 사항 - 멀티 스레드 스케줄링 방식에 대해 학습한다. - 멀티스레드로 작업을 하는 경우 여러 문제를 만날 수 있다. 교착상태나 무한대기상태가 대표적인데 이러한 부분들을 방지하기 위한 것이 스케줄링 방법이다. - 스케줄링 방법으로는 우선순위방법으로 개발자가 직접 우선순위를 부여하는 방법, 시간할당방법(Round Robbin)으로 돌아가면서 스레드에게 접근 권한을 주는 방식이 있다. - 스레드 동작 방식과 바리스타 작업 방식에 대해 비교한다. - 현재 바리스타 작업의 경우 먼저 들어온 것을 먼저 작업하게 우선순위를 주고 있다. 가장 먼저 들어온 주문이 가장 우선순위를 가진다. - Web Worker(또는 Worker Thread)에서 사용하지 않은 기능에 대해 학습한다. - Audio Workers는 스크립트를 통한 직접적인 오디오 처리를 Web Worker에서 처리할 수 있도록 함 - Shared worker는 Worker가 동일한 도메인 내에 존재하는 여러 script에 의해 공유가능. - worker.onerror 워커의 에러처리 기능. - close : 워커 스스로 종료되게 하며, Worker 객체의 terminate()와 비슷하다. - setTimeout 내부 동작 방식에 대해 학습한다. - setTimeout이 콜스텍에 등록된다. - API에서 타임아웃이 완료되면 콜백을 이벤트큐에 등록한다. - 콜스텍이 모두 비면 콜백을 콜스텍에 등록해서 콜백을 실행한다. ### 이상아 - **스스로 확인할 사항** - **멀티 스레드 스케줄링 방식에 대해 학습한다.** - 일반적으로 하나의 프로세스는 하나의 스레드를 갖는다. 이와달리 멀티 스레드란, 하나의 프로세스가 여러 스레드를 갖는 것을 말한다. - 또한 스레드는 CPU 코어 실행의 단위이다. - 따라서 동시에 여러개의 CPU 코어를 사용하여 처리하는 방식을 멀티 스레드라고 한다. [출처 - TCP school](http://tcpschool.com/java/java_thread_multi) - 하지만 스레드의 갯수가 CPU 코어의 갯수보다 많다면, 어떤 일을 먼저 해야할 지 정해주어야 한다. 이것을 **스레드 스케줄링** 이라고 한다. [출처 - 티스토리 블로그](https://codedragon.tistory.com/5346) - 우선순위를 기준으로 하는 Priority 방식과 주어진 시간을 기준으로 하는 Round-Robin 방식이 있다. [출처 - 네이버 블로그](https://m.blog.naver.com/PostView.nhn?blogId=qbxlvnf11&logNo=220837131449&proxyReferer=https%3A%2F%2Fwww.google.com%2F) - **스레드 동작 방식과 바리스타 작업 방식에 대해 비교한다.** - (나의 코드는 그렇지 않지만 올바르게 작동하였을 경우) - 대게 스레드의 동작 방식은 선점형이나, 바리스타의 작업 방식은 비선점형이다. 왜나하면 음료를 다 만든 다음에, 다음에 만들 음료를 주기 때문이다. - **Web Worker(또는 Worker Thread)에서 사용하지 않은 기능에 대해 학습한다.** - 에러 처리 `preventDefault()` - 스크립트 임포트 `importScripts()` - `SharedWorker` - **setTimeout 내부 동작 방식에 대해 학습한다.** 1. call stack에 `setTimeout()` 이 들어간다. 2. call stack에서 빠지고, web API로 넘어간다. 3. web API에서 처리가 끝난 후, event queue로 `setTimeout()`의 `callback function`이 들어간다. 4. event loop가 call stack과 event queue를 주시하다가, call stack이 비었을 경우 event queue의 것을 call stack으로 옮겨준다. 5. setTimeout()의 `callback function`이 실행된다. ### 한혜경 - 스스로 확인할 사항 - 멀티 스레드 스케줄링 방식에 대해 학습한다. - 하나의 프로그램 안에서 병렬 처리. 하나의 코어에 대한 이용성을 증가하는 것에 초점을 둔다. - FIFO(First In First Out) 스케줄링: Day14 미션에서 사용한 방식. worker를 계속 체크하여 먼저 들어와 있는 worker에게 다음 작업을 할당하는 비선점 방식이다. - 우선순위(Priority) 스케줄링: 각 작업마다 우선순위가 있고,우선 순위가 제일 높은 작업에 먼저 CPU가 할당 - SJF(Shortest Job First) 스케줄링: 처리해야할 작업 시간이 가장 짧은 작업부터 할당 >출처 [열망하다 - 스케줄링 기법과 종류](https://m.blog.naver.com/bestheroz/105116025) - 스레드 동작 방식과 바리스타 작업 방식에 대해 비교한다. - 메인 스레드가 아닌 백그라운드 스레드에서 작업되고 각각의 스레드가 맡은 작업을 실행한다. 바리스타의 경우 설정한 바리스타 수만큼의 스레드가 백그라운드에 생성되고 setTimeout의 영향은 각각의 바리스타 스레드에만 적용될 뿐 모든 바리스타에게 적용되는 것이 아니다. - Web Worker(또는 Worker Thread)에서 사용하지 않은 기능에 대해 학습한다. - onerror: 런타임 오류가 발생했을 때 호출하는 이벤트 핸들러 ```js const worker = new Worker('worker.js'); worker.onerror = function(err){ console.log(err.filename); console.log(err.lineno); console.log(err.message); } ``` > 출처 [My Piece(Life) - 간단한 웹 워커(Web Worker) 사용하기](https://bit.ly/2Zz5gOG) - setTimeout 내부 동작 방식에 대해 학습한다. - 지정한 타이머가 만료된 뒤 함수나 지정된 코드를 실행. - setTimeout이 실행되면 call stack에 들어갔다가 바로 web API 영역으로 넘어가서 타이머가 실행된다. 타이머가 만료되면 지정한 콜백 함수를 task queue에 넘기고 event loop가 call stack이 비어있는지 체크해서 비어있으면 task queue의 첫번째 요소부터 보내고 call stack은 그 함수를 받아 실행시킨다. ## 3. Consideration ### 다같이 확인할 사항 #### setTimeout 이 외에 timer를 구현하기 위한 여러 방식에 대해 학습한다. - Date.now()와 while문으로 timer를 구현할 수 있다(동기). - setInterval도 setTimeout과 같이 timer를 구현할 수 있으며 계속해서 시간마다 박복해야 하는 경우 사용하면 좋다(비동기). - 블로그들에서 Promise와 Async await등을 사용하는 방법들을 이야기하지만 결국에는 setTimeout을 사용하는 방법이다. - w3c를 봐도 브라우저의 Timer API를 사용하는 방법은 setTimeout과 setInterval을 제외하고는 찾을 수 없다. [출처 - W3C:Timer](https://www.w3.org/TR/2011/WD-html5-20110525/timers.html) #### 멀티 스레드가 공용 리소스에 접근할 때 임계구역을 다루는 방식에 대해 학습한다. (Semaphore, Mutex 등) > 임계영역 : 여러 스레드가 동시에 접근 할 수 있는 구역을 임계영역이라고 한다. - 뮤텍스 : 한번에 하나의 스레드만 실행 될 수 있도록 키값을 지정해서 권한을 부여하는 방법. 하나의 키만 가지고 있으며 한 스레드가 키를 가지게 되면 다른 스레드들은 접근이 불가능하다. - 스레드의 접근 권한 제어 ```javascript var flag = 1; // flag가 1이면 접근가능 0이면 접근 불가능 lock() { while(1) { if (v==1) break; } flag = 0; return 1; } unlock() { flag = 1; break; } ``` ```javascript lock(); // 임계영역 작업.. // 임계영역 작업 끝 unlock(); ``` - 세마포어 : 뮤텍스와 유사한 방법으로 동일하나 키의 갯수를 지정 할 수 있는 방식. - 프로세스의 접근 제한 ``` javascript sem_init(semaphore, 0, 2); // 세마포어 객체, 갯수 지정 // thread1, thread2, thread3 sem_wait(); // 세마포어 하나 사용 // 임계구역 작업 // 임계구역 작업 sem_post(); // 세마포어 반납 sem_destroy(); // 세마포어 폐기 ``` #### 멀티 스레드 작업을 그룹으로 묶어서 동기화하는 방식에 대해 학습한다. * 다수의 스레드의 관리를 쉽게 하기 위한 방법이다. (이번 과제에서 Manager가 Barista들을 관리한 방법과 비슷하다고 볼 수 있다) * 스레드 그룹이 필요한 이유는, **다수의 스레드를 만들었을 경우 관리가 어려우며** 각각의 스레드를 지원하는 **자원이 부족**하기 때문이다. * 자바의 경우, 처음 스레드를 생성하면 **main thread group**에 포함이 된다. 이후 thread 그룹이 생성되면, **tree 구조**로 생성된다. ![img](https://t1.daumcdn.net/cfile/tistory/2103073F5901D1BE22) * thread 그룹의 생성 ```java ThreadGroup(String name) ThreadGroup(ThreadGroup parent , String name) ``` * thread에 우선순위 부여 ```java void setPriority(int newPriority); //쓰레드의 우선순위를 지정한 값으로 변경 int getPriority(); //쓰레드의 우선순위를 반환. public static final int MAX_PRIORITY = 10; // 최대 우선순위 public static final int MIN_PRIORITY = 1; //최소 우선순위 public static final int NORM_PRIORITY = 5; //보통 우선순위 ``` * 우선순위 * 10 : 위기관리, 에러관리 * 7~9 : 상호작용, 이벤트 처리 * 4~6 : I/O 관련 작업 * 2~3 : 백그라운드 작업 * 1 : 기타 다른 작업이 있을때 실행 * [출처 - 티스토리 블로그](https://12bme.tistory.com/67)