728x90
반응형
1. async/await란
async/await는 ES2017(ES8)에서 도입된 비동기 처리 문법으로, 프로미스를 기반으로 동작합니다. 비동기 코드를 마치 동기 코드처럼 작성할 수 있어 가독성이 크게 향상됩니다. async 함수는 항상 프로미스를 반환하며, await는 프로미스가 처리될 때까지 함수 실행을 일시 중지합니다.
2. 기본 문법
2.1 async 함수 선언
// 함수 선언식
async function fetchData() {
return '데이터';
}
// 함수 표현식
const fetchData = async function() {
return '데이터';
};
// 화살표 함수
const fetchData = async () => {
return '데이터';
};
// 메서드
const obj = {
async getData() {
return '데이터';
}
};
2.2 await 사용
async function getUser() {
// await는 프로미스가 resolve될 때까지 대기
const response = await fetch('/api/user');
const user = await response.json();
return user;
}
// async 함수는 프로미스를 반환
getUser().then(user => console.log(user));
3. 콜백/프로미스와 비교
3.1 콜백 방식
function getUserData(userId, callback) {
getUser(userId, (err, user) => {
if (err) return callback(err);
getOrders(user.id, (err, orders) => {
if (err) return callback(err);
getOrderDetails(orders[0].id, (err, details) => {
if (err) return callback(err);
callback(null, { user, orders, details });
});
});
});
}
3.2 프로미스 체이닝
function getUserData(userId) {
let userData = {};
return getUser(userId)
.then(user => {
userData.user = user;
return getOrders(user.id);
})
.then(orders => {
userData.orders = orders;
return getOrderDetails(orders[0].id);
})
.then(details => {
userData.details = details;
return userData;
});
}
3.3 async/await
async function getUserData(userId) {
const user = await getUser(userId);
const orders = await getOrders(user.id);
const details = await getOrderDetails(orders[0].id);
return { user, orders, details };
}
4. 에러 처리
4.1 try/catch 사용
async function fetchUserSafely(userId) {
try {
const user = await getUser(userId);
const orders = await getOrders(user.id);
return { user, orders };
} catch (error) {
console.error('에러 발생:', error.message);
throw error; // 필요시 에러 재전파
}
}
4.2 개별 에러 처리
async function fetchMultipleData() {
// 각 작업별로 에러 처리
const user = await getUser(1).catch(err => {
console.error('사용자 조회 실패');
return null;
});
if (!user) return null;
const orders = await getOrders(user.id).catch(err => {
console.error('주문 조회 실패');
return [];
});
return { user, orders };
}
4.3 에러 처리 유틸리티 함수
// 에러를 배열로 반환하는 유틸리티
async function to(promise) {
try {
const result = await promise;
return [null, result];
} catch (error) {
return [error, null];
}
}
// 사용
async function fetchData() {
const [err, user] = await to(getUser(1));
if (err) {
console.error('에러:', err.message);
return;
}
console.log('사용자:', user);
}
반응형
5. 병렬 처리
5.1 순차 실행 (느림)
async function sequential() {
// 각 작업이 끝나야 다음 작업 시작 - 총 3초
const result1 = await delay(1000);
const result2 = await delay(1000);
const result3 = await delay(1000);
return [result1, result2, result3];
}
5.2 병렬 실행 (빠름)
async function parallel() {
// 모든 작업 동시 시작 - 총 1초
const [result1, result2, result3] = await Promise.all([
delay(1000),
delay(1000),
delay(1000)
]);
return [result1, result2, result3];
}
5.3 병렬 실행 with 개별 에러 처리
async function parallelWithErrorHandling() {
const results = await Promise.allSettled([
fetchUser(1),
fetchUser(2),
fetchUser(3)
]);
const users = results
.filter(r => r.status === 'fulfilled')
.map(r => r.value);
const errors = results
.filter(r => r.status === 'rejected')
.map(r => r.reason);
return { users, errors };
}
6. 반복문에서의 async/await
6.1 for...of (순차 실행)
async function processSequentially(items) {
const results = [];
for (const item of items) {
const result = await processItem(item);
results.push(result);
}
return results;
}
6.2 map + Promise.all (병렬 실행)
async function processParallel(items) {
const results = await Promise.all(
items.map(item => processItem(item))
);
return results;
}
6.3 forEach 주의사항
// 잘못된 사용 - forEach는 await를 기다리지 않음
async function wrong(items) {
items.forEach(async (item) => {
await processItem(item); // 기다리지 않고 다음 반복 실행
});
console.log('완료'); // 모든 처리가 끝나기 전에 출력됨
}
// 올바른 사용
async function correct(items) {
for (const item of items) {
await processItem(item);
}
console.log('완료'); // 모든 처리가 끝난 후 출력
}
7. 실전 예시
7.1 API 데이터 가져오기
const fs = require('fs').promises;
async function fetchAndSaveUser(userId) {
try {
// API 호출
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const user = await response.json();
// 파일로 저장
await fs.writeFile(
`user_${userId}.json`,
JSON.stringify(user, null, 2)
);
console.log(`사용자 ${userId} 저장 완료`);
return user;
} catch (error) {
console.error(`사용자 ${userId} 처리 실패:`, error.message);
throw error;
}
}
결론
async/await는 프로미스 기반의 비동기 코드를 동기 코드처럼 작성할 수 있게 해주는 문법입니다. try/catch로 에러를 처리하고, Promise.all과 함께 사용하면 병렬 처리도 가능합니다. 반복문에서는 for...of를 사용하고, forEach는 async/await와 함께 사용하지 않는 것이 좋습니다.
728x90
반응형
'Node.js' 카테고리의 다른 글
| Node.js의 모듈 시스템 (0) | 2026.02.22 |
|---|---|
| Node.js의 프로미스(Promise) 사용법 (0) | 2026.02.22 |
| Node.js의 콜백 함수(Callback Functions) (0) | 2026.02.22 |
| Node.js의 비동기 프로그래밍(Asynchronous Programming) (0) | 2026.02.21 |
| Node.js의 이벤트 루프(Event Loop) (0) | 2026.02.21 |