Ryu.log

[ NodeJS 07 ] async / await 본문

Prev-content

[ NodeJS 07 ] async / await

류뚝딱 2018. 7. 27. 11:50



01. async / await

async / await 의 개념을 이해하기 전에 아래 코드를보자.
Users.findOne('juno')
  .then((user) => {
    console.log(user);
    return Users.update('juno', 'jjuno');
  })
  .then((updateUser) => {
    console.log(updateUser);
    return Users.remove('jjuno');
  })
  .then((removedUser) => {
    console.log(removedUser);
  })
  .catch((err) => {
    console.error(error);
  });
console.log('다 찾았니?');
이전 챕터에서 진행했던 Promise 예제 코드이다, 이젠많이 익숙하다.

Promise를 사용하는 findOne, update, remove 함수를 통하여

juno를 찾은 뒤 찾은 juno값을 jjno로 변경한 다음 바뀐 jjno를 삭제 하는  로직이다.


Promise를 사용함으로써 콜백 헬을 벗어나게 되어 가독성이 끝내주게 향상되었으나,

개발자들은 여기서 만족하지 않고 조금더 괜찮은 것이 없을까 고민했다.


Promise는 아주 괜찮은 기능이지만, 아주 약간 걸리는 것이있다, 

로직이 then이나 catch안에서 실행되어야 한다는것이다. 이렇게 되면 결국,

then이나 catch안쪽에 로직은 이벤트 루프에 따라 테스크 큐로 들어가게되어 코드의 실행순서가 변하게 된다.


위 코드의 결과는 console.log가 순서대로 실행되는 것이 아니라, 

console.log('다 찾았니?')가 먼저실행되고 그뒤에 Promise내부에있는 console들이 찍힐것이다.


Promise가 가독성이 좋아지고, 분리되어 실행되는 면에서 자유도나 활용도가 엄청나게 높아지긴했지만

코드가 순서대로 실행되지 않는것은 이전과 별반 다를게 없다.


그리하여 ECMA2015에서 만들어진 Promise이후 2년뒤인,

ECMA2017에서 async / await 이라는 기능이 정식 채택되어 추가 되었다.


위에있는 Promise로 만들어진 코드를 

async / await으로 변경하면 어떻게 바뀌는지 Promise방식과 비교해서 코드로 한번 보자.

//Promise
Users.findOne('juno')
  .then((user) => {
    console.log(user);
    return Users.update('juno', 'jjuno');
  })
  .then((updateUser) => {
    console.log(updateUser);
    return Users.remove('jjuno');
  })
  .then((removedUser) => {
    console.log(removedUser);
  })
  .catch((err) => {
    console.error(error);
  });
console.log('다 찾았니?');

//--------------------------------------------------------------------------

// async / await
async func() => {
  const user = await Users.findOne('juno');
  const updatedUser = await User.update('juno', 'jjuno');
  const removedUser = await User.remove('jjuno');
  console.log('다 찾았니?');
}
func();

일단 코드자체가 굉장히 짧아지고 깔끔해졌다.

기존  콜백방식부터 Promise를 거쳐 async / await 까지의 코드 변화를 살펴보면 더 놀라울 것이다.


async / await 은 바로 바로 변수에 대입해버려서  로직이 then이나 catch안에서 실행할 필요없이 자유로워졌다.

또한 비동기 방식에서 console.log('다 찾았니?')의 코드 실행순서가 변경되었던것이 이제 눈에 보이는대로 순서대로 실행 되게 된다. 아래코드를보자.

async func() => {
  const user = await Users.findOne('juno');
  const updatedUser = await User.update('juno', 'jjuno');
  const removedUser = await User.remove('jjuno');

  console.log(updatedUser);
  console.log(user);
  console.log(removedUser);
  console.log('다 찾았니?');
}
func();

async / await 은 어떻게 사용할까? 

위 코드를 보면 알겠지만

변수에 대입하는 코드 앞에 await 키워드를 붙혀주면 사용이가능하다.

이 await키워드를 사용하기 위해서는,

감싸져있는 함수 이름 앞에 async라는 키워드를 붙혀 주면 된다. 

함수가 익명함수더라도 async라는 키워드만 붙혀주면 사용가능하다.


그렇다면 async / await 에서는 어떻게 애러처리를 할까?

코드가 약간 지저분해지지만 아래와 같은 방식으로 애러처리가 가능하다.

async func() => {
  try{
    const user = await Users.findOne('juno');
    const updatedUser = await User.update('juno', 'jjuno');
    const removedUser = await User.remove('jjuno');

    console.log(updatedUser);
    console.log(user);
    console.log(removedUser);
    console.log('다 찾았니?');
  } catch (err) {
    console.error(error);
  }
}
func();

애러는 위 코드와 같이 try / catch로 애러를 잡아낼 수 있다.  


findOne, update, remove이 세가지가 DB에서 유저를 조회하고, 업데이트하고, 지우는 것이라고 가정해보자,

위 코드는 한방에 catch를 하기때문에 3가지 findOne, update, remove이 셋중에 어떤곳에서 애러가 발생했는지 모를 수 있다.

그렇다면 각각 개별적으로 애러를잡기위해서는 어떻게 해야할까? 아래코드를보자.

async func() => {
  try {
    const user = await Users.findOne('juno');
    console.log(user);
  } catch (err) {
    console.error(err);
  }
  try {
    const updatedUser = await User.update('juno', 'jjuno');
    const removedUser = await User.remove('jjuno');

    console.log(updatedUser);
    console.log(removedUser);
    console.log('다 찾았니?');
  } catch (err) {
    console.error(err);
  }
}
func();

위와 같은방식으로 애러를 catch하고 싶은곳은 따로 try / catch를 사용하여 해당부분의 애러인지를 잡아내야한다.

위에서 async / await에서 코드가 약간 지저분해질 수있다는 말을 했는데, 

그 이유가 바로 나중에 try / catch가 이런식으로 중첩되고 많아졌을때를 이야기 한것이다.


Promise를 사용해도 좋고 async / await를 사용해도 좋다 좀더 보기좋고 편한 쪽으로 선택하면 될 것이다.



Promise부터 async / await까지 오면서,

정리를 해본다면 일단 가장중요한 것은 Promise이다.

Promise를 기반으로 async / await은 Promise의 then부분을 일자로 펼쳐준다고 생각하면 된다.


Comments