HTTP 통신을 하기 위해 Promise
가 어떻게 사용되는지 살펴 보겠습니다. 아래 예제에 사용된 axios
는 Javascript를 통해 직접 요청을 보내기 위해 널리 사용되는 라이브러리 입니다. GET
메서드로 요청을 보내기 위해 axios.get()
함수를 사용할 수 있는데, 이 때 Promise 객체가 반환됩니다.
const axios = require('axios');
const API_URL = 'https://api.github.com';
axios.get(`${API_URL}/repos/facebookincubator/create-react-app/issues?per_page=10`)
.then(res => {
console.log('최근 10개의 이슈');
res.data
.map(issue => issue.title)
.forEach(title => console.log(title));
console.log('출력이 끝났습니다.');
});
axios.get()
을 호출해서 반환된 Promise
객체에 담긴 결과값은 Response
객체로, HTTP 응답에 대한 내용을 담고 있습니다.
Promise
의 진가는, 복잡한 비동기 데이터 흐름을 다룰 때 발휘됩니다.
아래의 두 특징을 활용하면, 콜백만 사용했을 때보다 코드를 훨씬 더 깔끔하게 작성할 수 있습니다.
then
메서드는 Promise
객체를 반환하므로, 콜백을 중첩하지 않고도 비동기 작업을 연이어 할 수 있습니다.Promise
를 사용하는 비동기 프로그래밍 방식은 여러가지 장점을 갖지만, 여전히 콜백은 사용한다는 점 때문에 '불편하다', '가독성이 좋지 않다' 는 비판을 받았습니다.
ES2017에서 도입된 비동기 함수(async Function)을 사용하면, 동기식 코드와 거의 같은 구조를 갖는 비동기식 코드를 짤 수 있습니다.
함수 앞에 async
키워드를 붙이면 그 함수는 비동기 함수가 됩니다.
// 비동기 함수
async function func1() {
// ...
}
// 비동기 화살표 함수
const func2 = async () => {
// ...
}
// 비동기 메소드
class MyClass {
async myMethod() {
// ...
}
}
비동기 함수는 항상 Promise
객체를 반환하는 특징을 가지고 있습니다. 이 Promise
의 결과 값은 비동기 함수 내에서 무엇을 반환하느냐에 따라서 결정되며, then
메서드와 똑같은 방식으로 동작합니다.
async function func1() {
return 1;
}
async function func2() {
return Promise.resolve(2);
}
func1().then(console.log); // 1
func2().then(console.log); // 2
또 하나의 중요한 특징은 비동기 함수 내에서 await
키워드를 쓸 수 있습니다. await
는 Promise
의 then
메서드와 유사한 기능을 하는데, await
키워드 뒤에 오는 Promise
가 결과값을 가질 때 까지 비동기 함수의 실행을 중단 시킵니다.
'중단'에 의미는 비동기식이며, 브라우저는 Promise
가 완료될 때까지 다른 작업을 처리할 수 있습니다.
await
는 연산자이기도 하며, await
연산의 결과값은 뒤에 오는 Promise
객체의 결과값이 됩니다.
then
을 이용하여 작성하는것 보다 아래처럼 작성하는게 더 동기식 코드를 짜듯이 비동기식 코드를 짤 수 있습니다.
// Promise 객체를 반환하는 함수.
function delay(ms) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`${ms} 밀리초가 지났습니다.`);
resolve()
}, ms);
});
}
async function main() {
await delay(1000);
await delay(2000);
const result = await Promise.resolve('끝');
console.log(result);
}
main();
await
키워드는 for
, if
와 같은 제어 구문 안에서도 쓰일 수 있기 때문에, then
메소드를 사용할 때보다 복잡한 비동기 데이터 흐름을 아주 쉽게 표현할 수 있다는 장점이 있습니다. 다만, 비동기 함수 역시 Promise를 사용하기 때문에, 비동기 함수를 잘 쓰기 위해서는 여전히 Promise에 대해 잘 알고 있어야 합니다.