날아라김지원
article thumbnail

자바스크립트

자바스크립트는 코드가 작성된 순서대로 작업을 처리하는 동기적 언어

이전 작업이 진행 중 일 때는 다음 작업을 수행하지 않고 기다린다.

먼저 작성된 코드를 먼저 다 실행하고 나서 뒤에 작성된 코드를 실행한다.

 

만약 이와같이 중간에 특정작업이 오래걸리면 전반적인 흐름이 느려진다.

 

이와같이 멀티 쓰레드 방식으로 작동한다면 작업 분할이 가능하지만 자바스크립트는 싱글 스레드 언어이다.

 

비동기 작업

씽글 쓰레드 방식을 이용하면서 동기적 작업의 단점을 극복하기 위해 여러개의 작업을 동시에 실행시킨다.

먼저 작성된 코드를 기다리지 않고 바로 다음 코드를 실행하는 방식

 

대표적으로 setTimeout함수가 비동기 방식으로 동작하는 함수이다.

function taskA(a, b, cb) {
  // cb는 콜백함수
  setTimeout(() => {
    const res = a + b;
    cb(res);
  }, 3000);
}

taskA(3, 4, (res) => {
  console.log("A Task Result", res);
});
console.log("코드 끝");
//


코드 끝 
A Task Result

이와같이 비동기를 구성할 수 있고

 

function taskA(a, b, cb) {
  setTimeout(() => {
    const res = a + b;
    cb(res);
  }, 3000);
}

function taskB(a, cb) {
  setTimeout(() => {
    const res = a * 2;
    cb(res);
  }, 1000);
}

taskA(3, 4, (res) => {
  console.log("A Task Result", res);
});

taskB(7, (res) => {
  console.log("B Task Result", res);
});
console.log("코드 끝");
//

코드 끝 
B Task Result 
14
A Task Result 
7

위에 함수도 이와같은 실행 순서를 보인다.

 

function taskA(a, b, cb) {
  setTimeout(() => {
    const res = a + b;
    cb(res);
  }, 3000);
}

function taskB(a, cb) {
  setTimeout(() => {
    const res = a * 2;
    cb(res);
  }, 1000);
}

function taskC(a, cb) {
  setTimeout(() => {
    const res = a * -1;
    cb(res);
  }, 2000);
}

taskA(3, 4, (res) => {
  console.log("A Task Result", res);
});

taskB(7, (res) => {
  console.log("B Task Result", res);
});

taskB(14, (res) => {
  console.log("C Task Result", res);
});
console.log("코드 끝");

최종적으로 이 코드도 

코드끝 -> B -> C ->A 순으로 실행되는것을 볼 수 있다.

 

자바스크립트 엔진 동작원리

기본적으로 힙과 콜스택 두가지로 구성 되어있고

힙은 변수나 상수들에 사용되는 메모리가 저장되는 부분이다.

중요한 부분은 콜스택 부분!

 

이와같이 Call Stack에 누적되어 마지막것부터 실행이 된다.

 

그리고 비동기 방식을 포함한 전체적인 동작방식이다.

setTimeout은 Web APIs로 빠지게 되고 콜스택에 남아있는 가장 위에 있는 asyncAdd()부터 실행되고 

콜스택에서 제거가 된다.

 

그다음 cb() 함수가 콜백큐로 넘어온다음 다시 이벤트 루프를 통해

콜스택으로 이동된다.(Main Context가 없어질 때 까지 계속 삭제)

 

원하는 순서대로 실행하고 싶다면?

function taskA(a, b, cb) {
  setTimeout(() => {
    const res = a + b;
    cb(res);
  }, 3000);
}

function taskB(a, cb) {
  setTimeout(() => {
    const res = a * 2;
    cb(res);
  }, 1000);
}

function taskC(a, cb) {
  setTimeout(() => {
    const res = a * -1;
    cb(res);
  }, 2000);
}

taskA(4, 5, (a_res) => {
  console.log("A Result", a_res);
  taskB(a_res, (b_res) => {
    console.log("B Result :", b_res);
    taskC(b_res, (c_res) => {
      console.log("C Result : ", c_res);
    });
  });
});

console.log("코드 끝");

A Result 
9
B Result : 
18
C Result :  
-18

이런식으로 함수안에 콜백안에 콜백안에 넣어줘서 실행해줄 수 있다. 하지만 갯수가 점점더 많아지면

유명한, 이러한 콜백 지옥이 생긴다. 그래서 생긴 방식이

 

Promise이고 그 Promise를 좀더편하게 쓰기위한 async / await가 있다.

 

이어서 기록해보자

profile

날아라김지원

@flykimjiwon

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!