async await

async await

es7 공식발표가 되진않았지만 es7에 async와 await 가 잠정적으로 탑재되는 분위기인것 같다 . es6 의 promise가 탑재된듯이 .
필자는 nodejs 개발시 Promise ( bluebird module )를 아주 적극적으로 사용하고있다 . 변화를 느끼고자 이전포스트 Promise ReactiveX
에서 ReactiveX를 사용해보았지만 코드 가독성이 Promise 보다는 떨어지기에 적극적으로 도입하긴보다는 Promise와 적절히 섞어 쓰는것이 좋겠다 라는 결론을 지었다.
이번에는 async await 에대한 글을 적어보려한다. 결론부터 말하자면 굉장히 아주 매우 마음에드는 녀석이다 .


more than higher node 7.6

async await keyword 는 기본적으로 node 7 이상에서 동작한다 ( v7.6 )
필자는 ‘ async await 을 사용해봐야지 ‘ 라고 생각하기전까지는 v6.10.3 를 줄곧사용하였다 .
nvm이 정말 유용한 녀석이라고 생각한순간이 바로 이순간이었다. nvm에대해서는 nvm 참고하자 .
추가적으로 필자는 지금 이 글을 쓰기위한 node 기반 hexo 를 사용할때는 v6.10.3 로 switch 한다. ( node v.7.10.0 에서 hexo 설치시 버그가 있는듯하다 . )

설치가능 node version 확인

1
$ nvm ls-remote


node 설치

1
$ nvm install <node버전>


node version 변경

1
$ nvm alias default <node버전>


확인

1
$ node --verion

필자는 node 최신버전 v.7.10.0 를 사용한다 .


어떻게 사용하는가

필자도 쓰면서 알게되었지만. async await은 내부적으로 기본 Promise가 탑재되어있다는것을 알게되었다 .
Promise를 즐겨쓰는 개발자라면 학습하는데에 있어 어렵지않을것이다 .
먼저 Promise와 async awawit을 비교해보자 .

async tasks

다음과 같이 비동기 task 들을 정의하였다 .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function asyncTask1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('data1');
}, 1000);
});
}
function asyncTask2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('data2');
}, 2000);
});
}
function asyncTask3() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('data3');
}, 3000);
});
}


Promise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// single execution ( 단일실행 )
function simpleWork(){
asyncTask1()
.then(data => console.log(data))
.catch(err => console.log(err))
}
//sequential execution ( 순차실행 )
function seqWork(){
asyncTask1()
.then(data => { console.log(data); return asyncTask2(); })
.then(data => { console.log(data); return asyncTask3(); })
.then(data => console.log(data))
.catch(err => console.log(err))
}
// unify after execution ( task들 실행후 결과값 합치기 )
function unifyWork(){
Promise.all([asyncTask1(), asyncTask2(),asyncTask3()])
.then(data => console.log(data))
.catch(err => console.log(err))
}


async await

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// single execution ( 단일실행 )
async function simpleWork(){
try{
console.log(await asyncTask1());
}catch(err){
console.log(err);
}
}
//sequential execution ( 순차실행 )
async function seqWork(){
try{
console.log(await asyncTask1());
console.log(await asyncTask2());
console.log(await asyncTask3());
}catch(err){
console.log(err);
}
}
// unify after execution ( task들 실행후 결과값 합치기 )
async function unifyWork(){
try{
console.log(await Promise.all([asyncTask1(), asyncTask2(), asyncTask3()]));
}catch(err){
console.log(err);
}
}


Promise와 async await 실행결과는 모두 동일하다 .

1
2
3
4
5
simpleWork() // data1
seqWork() // data1
// data2
// data3
unifyWork() // [ 'data1', 'data2', 'data3' ]

Promise와 async await 기본 사용법에대해 알아보았다 .
Promise도 분명 간결하나, 실행해야될 로직 전에 사전에 수행되어야할 의존된 로직이있을시에는 Promise chain ( .then() ) 을걸어 정의해야한다.
그런부분에 있어서는 async await 은 비동기 코드가 마치 동기 코드로 동작하기때문에 상당히 메리트가 있는것 같다 .


async awiat with rx

async await 을 rx와 같이 사용해보자 .
async await 도 Promise 기반으로 동작되기도하고, 가독성도 훨씬 좋아졌으니 덧붙여 적절한 상황에서 rx 를 사용하면 금상첨화라고 생각했다 .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
async function asyncTask() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3, 4, 5, 6, 7, 8]);
}, 2000);
});
}
async function doWork(){
Rx.Observable.from(await asyncTask())
.filter(num => num % 2 )
.map(num => num * num )
.subscribe(
result => console.log(result),
err => console.log(err),
() => {}
);
}
doWork(); //1
//9
//25
//49

사실 async await 만을 사용하여도 로직을 처리하는데에 충분이 문제가되지않지만 필자는 rx 역시 로직 처리에있어서는 분명 이점이있는 모듈이라고 생각되어 같이 사용해보았다.


견해

front-end 에서 async await 을 적용하려면, 역시 node version ( 7.6 ) 이상과 babel을 필수로 도입해야할것이다 .
모든 브라우저가 async await을 지원하지않기에 babel를 통해 es5 코드로 변경된 코드를 적용해야하기 때문이다 .
사용을해본후 드는 생각으로는 async await 을 적극적으로 사용해야겠다는 생각과 무엇보다 동기코드로 작성할수있기에 callback hell 에대한 걱정이 없어 좋다 .
필자는 node version 7 위한 docker images을 만들어놓았다. setyourmindpark/debian-node:7
해당 이미지를 base로 하여 추가적인 node 관리 pm2나, 필요한 모듈을 설치하여 새로운 이미지를 만들어 사용하면될것이다 .