- heap : 메모리 할당이 일어난다.
- call stack : 스택프레임이 생성되어 호출된 함수들이 쌓인다.
- setTimeOut, DOM, HTTP같은건 V8소스에 없다.
- V8 런타임과 브라우저가 제공하는 웹 API가 존재한다.
- 브라우저는 DOM, AJAX, timeout, callback queue, event loop를 가지고 있다.
- JS : 기본적으로 싱글스레드 런타임을 가지고 있다.
- 즉, 하나의 콜 스택을 가지고 있다.
- ex : 제곱을 출력하는 기능을 만든다.
- 구성함수들
- 곱하기 (a, b) => a * b;
- 제곱 (n) = > 곱하기 (n, n);
- 제곱출력기 (n) => console.log(제곱(n));
- 콜스택에서 일어나는 일
- main 함수 push
- 제곱출력기 push
- 제곱 push
- 곱하기 push
- 곱하기 pop
- 제곱 pop
- 제곱출력기 pop
- main pop
- 즉, error로 나오는 stacktrace는 스택의 마지막부터 처음까지 순서로 나온다.
- StackOverflow는 이 콜 스택이 까아득 찼다는 뜻이다.
- 블로킹 : 느린 동작이 스택에 들어있다? => 블로킹!!
- getSync가 콜스택에 연속적으로 들어간다?
- 웹에서 동작을 받을 때 까지 스택에 담아 기다리고, 다음 동작을 한다.
- 연속적으로 3개를 받고, 받은 것들을 출력한다면?
- 동기적으로 동작하면 해당 동작들을 기다려야 한다.
- 반복문들이 동기적으로 동작되기 때문에, 사용을 지양하고 재귀로 처리하라고 하는 것이다.
- 동기적으로 실행되는 네트워크 요청이 콜 스택을 블로킹한다.
- 브라우저가 다른 일을 못한다.
- 결국, 느려진다.
- 해결책 : 비동기 콜백
- 코드를 실행하면 콜백을 받고, 나중에 콜백받은 코드들을 실행시키는 방식이다.
- 아래의 코드를 보았을 때, 출력과 콜 스택을 생각해보자.
- 어떻게 이렇게 되는거여?
- 출력
- 콜스택
- main push
- console.log('hi') push
- console.log('hi') pop
- setTimeout(cb, 5000) push
- setTimeout(cb, 5000) pop
- console.log('janghee') push
- console.log('janghee') pop
- main pop
- console.log('there') push
- console.log('there') pop
console.log('hi');
setTimeout(function () {
console.log('there');
}, 5000);
console.log('janghee');
- 이벤트 루프, 동시성 역할
- 브라우저는 단순 런타임 이상을 의미한다.
- JS는 싱글 스레드로 동작하지만, 웹 API들이 있다
- 얘네가 스레드를 지원한다.
- 백엔드에서는 C++ API가 지원한다.
- 아까 봤던 setTimeout의 기능을 조금 설명하면
- function : 콜백 함수
- 5000 : ms(즉, 지금은 5000ms, 5초)
- 그러면 저 카운트는 어디서 일어나고, 어떻게 다시 콜 스택에 들어올까?
- webAPIs, 태스트 큐를 이용한다.
- setTimeout이 호출되면 아래와 같이 동작한다.
- 콜 스택에 담는다.
- web API에서 타임아웃에 명시된 시간만큼 타이머를 걸어둔다.
- 콜 스택에서 빼낸다. (이후, JS는 할 일을 한다.)
- web API에서 타이머가 끝났다면, 태스크 큐에 해당 콜백 함수를 push한다.
- 여기에서 이벤트 루프가 일한다.
- 위에서 태스크 큐에 있는 함수와 콜 스택을 확인한다.
- 콜 스택은 비어있고, 태스크 큐에는 콜백 함수가 하나 존재한다.
- 태스크 큐를 poll해서 콜 스택에 push 해준다.
그러면 setTimeout에서 콜백 시간을 0으로 주면 왜그러는걸까?
- 기본적으로 이벤트 루프는 콜 스택이 비어있을 때, 태스크 큐의 데이터를 앞에서 하나씩 스택에 push한다.
- 결국, 타임 딜레이만 없을 뿐, 순서에 대한 딜레이를 줄 수 있다.
- 또한, setTimeout을 이용한 시간은 정확하게 딜레이를 주는 것이 아니다.
- 딜레이는 web API에서 대기하는 시간일 뿐, 실제 실행은 더 걸릴 수 있다.
- 일반 반복문으로 해당 과정을 처리시키면 시간이 오래걸린다
- ex : forEach
- 배열에 forEach로 원소마다의 처리가 오래걸리는 동작이라면, 전체적인 과정이 오래걸리게 된다.
- 이 때 async forEach를 처리해준다면, 더 빠르게 이를 처리할 수 있다.