꼬꼬마 블로그

꼬꼬마의 기술 블로그

평소 비동기를 잘 처리하기 위해서 고민합니다. 그러다 오늘 코딩 테스트에서 비동기 처리에 관한 문제가 나왔습니다. 그리고 제가 아직 부족하다는 것을 느껴 글로 정리해 보았습니다.

 

비동기

Promise, Async, Await에 대한 기본적인 내용은 아래 글을 통해 확인할 수 있습니다.

 

[JS] Promise, Async, Await 비동기 처리

제가 JS를 처음 접하고 비동기에 대한 개념을 몰라 많이 삽질했던 기억이 있습니다. const a = getUser(); console.log(a); 해당 코드는 getUser 라는 메소드를 실행 시킨 후 console.log를 찍습니다. 물론 회원정

wlswoo.tistory.com

 

앞으로 사용할 간단한 코드를 먼저 설명하도록 하겠습니다.

async function asyncHello() {
  return new Promise(resolve => setTimeout(() => {
    console.log('hello');
    resolve();
  }, 200))
}

async function main() {
  await asyncHello();
  console.log('end');
}

main();

// 결과
// hello
// end

위와 같이 asyncHello는 0.1초 후 hello를 출력합니다. 그리고 Promise를 반환합니다.

 

main은 await 키워드를 사용하기 위한 async 함수입니다.

 

병렬 처리

기존 처리

반복을 통해 비동기를 처리해야된다면 보통 아래와 같이 사용할 것입니다.

async function asyncHello(number) {
  return new Promise(resolve => setTimeout(() => {
    console.log('hello ' + number);
    resolve();
  }, 200))
}

async function main() {
  console.time();
  for (var i = 0; i < 10; i++) {
    await asyncHello(i);
  }
  console.timeEnd();
}

main();

 

위와 같은 코드는 아래와 같은 결과를 보여줍니다. (시간 로그를 제거한 결과입니다)

 

 

각 함수가 0.2초 간격으로 실행되는 것을 확인할 수 있습니다.

 

 

시간도 총 2.046초가 결렀습니다.

만약 이 함수를 100번 1000번 실행한다면 전체 실행 시간은 더 많아지겠죠? 위와 같은 코드는 ESLint에서도 권장하지 않는 방식입니다.

 

비동기를 더 잘 다루기 위해서는 이런 비동기 처리는 병렬로 처리해야 합니다.

 

병렬 처리

async function asyncHello(number) {
  return new Promise(resolve => setTimeout(() => {
    console.log('hello ' + number);
    resolve();
  }, 200))
}

async function main() {
  console.time();

  const promises = [];
  for (var i = 0; i < 10; i++) {
    promises.push(asyncHello(i));
  }
  await Promise.all(promises);

  console.timeEnd();
}

main();

위와 같이 Promise.all이라는 메서드를 이용하여 병렬로 처리했습니다.

 

 

아까와 달리 0.2초의 간격이 없어진 것을 확인할 수 있습니다.

 

 

시간도 굉장히 단축되었습니다.

Promise.all은 Promise 배열을 매개변수로 받은 후 병렬로 처리합니다. 그 후 결과 배열의 Promise를 반환합니다.

 

async function asyncHello(number) {
  return new Promise((resolve, reject) => setTimeout(() => {
    if (number == 3) {
      reject();
    }

    console.log('hello ' + number);
    resolve();
  }, 200))
}

async function main() {
  console.time();

  const promises = [];
  for (var i = 0; i < 10; i++) {
    promises.push(asyncHello(i));
  }
  await Promise.all(promises);

  console.timeEnd();
}

main();

만약 위와 같이 하나라도 거부된다면 모두 거부로 처리됩니다.

 

Promise.all 비동기 함수의 순차적 실행 순서를 보장하지 않습니다.

 


참고자료

blog.woolta.com/categories/3/posts/138