[JavaScript] Async/Await를 이용한 비동기 처리
Async/Await는 ECMAScript8에서 새롭게 추가된 자바스크립트 비동기 처리 패턴이다. 코드의 모습과 동작을 좀 더 동기 코드와 유사하게 작성할수 있어 기존의 콜백 패턴이나 프로미스 패턴보다 가독성이 높다는 장점이 있다.
async function getData() {
const result = await new Promise((resolve) => {
// 1초뒤 data에 값 담음
setTimeout(() => {
const data = "my-data";
resolve(data);
}, 1000);
});
// data 값 출력
console.log(result);
}
getData();
기본적인 형태는 위와 같으며 아래에서 각 키워드를 알아본다.
async
async 키워드를 function앞에 붙이면 AsyncFunction 함수가 되며 이 함수는 항상 프라미스를 반환한다.
async function func() {
return "my-data";
}
console.log(func()); // Promise { 'my-data' }
위 코드를 보면 func()는 my-data 값을 리턴하고 있지만 실제 리턴값은 프로미스 객체를 리턴하고 있다.
async function func() {
return "my-data";
}
func().then((data) => {
console.log(data); // my-data
});
위 코드는 반환된 프라미스 객체를 then 함수를 통해 data값을 받아 출력하고 있다.
await
또 다른 키워드 await는 async 함수 안에서만 동작한다. await는 프로미스 객체를 만나면 처리될 때까지 기다리고 결과는 그 이후에 반환되며 이 키워드로 비동기 패턴을 동기식으로 작성할 수 있다.
async function getData() {
// promise 변수에 프로미스 객체를 담음
const promise = new Promise((resolve) => {
// 1초뒤 resolve 함수를 호출하여 프로미스가 이행상태가 됨
setTimeout(() => {
resolve("my-data");
}, 1000);
});
const result = await promise; // 프로미스가 이행될 때 까지 기다림
console.log(result); // my-data
}
getData();
await는async함수 외부에서 사용될 수 없다. 만약 사용된다면 문법 에러가 발생한다.
위 코드를 아래처럼 프로미스를 선언할 때 await 키워드를 사용할 수도 있다.
async function getData() {
// 프로미스가 이행되었을 때 결과값을 담음
const result = await new Promise((resolve) => {
// 1초뒤 resolve 함수를 호출하여 프로미스가 이행상태가 됨
setTimeout(() => {
resolve("my-data");
}, 1000);
});
console.log(result); // my-data
}
getData();
기존 비동기 처리 방식과 비교
기존의 비동기 방식과 비교해보자, 서버와 통신하여 1초뒤 my-data 값을 리턴하는 getData() 함수가 있다고 가정한다.(여기서는 비동기 통신을 setTimeout()로 대체한다.)
function getData() {
let data = "";
setTimeout(() => {
data = "my-data";
}, 1000);
return data;
}
console.log(getData()); // 출력 안됨
함수를 실행하면 리턴값은 아무것도 안나온다. 비동기 방식으로 통신되기 때문에 응답(1초)을 기다리지 않고 바로 값을 리턴하기 때문이다.
콜백함수 방식
function getData(callBack) {
let data = "";
setTimeout(() => {
data = "my-data";
return callBack(data);
}, 1000);
}
getData(function(result) {
console.log(result); // my-data
});
콜백 방식을 사용하면 위와 같다. getData() 함수에 콜백함수를 인자로 넣고 통신이 끝난 후 리턴하여 그 값을 출력하는데, 코드의 가독성이 좋지 않다.
프로미스의 then 방식
function getData() {
let data = "";
return new Promise((resolve) => {
setTimeout(() => {
data = "my-data";
resolve(data);
}, 1000);
});
}
getData().then(function(result) {
console.log(result); // my-data
});
반환된 프로미스 객체를 then() 함수에 전달받는 방식이다. 콜백 지옥을 해결하고, 예외처리가 가능한 방식이지만, 여전히 가독성이 안좋은건 사실이다.
Async/Await 방식
function getData() {
let data = "";
return new Promise((resolve) => {
setTimeout(() => {
data = "my-data";
resolve(data);
}, 1000);
});
}
async function getResult() {
const result = await getData();
console.log(result); // my-data
}
getResult();
getResult() 함수에 async 키워드를 사용해 AsyncFunction으로 만들었다. getData()의 리턴값은 프로미스기 때문에 await 키워드를 만나 프로미스 실행이 완료되면 결과값이 result 변수에 할당된다.
예외처리
Async/Await의 예외처리는 try, catch로 한다. 프로미스에서 catch()를 사용한 것처럼 async & await에서는 catch{}를 사용하면 된다.
function getData() {
let data = "";
return new Promise((resolve) => {
setTimeout(() => {
data = "my-data";
resolve(data);
}, 1000);
});
}
async function getResult() {
// 통신 성공
try {
const result = await getData();
console.log(result); // my-data
// 통신 실패
} catch (error) {
console.log(error); // error
}
}
getResult();
catch로 통신 오류 및 타입오류 등이 error 객체에 담기게 된다. 에러 유형에 맞게 코드를 작성하면 된다.
References
자바스크립트 async와 await
async와 await
자바스크립트의 Async/Await 가 Promises를 사라지게 만들 수 있는 6가지 이유