woolta

async / await 최적화 방법 (병렬처리)

wooltaUserImgjavaScript | 2019-06-09

**async, await ** 은 비동기 처리를 위해 ES2017 부터 생성된 문법입니다. **async, await ** 을 사용하게 되면 promise 보다 더욱 직관적인 코드를 짤 수 있게 됩니다.

Promise 를 이용한 비동기 처리

function getUsers(){ const users = this.getUsersFromApi() .then(users => { return users; }) }

Promise 를 사용할 경우 callBack을 사용하는 방법보다 훨씬 깔끔하고 직관적인 코딩이 가능합니다. 그러나 async / await을 사용하게 되면 이보다 더욱 간결하게 처리가 가능합니다.

async / await 를 이용한 비동기 처리

async function getUsers(){ const users = await this.getUsersFromApi(); }

다음과 같이 **async / await ** 을 이용하여 더욱 간결하게 비동기 요청을 처리할 수 있습니다.

async / await 을 활용한 반복문 처리

이번에는 async await 을 활용하여 반복문을 처리해보도록 하겠습니다. 우선 비동기 처리를 위해 다음과 같은 비동기 호출 샘플을 먼저 작성하도록 하겠습니다.

function wait(ms){ return new Promise(resolve => setTimeout(resolve, ms)) } async function waitLog(item){ await wait(500); console.log(`waitLog : ${item}`); }

위의 비동기 샘플함수 waitLogsetTimeout 함수를 이용해 강제로 500ms 동안 지연시킨 후 로그를 찍는 간단한 함수 입니다.

forEach 를 사용한 반복 처리

async function AsyncAwaitByForEach() { [1, 2, 3].forEach(async index => await this.waitLog(index)); console.log('end'); };

다음과 같이 forEach 를 사용하여 1,2,3 의 배열을 반복시켜 비동기 처리를 요청하였습니다. 이 경우 콘솔에 찍히는 값은 1, 2, 3 ,'end' 로 찍힐것으로 기대할 수 있습니다.

forEach 함수 실행 결과

https://image.woolta.com/3fc6675ca6f44004.png

oops. 예상했던 것과 달리 end 가 먼저 실행되고 1,2,3 이 실행되는 모습입니다. forEach반복문 전체가 종료되는 것에 대한 결과를 기다려주지 않습니다. 때문에 end 가 먼저 실행되고 나머지 1,2,3 이 순차적으로 실행된 것 입니다.

FOR…OF 를 사용한 반복 처리

위와 같은 경우 때문에 반복문이 끝난 뒤 작업을 해야하는 상황이면 ForEach 가 아닌 For...of 를 사용해서 처리하면 됩니다.

async function AsyncAwaitByForOf() { const arrays = [1, 2, 3]; for (const index of arrays) { await this.waitLog(index); } console.log('end'); }

FOR…OF 함수 실행 결과

https://image.woolta.com/3fbf7255d17f0068.png

원래 기대했던 1,2,3,'end' 순으로 출력되는 모습을 볼 수 있습니다. :)

비동기 병렬 처리를 통한 최적화

async / await을 사용하여 비동기 작업을 배열 로 처리하는 경우 순서가 보장되어야 하는 상황이 아니라면 병렬로 처리해 최적화를 할 수 있습니다.

기존 배열 반복 실행 시간 측정

위에서 사용한 AsyncAwaitByForOf 함수의 수행 속도를 console.time을 사용해 측정해 보도록 하겠습니다. 우선 다음과 같이 측정을 위한 console을 추가합니다.

async function AsyncAwaitByForOf() { console.time("calculatingTime"); const arrays = [1, 2, 3]; for (const index of arrays) { await this.waitLog(index); } console.log('end'); console.timeEnd("calculatingTime"); }

https://image.woolta.com/3feb101df1c4a32b.png

실행시간이 약 1508ms 가 나왔습니다. 한번의 비동기 처리가 500ms 걸리도록 세팅되어 있고 이를 3번 반복한 측정 결과 입니다.

비동기 병렬 처리

mappromise.All 을 사용하게 되면 병렬 처리가 가능해집니다. 우선 map 을 사용하여 Promise를 반환하도록 하고 이를 promise.All로 통해서 한번에 처리하게 하면 순차적인 병렬 처리가 가능합니다.

async function AsyncAwaitByForOfParallel() { console.time("calculatingTime"); const arrays = [1, 2, 3]; const arrayPromises = arrays.map(this.waitLog); await Promise.all(arrayPromises); console.log('end'); console.timeEnd("calculatingTime"); }

https://image.woolta.com/3fdf55c64b46f9d2.png

위와 같이 병렬로 처리할 경우 더욱 빠른 처리가 가능합니다.

참조

javascript-loops-how-to-handle-async-await

async-functions