티스토리 뷰

자바스크립트 동작 (왜 비동기로 작동하는가?)

자바스크립트는 싱글 스레드다. 하나의 스레드로 모들 일을 해야 한다.

따라서 일을 하던 중 시간이 오래 걸리는 작업(API 통신, setTimeout 등)을 만났을 때, 이 작업을 끝까지 기다리게 되면 그동안 다른 일을 못하게 된다. 이는 굉장히 비효율적이고 느리기 때문에 자바스크립트는 비동기식으로 일을 진행한다. 즉 오래 걸리는 작업은 요청만 해놓고 그동안 다른 일을 하는 것이다.

 

 

아래 장보기 예제를 보자 (각 가게로 이동하는 시간은 0분이라고 가정)

 

내가 장을 보는데 다음과 같은 순서로 행동했다면

  1. AM 11:00 떡집 도착 후 떡이 만들어지는 동안 30분 대기 후 수령
  2. AM 11:30 야채가게 도착 후 물건 고르는데 20분 소요

장보기를 마무리했을 때 시간은 AM 11:50일 것이다.

 

하지만 다음과 같은 순서로 행동했다면

  1. AM 11:00 떡집 도착 후 떡이 완성되면 전화 달라고 하고 야채가게 이동
  2. AM 11:00 야채가게 도착 후 물건 고르는데 20분 소요
  3. AM 11:30 떡집에서 완성된 떡 수령

20분을 절약할 수 있다.

 

 

자바스크립트도 위와 같이 실행 시간을 최소화하고 효율적으로 동작하도록 설계되어 있다.

자바스크립트에서 비동기를 다룰 수 있는 방법은 (작성일 현재) Callback, Promise, Async-Await 세 가지가 있다. 장보기 예제를 간단한 코드로 작성하여 원리를 알아보자.


Callback

자바스크립트는 함수를 파라미터로 전달할 수 있고 이를 활용하여 callback 함수를 구현한다. riceCakeStore 호출 시 callback 함수를 전달하고, riceCakeStore 함수에서 모든 작업을 마치고 callback 함수를 실행해준다.

function riceCakeStore (callback) {
  setTimeout(function () {
    callback('떡 완성')
  }, 3000);
}

console.log('떡집 도착')

riceCakeStore(function (result) {
  console.log(result)
})

console.log('야채가게 도착')

참고 : https://developer.mozilla.org/en-US/docs/Glossary/Callback_function


Promise

ES6 (2015)에서 추가된 기능이다.

riceCakeStore 함수 실행 시 Promise 객체를 리턴하고, Promise가 완료(resolve)되었을 때 .then 메서드를 실행한다.

function riceCakeStore() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('떡 완성');
    }, 3000);
  });
}

console.log('떡집 도착')

riceCakeStore().then(result => {
  console.log(result);
})

console.log('야채가게 도착')

참고 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise


Async Await

ES8 (2017)에서 추가되었다. Promise의 복잡한 구조를 더 간결하게 표현할 수 있다.

await와 함께 riceCakeStore 함수를 실행하면 이 함수는 async 범위 안에서 동기식처럼 작동한다. (riceCakeStore 함수의 모든 작업이 끝나기를 기다린 후 결과 값을 result 함수에 할당된다.)

※ await는 async와 함께 사용해야 한다.

function riceCakeStore(n) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('떡 완성');
    }, 3000);
  });
}

console.log('떡집 도착')

async function request() {
  let result = await riceCakeStore();
  console.log(result)
};
request();

console.log('야채가게 도착')

참고 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/await


위 예제는 원리를 파악하기 위해 매우 간략하게 작성된 코드로 예외 및 에러 처리 등은 모두 생략되어 있다. 각 코드의 참고 URL을 꼭 확인해야 한다.

또한, 위 3가지 방법 중 좋고 나쁜 것은 없다. 상황에 따라 적절하게 사용하면 된다.

댓글