킹의 개발일지
JavaScript - async & await 본문
async & await 보기전에 ‘콜백지옥’이 무엇인지, 그리고 이를 해결할 Promise를 먼저 보도록하자!
콜백 지옥
timer(1000, function() {
console.log('어떤 일1');
timer(1000, function() {
console.log('어떤 일2');
timer(1000, function() {
console.log('어떤 일3');
});
});
});
위 코드는 timer를 통해서 1초후 일어날 일들을 콜백으로 처리하는 코드이다.
‘어떤 일 1‘이 끝나고 1초후 다시 ‘어떤일 2’가 일어나고… 이를 구현하기위해 무수히 많은 콜백을 붙힌 모습이다. 딱 봐도 실수하기 좋은 코드이지 않은가.
사람들을 이런 코드를 보고 ‘콜백 지옥’이라고 부른다.
Promise
이를 Promise를 사용해서 좀더 가독성이 좋은 코드로 바꿀 수 있다. 그 코드를 한 번 살펴보자.
timer(1000)
.then(function {
console.log('어떤 일1');
return timer(1000);
})
.then(function {
console.log('어떤 일2');
return timer(1000);
})
.then(function {
console.log('어떤 일3');
return timer(1000);
})
코드를 뜯어보면, timer 메서드가 Promise를 반환하고 이를 then을 사용해서 resolve해준다. 그리고 이를 체이닝해서 콜백 지옥을 맛 봤던? 코드와 동일한 기능을하는 메서드를 구현한 모습이다.
첫 번째 코드와 동일한 역할을 하지만 가독성이 훨씬 좋지 않은가!
하지만 이 마저 then이 반복되어서 보기 좋진 않은 모습이다. 이것을 마치 동기적으로 동작하는 메서드처럼 작성할 수 있다면 보기 더 좋지 않을까?
async & await
위에서 Promise를 통해서 설명했던 코드와 같은 동작을 하는 코드를 async와 await를 사용해서 구현해 보자.
async function run() {
await timer(1000);
console.log('어떤 일1');
await timer(1000);
console.log('어떤 일2');
await timer(1000);
console.log('어떤 일3');
}
// 함수 실행
run();
async와 await를 사용하니, 코드 길이부터 짧아진 것을 볼 수 있다. 뭔가 동기적인 코드처럼 보이면서 더 단순해 보이지 않은가?!
이 처럼 코드를 만들기 위해서는 몇가지 규칙이 있다. 이를 살펴보자.
- 비동기적 함수 앞에 await를 붙혀준다.
- await는 async 함수 안에서만 사용할 수 있다.
async와 await의 규칙과 사용 예시를 봤으니, 다음 코드의 결과가 어떻게 될지 생각해보자.
// 위 코드와 동일한 run함수
console.log('start');
run();
console.log('end');
처음 생각했을 땐 당연히 start → 어떤 일1 → 어떤 일2 → 어떤 일3 → end 라고 생각했다.
하지만 실제 실행시켜본다면 다음과 같은 결과를 볼 수 있다.
start → end → 어떤 일1 → 어떤 일2 → 어떤 일3
위 같은 결과를 보면 ‘run() 이 비동기로 실행되는구나!!’ 라고 생각해볼 수 있다. 그래서 run()의 타입을 찍어보면,
Promise {<pending>}
Promise를 반환함을 알 수 있다. 즉, async 함수는 Promise를 반환하는 것이다.
그럼 Promise를 반환하니 이것 역시 await 키워드를 붙힐 수 있다!
따라서 순차적으로 실행하고 싶다면, 아래코드처럼 작성하면 된다.
async function run2() {
console.log('start');
await run();
console.log('end');
}
run2();
/**
* 실행 결과
* start
* 어떤 일1
* 어떤 일2
* 어떤 일3
* end
*/
즉, async 라는 키워드는 평범한 함수를 Promise를 리턴하는 비동기적인 함수로 만들어준다.
그런데 만약, async 함수에 return 값이 명시적으로 존재한다면 어떻게 될까?
async function run() {
await timer(1000);
console.log('어떤 일1');
await timer(1000);
console.log('어떤 일2');
await timer(1000);
console.log('어떤 일3');
return 어떤 값;
}
return 값이 존재한다면, return 값을 다음과 같이 변수에 저장할 수 있다.
async function run2() {
console.log('start');
var val = await run();
console.log('end');
console.log(val); // => 어떤 값 출력
}
지금까지 async & await에 대해서 살펴봤다. 자바스크립트 공부를 하며 항상 promise와 async와 await에 대한 지식이 부족하다고 느꼈는데, 좋은 공부가 되었다.
'프로그래밍 언어 > Js' 카테고리의 다른 글
| Promise.all, Promise.allSettled (0) | 2023.09.11 |
|---|---|
| Optional Chaining (0) | 2023.04.27 |
| JavaScript - Promise (then, catch) (0) | 2023.03.29 |