비동기 프로그래밍은 자바스크립트에서 매우 중요한 개념입니다. 네트워크 요청, 파일 입출력, 타이머 설정 등 시간이 걸리는 작업을 처리할 때 비동기 작업은 사용자 경험을 향상시키는 데 큰 역할을 합니다. 특히 async/await는 자바스크립트의 비동기 작업을 보다 직관적이고 쉽게 처리할 수 있도록 도와주는 ES6 이후 추가된 기능입니다. 이 글에서는 **async/await**의 개념과 그 사용법을 예제와 함께 설명하겠습니다.
async/await란?
async/await는 자바스크립트에서 비동기 코드를 동기 코드처럼 작성할 수 있게 해줍니다. 비동기 작업을 처리하는 기존의 Promise나 콜백 함수보다 가독성이 좋으며, 코드의 유지보수성도 높아집니다.
- async 함수: 함수 앞에 async 키워드를 붙이면, 해당 함수는 항상 Promise를 반환합니다. 함수 내에서 명시적으로 Promise를 반환하지 않으면, **Promise.resolve()**로 처리됩니다.
- await 키워드: **await**는 Promise가 해결될 때까지 해당 작업을 기다립니다. 이 키워드는 반드시 async 함수 내부에서만 사용할 수 있습니다.
기본 예제
async function fetchData() {
return '데이터를 성공적으로 가져왔습니다!';
}
fetchData().then(result => console.log(result));
// 출력: 데이터를 성공적으로 가져왔습니다!
위 예제에서 fetchData() 함수는 **async**로 정의되었으므로, 해당 함수는 Promise를 반환합니다. then() 메서드를 사용하여 결과를 처리할 수 있습니다.
async/await의 실제 활용
다음은 실제로 **async/await**을 활용하여 비동기 네트워크 요청을 처리하는 예제입니다. 이 예제에서는 데이터 요청 전 일정 시간(2초) 동안 기다리게 한 후, 데이터를 처리합니다.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function fetchData() {
console.log('데이터를 가져오는 중...');
await delay(2000); // 2초 대기
return '데이터가 준비되었습니다!';
}
async function displayData() {
const result = await fetchData();
console.log(result);
}
displayData();
// 출력:
// 데이터를 가져오는 중...
// (2초 후)
// 데이터가 준비되었습니다!
async/await의 장점
- 가독성 향상: 비동기 코드도 동기 코드처럼 작성할 수 있어, 코드가 더 명확하고 읽기 쉬워집니다.
- 에러 처리 용이: try/catch 구문을 사용하여 에러를 처리할 수 있습니다.
- 콜백 지옥 해소: 콜백 함수나 Promise 체인을 지나치게 중첩하지 않고 깔끔한 코드 작성이 가능합니다.
에러 처리
async/await를 사용할 때 발생하는 에러는 try/catch 구문을 통해 쉽게 처리할 수 있습니다. 다음 예제는 데이터를 가져오는 도중 발생하는 에러를 핸들링하는 방법을 보여줍니다.
async function fetchData() {
try {
let response = await fetch('https://jsonplaceholder.typicode.com/posts');
let data = await response.json();
console.log(data);
} catch (error) {
console.error('에러 발생:', error);
}
}
fetchData();
위 예제에서는 비동기 요청 중에 발생할 수 있는 네트워크 오류나 기타 예외 상황을 catch 블록에서 처리하고 있습니다.
async/await vs Promise 체인
async/await은 기존의 Promise를 기반으로 더 간결한 문법을 제공하지만, 두 방식 모두 동일한 비동기 처리를 수행합니다. 다음은 Promise 체인 방식과 async/await 방식의 비교입니다.
Promise 체인 방식
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('데이터가 준비되었습니다!'), 2000);
});
}
fetchData()
.then(data => console.log(data))
.catch(error => console.error('에러:', error));
async/await 방식
async function fetchData() {
try {
await new Promise(resolve => setTimeout(resolve, 2000));
console.log('데이터가 준비되었습니다!');
} catch (error) {
console.error('에러:', error);
}
}
fetchData();
async/await 방식이 더 간결하고 읽기 쉬운 구조를 제공합니다.
async/await의 단점
- 성능 이슈: 여러 개의 비동기 작업을 await로 순차적으로 처리할 경우 성능 저하가 발생할 수 있습니다. 비동기 작업을 병렬로 처리하는 것이 더 효율적일 때는 **Promise.all()**을 사용해야 합니다.
- 에러 처리 복잡성: 비동기 함수마다 별도의 try/catch를 사용해야 하므로, 코드가 길어질 수 있습니다.
성능 최적화를 위한 병렬 처리
async/await를 사용할 때 성능을 최적화하려면 **Promise.all()**을 사용해 비동기 작업을 병렬로 처리할 수 있습니다.
async function fetchDataInParallel() {
const [data1, data2] = await Promise.all([
fetch('https://jsonplaceholder.typicode.com/posts/1'),
fetch('https://jsonplaceholder.typicode.com/posts/2')
]);
console.log('두 개의 데이터를 병렬로 가져왔습니다.');
}
fetchDataInParallel();
위 코드에서는 두 개의 네트워크 요청이 병렬로 처리되어, 성능이 향상됩니다.
async/await 사용 시 주의할 점
- 병렬 처리 여부: 여러 개의 비동기 작업을 순차적으로 처리해야 하는 경우가 아니라면, **Promise.all()**을 사용하여 병렬로 처리하는 것이 성능상 이점이 큽니다.
- 에러 처리: 비동기 함수에서 발생하는 모든 에러는 try/catch로 명확히 처리해야 하며, 예외가 발생할 수 있는 모든 비동기 작업에 대해서는 철저히 대비해야 합니다.
- 블록킹 위험: await는 Promise가 해결될 때까지 실행을 일시 중지하기 때문에, 불필요하게 많은 await을 사용하면 동시 처리의 이점을 살리지 못하고 코드가 블록킹될 수 있습니다.
결론
async/await은 자바스크립트의 비동기 프로그래밍을 더 간결하고 직관적으로 처리할 수 있는 방법입니다. Promise 체인 방식에 비해 가독성이 뛰어나며, 에러 처리도 더욱 명확해집니다. 그러나 성능 최적화를 위해 병렬 처리가 필요한 경우 **Promise.all()**과 같은 방법을 사용해야 하고, 코드의 흐름을 충분히 고려하여 사용해야 합니다.
'JS > JavaScript' 카테고리의 다른 글
자바스크립트 공통 유틸 함수 모음 (1) | 2024.09.12 |
---|---|
#25 자바스크립트 jQuery, Ajax, 에니메이션 (1) | 2024.09.08 |
#23 자바스크립트 ES6 (0) | 2024.09.06 |
#22 자바스크립트 Promise (0) | 2024.09.05 |
#21 자바스크립트 비동기 처리: setTimeout과 setInterval (0) | 2024.09.05 |
#20 자바스크립트 이벤트 루프(Event Loop): 콜 스택, 이벤트 큐, 태스크 큐 (0) | 2024.09.04 |
#19 자바스크립트 클로저 활용 예시 : 즉시 실행 함수(IIFE)와 모듈 패턴 (0) | 2024.09.03 |
#18 자바스크립트 클로저(Closure) 개념 (0) | 2024.09.03 |