2 분 소요

JS 동작 원리

앞서 실행 컨택스트를 공부를 했었을 때, 하나의 함수가 실행이 되면 콜 스택에 함수의 실행 컨텍스트가 쌓인다고 공부를 했었다. 스택 이므로 나중에 들어온 것이 먼저 실행이 된다고 공부를 했었다. 이렇게 하나가 콜스택에서 빠져 나와 완료가 되면 다음 컨택스트가 실행이 되는 방식을 싱글스레드라 부른다. 조금 더 내부적으로 살펴 보자.

Node APIs

스택에서 가장 나중에 들어온 컨택스트는 콜 스택에서 빠져나와 어떻게 처리가 될까? 컨택스트는 빠져나와서 Node APIs 라는 곳으로 들어오게 된다. Node APIs가 무엇을 하는 곳일까? 앞서 js의 동작 원리는 싱글스레드로 동작이 된다 라고 언급했었다. 즉, 하나가 실행이 완료 되어야 다음 것을 수행을 할 수 있다는 뜻이다. 이러한 점은 동작 하는데 있어 많은 불편함을 겪을 것이다. 유튜브의 영상을 재생을 시키면 버퍼링이 생기기 마련인데, 영상이 제대로 재생이 될 동안 아무 동작을 할 수 없다는 뜻과 같다. node는 이러한 점을 개선을 하기 위해서 Node APIs 라는 것을 만들었다. 즉, 컨택스트가 들어오면 병렬적으로 실행을 시켜준다는 뜻이다. 이것을 멀티 스레드 동작 방식이라 부른다. 콜스택에 있는 컨택스트의 콜백 함수를 Node APIs에 보내서 병렬적으로 처리를 할 동안 콜스택에서는 다음 컨택스트를 실행을 하여 또 다시 콜백 함수를 보내는 동작을 하게 된다. Node APIs에서 콜백 함수를 처리르 하게 되면 queue에 보내서 완료된 순서대로 실행이 되도록 한다.

동기적

동기적이란 JS와 같이 하나가 실행이 되고 완료가 될 때 까지 다음 일을 처리를 하지 못하는 것을 의미한다. Node.js의 런타임 환경은 위에서 확인 했듯이 멀티 스레드 방식으로 작동을 한다. 하지만 꼭 어떤 함수의 동작이 이전의 함수 동작이 완료한 후에 실행을 하고 싶을 때, 동기적 방식을 사용한다.

async, await

그렇게 하기 위해선 async와 await를 이용 하게 된다. asycn는 함수 식별자 앞에 붙이게 되는데, 이때 이 함수 안에서 동기적 방식을 사용할 것이 있다 라는 것을 의미한다. 동기적 방식을 사용할 함수의 실행 앞에 await를 붙히는데, 이는 이 함수를 동기적 실행을 할 것이다 라는 것을 의미한다.

  • await는 async function 스코프 안에서 실행이 되어야 한다.
async function foo() {
  await abc(); // abc() 완료 할 때 까지 기다려
  bbb();
}

비동기적

비동기적 동작은 앞서 설명 했듯이 병렬적인 컨택스트 실행을 하기위해서 하는 방식이다. promise를 이용하여 사용하게 된다.

promise

promise는 마치 약속을 하는 것과 같다. 약속을 지켰을 때 와 못지켰을 때를 나누어 실행되는 것을 달리 한다. 이를 resole와 reject로 나누게 된다. promise는 class를 생성 했을 때와 같이, promise를 만들고 싶을 때 new 연산자로 만든다. promise의 매개변수로는 resolve와 reject가 있다. 만약 잘 작동을 했다면 resolve 함수가 콜백함수로 나오게 된다.

function promise() {
  return new Promise(resolve, resject) {
    resolve('resolve 함수 실행');    // 잘 이루어 졌을 경우 resolve 함수 리턴
    reject('reject 함수 실행');     // 잘 안됐을 경우 reject 함수 리턴
  }
}

 function callback() {
   promise()
    .then(console.log(ok => console.log(ok)));  // resolve 함수 실행
    .catch(console.log(fail => console.log(fail))); // reject 함수 실행
 }

promise.all

promise all은 단어에서도 알 수 있듯이 들어오는 매개변수를 모두 프로미스로 수행한다는 뜻이다.

  • 매개변수로 들어오는 프로미스를 array 형태로 묶어서 넣는다.
  • 매개변수로 들어온 프로미스가 하나라도 거부 당하면 전체가 즉시 거부.
  • 반환 값은 모든 값을 담은 배열이다.
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "foo");
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]

댓글남기기