Node.js-Promise, Async/Await

1 분 소요

Promise의 필요성

싱글쓰레드인 자바스크립트에서 비동기 처리를 위해서 콜백(callback)을 사용해왔다.덕분에 비동기 처리를 온전히 해낼 수 있었지만 이런 콜백이 사용되는 경우가 많아지면서 단점이 드러났다.

그 단점은 비동기 처리를 순차적으로 실행할 필요가 있는 경우에 비동기 처리를 중첩시켜서 표현하므로 에러, 예외처리가 어렵다는 것과 중첩으로 인한 복잡도가 증가하는 것이 이다.

try {
  setTimeout(() => { throw 'Error!'; }, 1000);
} catch (e) {
  console.log('에러를 캐치하지 못한다..');
  console.log(e);
}

위 코드에서 try-catch에서 비동기 함수의 콜백메서드에서 에러를 만들지만 catch하지 못한다. (setTimeout()함수의 콜백은 이벤트큐에 있다가 콜스택이 비어지면 실행되기 때문) 고로 콜백메서드의 중첩은 에러 처리가 힘들다.

이러한 단점을 해결하기위해 프로미스가 예전부터 라이브러리로 생겨났고, 이것을 ES6에서는 언어적 차원에서 지원하게 되었다.

Promise의 생성과 실행

//프로미스 생성
const promise1 = (param) => {
  return new Promise((resolve, reject) => {
    if (param) {
      resolve("성공");
    } else {
      reject("실패");
    }
  });
}

//프로미스 실행
promise1(true)
            .then((result) => {
                console.log(result);  // 성공
            })
            .catch((err) => {
                console.log(err);  // 실패
            });

프로미스는 new Promise((resolve, reject){…}) 방식으로 생성된다.

promise1 함수를 보면 프로미스를 리턴하는데 이것은 프로미스안에서 비동기함수를 실행하고 성공했을 때 resolve()를 실행하고 실패 또는 에러가 났을 때 reject()를 실행한다.

그러면 resolve()랑 reject()는 나중에 함수를 실행할 때 .then(success, fail)메서드로 수행하면 된다.

결국 비동기함수를 만들어서 사용해야할 때 프로미스 객체를 리턴하게 만들어서 사용하면 콜백 헬(콜백 중첩)을 방지할 수 있고 에러처리를 수월하게 할 수 있다는 이야기다.

누군가 만든 비동기함수 역시 프로미스 객체를 리턴하게 만들어 놨으므로 promise를 실행(.then 또는 .catch)하면 된다.

Async/Await

async과 await 구문은 ES8(ECMA2017) 스펙에서 새롭게 정의된 규약이다. async/await는 사실 새로운 개념이 아닌 Promise 구문의 코드를 간결하게 표현하기 위해서 등장한 규약이다. Promise를 기반으로 동작되며 작성이 간편하고 코드품질을 높여준다. async/await 의 목적은 기존의 Promise 를 편하게 쓰기 위해서라고 볼 수 있다.

const delay = (item) => { 
    return new Promise(resolve => setTimeout(() => { 
            console.log(item); 
            resolve(); 
        }, 500) 
    ); 
} 

const basic = async () => { 
    await delay(1); 
    console.log("Done"); 
    return "basic"; 
}

위 코드와 같이, async키워드가 함수 앞에 정의되어야만, await를 사용할 수 있다.

promise를 await하는 경우 promise가 이행되어 값을 반환할 때까지 함수는 일시적으로 중단된다.

결과적으로 1을 먼저 출력한 후 “Done” 텍스트가 출력하게 된다.

결과적으로 비동기 처리를 async/await를 사용함으로써, 다른 방법보다 훨씬 읽기 쉬운 코드로 작성할 수 있다.

const usePromise = () => { 
    return Promise.resolve(1);
    // return Promise.reject('error');  
} 
const useAsync = async () => { 
    return 1; 
    // throw 'error';
}

같은 맥락으로 위 코드에서 usePromise와 useAsync함수는 둘 다 같은 동작을 한다.

카테고리:

업데이트:

댓글남기기