제너레이터 (Generators)와 async/await
제너레이터(Generators)와 **async/await**는 JavaScript의 비동기 프로그래밍을 다루는 두 가지 중요한 개념입니다. 이들은 비동기 코드를 작성하고 관리하는 방식에 혁신을 가져왔으며, 특히 콜백 지옥(callback hell)을 해결하고 코드의 가독성을 향상시키는 데 크게 기여했습니다.
제너레이터 (Generators)
제너레이터는 ES6(ES2015)에 도입된 기능으로, 함수의 실행을 중간에 멈췄다가 필요한 시점에 다시 재개할 수 있는 함수입니다. function* 키워드로 선언하며, yield 표현식을 사용해 함수의 실행을 일시 중지하고, next() 메서드를 통해 다시 실행을 재개합니다. 제너레이터는 비동기 작업을 순차적으로 처리하는 데 유용하게 사용될 수 있습니다.
function* generatorFunction() {
console.log('처리 시작');
yield '1단계 완료';
console.log('처리 재개');
yield '2단계 완료';
}
const generator = generatorFunction();
console.log(generator.next().value); // 처리 시작, 1단계 완료
console.log(generator.next().value); // 처리 재개, 2단계 완료
제너레이터는 **yield**를 통해 비동기 작업의 완료를 기다리는 방식으로 사용될 수 있으나, 이 패턴을 직접 구현하는 것은 복잡할 수 있습니다. 이를 간소화하기 위해 **async/await**가 도입되었습니다.
async/await
**async/await**는 ES2017(ES8)에서 소개된 문법으로, 비동기 작업을 마치 동기 코드처럼 쉽게 작성할 수 있게 해줍니다. **async**로 선언된 함수 내에서 await 키워드를 사용하면, 프로미스의 완료를 기다릴 수 있습니다. 이 구문을 사용하면, 비동기 코드를 순차적이고 직관적으로 작성할 수 있습니다.
async function asyncFunction() {
console.log('처리 시작');
const result1 = await new Promise((resolve) => setTimeout(() => resolve('1단계 완료'), 1000));
console.log(result1);
console.log('처리 재개');
const result2 = await new Promise((resolve) => setTimeout(() => resolve('2단계 완료'), 1000));
console.log(result2);
}
asyncFunction();
제너레이터와 async/await의 차이
- 제너레이터: 수동으로 next() 메서드를 호출하여 제너레이터 함수의 실행을 제어해야 합니다. 비동기 작업을 처리하기 위해서는 **yield**와 프로미스를 함께 사용하는 복잡한 로직이 필요할 수 있습니다.
- async/await: async 함수 내에서 await 키워드를 사용하여 프로미스의 완료를 간단하게 기다릴 수 있습니다. 코드가 동기적으로 실행되는 것처럼 보이게 하여 가독성이 크게 향상됩니다.
**async/await**는 제너레이터와 비교했을 때 비동기 코드를 더 간결하고 이해하기 쉽게 작성할 수 있게 해주므로, 현대 JavaScript에서 비동기 처리를 위한 주된 선택지가 되었습니다.