안녕하세요
이전 포스팅에서는 콜백함수와 Promise 패턴에 대해 알아보았습니다.
이번 시간에는 비동기함수(Async function)에 대해 알아보도록 합시다!
Node.js에서는 7.6버전부터 지원이 된다고 하니 알아두면 좋을것같습니다!
먼저 비동기함수에 대해 알아보기 전에 프라미스 패턴으로 구현한 간단한 예제를 봅시다.
위 예제는 이름이 비어있지 않으면 **님 반갑습니다! 를 출력하고
만약 이름이 비어있으면 이름이 비어있다고 알려주는 예제입니다.
프라미스 패턴으로 구현되어있습니다.
프라미스 작동방식에 대해 이해하셨다면 금방 분석이 가능합니다.
아래 사진은 위 예제를 실행한 결과입니다.
이름이 'Lee' 이므로 정상적으로 출력이 됩니다.
만약 10행에서 'Lee' 대신 ''를 전달했다면 프라미스가 reject되어 이름이 비어있다는 오류가 13행에서 출력이 될것입니다.
아래는 비동기함수 예제입니다.
1~8행까지의 프라미스 부분은 동일합니다.
10행을 확인해보면 asyncHello 변수에 async 함수가 저장되어있습니다.
비동기 함수는 async 키워드를 붙여서 선언이 가능합니다.
async 함수 안에서는 await라는 키워드도 사용이 가능하죠
await의 뜻을 찾아보면 '기다리다' 라는 뜻인데 정말 그러한 기능을 가지고 있습니다.
위 코드를 실행시키면 아래와 같은 결과가 출력됩니다.
프라미스 패턴을 사용했을 때와 동일한 결과입니다.
[] = await []
왼쪽 []는 변수입니다.
await 후 돌아오는 결과가 저장되죠
오른쪽 []는 기다려야할 기능입니다.
주로 프라미스가 등장하구요 프라미스를 기다렸다가 프라미스가 resolve(fulfill)되면 결과값이 왼쪽 변수에 대입됩니다.
(프라미스 말고 일반 문자열, 숫자, 기타 등등 가능합니다.)
(프라미스가 아닌 경우 해당 값 자체가 반환됩니다.)
만약 프라미스가 reject 되었다면?
변수에 fulfill과 같이 reject된 결과가 저장되는것이 아니라
해당 오류를 그 자리에서 throw 합니다.
비동기함수를 사용한다면 try~catch를 사용하여 혹시 모를 reject 상황을 대비하는것이 좋겠죠?
아래는 reject 상황 예 입니다.
(코드는 동일합니다)
20행의 전달값을 'Lee' 에서 '' 로 바꾼 후 실행해보겠습니다.
에러가 발생하네요
에러를 핸들링하려면 비동기 함수 내에서 try~catch를 사용해야합니다.
비동기함수 내에 try~catch를 추가한 후 다시 실행해봅시다!
(20행에 갑자기 then() 이 붙었는데 아래에서 설명하겠습니다.)
에러가 핸들링되고 우리가 원하던 에러 메시지가 잘 출력됩니다.
위 예제를 다시 분석하자면
12행에서 hello(name) 을 통해 새로운 프라미스를 받아왔습니다.
그런데 앞에 await 키워드가 붙어있네요?
await가 붙어있으면 프라미스가 끝날 때 까지 무조건 기다립니다.
프라미스에서 'Lee님 반갑습니다!' 라는 결과값이 resolve(fulfill)되었습니다.
12행의 result 변수에 저장이 되고 이제서야 13행으로 코드가 진행이 됩니다.
13행은 result 값을 출력하기 때문에 'Lee님 반갑습니다!' 가 출력됩니다.
또한 비동기함수는 종료될 때 암묵적으로 Promise를 반환합니다.
(20행)
13행에 '비동기함수 종료' 라는 문자열을 return 해주고 있습니다.
16행에서는 then()을 사용하여 값을 받고 있습니다.
then()은 프라미스에서 결과가 resolve(fulfill)되었을 때 결과값과 함께 콜백이 호출되는 부분입니다.
그런데 비동기 함수에서 then()을 사용하고 있네요?
비동기 함수는 종료될 때 (return이 없더라도) Promise를 새로 반환합니다.
return 되는 값을 담아서 전달하는데요
만약에 return 값이 없다면 undefined가 전달이 됩니다.
위 예제의 실행 결과입니다.
비동기함수에서 비동기작업을 처리한 후 끝났을 때 then으로 모든 작업이 완료되었음을 알릴 때 정말 편리합니다.
이제 마지막으로 여러 비동기 작업을 동기 작업(순차처리)하기 위한 응용방법을 알아봅시다.
이전 포스팅과 비슷한 예제로 준비되어있습니다!
만약 DB작업, 네트워크 작업 등 시간이 걸리는 작업인 경우라고 가정하고 진행하도록 하겠습니다.
먼저 프라미스 패턴입니다.
프라미스 패턴 결과
이전 포스팅에서 봤던것처럼 프라미스들이 체이닝되어 줄줄이 이어져있습니다.
콜백 방식보다 훨씬 가독성이 좋아졌는데요
이제 비동기 함수 방식으로 그대로 옮겨보겠습니다.
비동기 함수
비동기 함수 결과
프라미스보다 더 간결하고 보기 쉽죠?
await라는 키워드 자체로도 이미 기능을 표현하고 있습니다.
프라미스를 대기하고 출력하는 코드가 20~22줄(총 3번)이 있습니다.
await는 무조건 해당 작업이 끝날 때 까지(fulfill) 기다립니다.
(reject인 경우 해당 오류를 throw)
작업을 하나하나 기다리기 때문에 어떠한 비동기 작업이라고 해도
코드 작성한 순서에 따라 차례대로 실행이 되는것이죠
마지막으로 return값 으로 '작업 완료'를 반환함으로써
26행의 then()을 통해 비동기함수의 종료를 알리고 있습니다.
비동기 함수의 사용법은 이정도로 마무리 하겠습니다.
콜백, 프라미스, 비동기함수
총 3가지를 알아보았는데 3가지의 공통점은
주로 비동기 작업을 순차적으로 진행하기 위해 사용한다는것입니다.
마지막으로 콜백, 프라미스, 비동기함수로 동일한 기능을 구현한 코드를 보고 마치겠습니다.
(가독성을 기준으로 한번 보세요)
(이전 포스팅에서 작성한 예제 +비동기 함수 방식 코드입니다)
[Callback function]
[Promise]
[Async function]
[결과]
(결과는 세 코드 모두 동일합니다!)
가독성, 기타 등등에 대해 더 개선된것같죠?
자주 사용해보고 프라미스를 먼저 익히신 후 비동기함수를 사용하시면 편리합니다.
궁금하신사항, 기타 질문, 문제사항은 댓글로 남겨주세요!
감사합니다.