[Node.js] 여러 개의 계산 중, 내가 원하는 조건이 되었을 때 함수를 불러와서 호출 스택의 가장 위에 놓는 방법.
조회수 626회
안녕하세요.
궁금한 점이 있어 이렇게 질문을 올립니다.
먼저 코드로 설명을 해보겠습니다.
function a(){ // 한 번 도는데 100~150 ms 걸리는 함수. for에서 시간이 많이 걸림.
for(){
// 계산, 계산, 계산........
if( 계산 도중 조건을 만족 ){
b(); // func b()를 호출
};
};
};
function b(){
c(()=>{
d(()=>{
console.log('도착!');
});
};
};
function c(callback){
callback(null);
};
function d(callback){
callback(null);
};
// Run
setInterval(()=>{
a(); // func a()를 호출하여 시작
}, 200);
위와 같은 형태의 프로그램을 만들었는데 몇가지 궁금증이 생겨서 질문을 올립니다.
Q.질문
- 위의 프로그램에서 a()에서 조건 만족시 b()를 호출했을 때 b(),c(),d()가 각각 호출 스택(call stack)의 제일 위에 쌓이게 되는 건가요?
- 혹시 제일 위에 쌓이지 않는다면 d()가 테스크 큐(task queue)에 쌓여 느려질 것이라 생각되는데 맞나요?
만약 위의 두 개 다 틀렸다면 b(),c(),d()를 호출 스택(call stack)의 가장 위에 쌓는 방법을 알고 싶습니다.
현재 제가 가진 문제는 b()를 개별적으로 호출 했을 때와 위처럼 a() 실행 안에서 실행했을 때 호출되는 속도가 차이가 나는 게 문제입니다.
p.s. 코드를 위와 같이 작성한 이유는 callback에서 response를 받아서 처리해야 하는 부분이 있기 때문입니다.
1 답변
-
1.
200ms 이후에 a가 실행되며 a가 콜스택에 쌓입니다. 조건을 만족하면 (익명함수 제외) b,c,d가 추가적으로 콜스택에 쌓이는게 맞습니다.
그런데 a라는 함수의 실행시간이 interval로 지정한 200ms보다 크게 되면 콜스택이 비는 가장 빠른 타이밍(이 전 b,c,d가 모두 끝난, a함수 종료 시점)에 실행을 할 뿐, 다음 a함수 콜을 200ms 에 딱 맞추어 overlap 하여 실행하지 않습니다. 이는 메인 코드를 실행하는 쓰레드는 하나라는 특성에 기인합니다.
위에 제가 단 댓글에도 언급해 드렸듯, a라는 함수의 수행시간이 200ms가 넘어가게 되면 그 시점에는 주기가 200ms가 아닐 수 있다는 말입니다.
2.
setInterval은 함수 구현 특성상 한 번에 하나의 함수만을 실행하게 됩니다. 즉, 이 전의 호출이 끝나기 전까지 시간이 만료되었다 하더라도 다음 호출은 발생하지 않아요. 때문에 위 로직에서는 어딘가에 함수 콜이 쌓여 느려질 것을 염려하실 필요는 없습니다. 만약 애초에 그렇게 쌓일 상황이었다면 call stack이 넘쳤다는 에러(maximum call stack size exceeded)를 먼저 보셨을 겁니다.
아무튼, 코드는 절대 병렬 실행되지 않습니다. a함수는 콜스택에 쌓이고 내부에서 호출하는 함수들도 순차적으로 쌓입니다. 그리고 역순으로 비워집니다. 모두 비워지고 나서야 다음 a함수 콜이 콜스택에 쌓이게 됩니다. 이 일련의 함수 호출이 하나의 묶음으로 동작하기 때문에 다음 차례의 b,c,d가 이전 a함수 실행 도중에 끼어들어 먼저 실행될 수 없습니다.
만약 b,c,d 함수중 하나라도 async 함수가 있다면 얘기는 좀 달라질 수 있겠네요. 200ms가 넘어가는 주기가 계속되거나 비동기 콜백이 늦게 호출되는 상황이면 특정 시점에 호출이 몰린다거나 호출 순서와 상관없이 콜백이 실행되는 상황... 이래저래 더 복잡해지겠죠. (이건 생각하기도 싫네요. ㅎ)
댓글 입력