API로 받은 리스트를 순회하면서 각 항목마다 데이터를 업데이트하는 자동화 스크립트를 짜고 있습니다.
코드:
const items = [1, 2, 3];
async function updateData(id) {
return new Promise(resolve => setTimeout(() => {
console.log(`Update complete: ${id}`);
resolve();
}, 1000));
}
async function run() {
items.forEach(async (item) => {
await updateData(item);
});
console.log('All tasks finished');
}
run();
오류: 'All tasks finished'가 가장 먼저 출력되고, 그 이후에 1초 간격으로 Update complete 메시지가 출력됨
시도: run 함수 앞에 async를 붙였고, forEach 콜백 함수 앞에도 async를 추가해 보았습니다.
질문: forEach 내부의 await가 무시되고 다음 코드로 바로 넘어가는 이유가 무엇인가요?
댓글9
-
행복한하루
2026.10.30 11:15
-
빗방울
2026.10.30 11:48
맞음ㅋㅋ 저거 진짜 처음 하면 다들 당황하는 부분인듯
개인적으로는 웬만하면 Promise.all 쓰는 게 속도 면에서 훨씬 이득이라 추천함
-
빗방울
2026.10.30 13:11
설명 진짜 깔끔하시네요ㅋㅋ 저도 처음에 이거 때문에 밤샜는데 for...of 쓰는 게 정신건강에 제일 이로운 것 같습니다.
-
빗방울
2026.10.30 14:48
와 설명 진짜 정석이네요ㅋㅋ
이거 모르면 진짜 한참 헤매는데
딱 정리해주신 듯ㄷㄷ
-
빗방울
2026.10.30 18:10
와 설명 진짜 정석이네요ㅋㅋ 저도 처음에 이거 때문에 뇌정지 왔는데 이렇게 정리해주시니까 바로 이해됨ㄷㄷ
-
빗방울
2026.10.30 11:52
이거 진짜 킹받는 포인트죠ㅋㅋ
근데 API 서버 사양 낮으면 Promise.all 썼을 때 요청 너무 몰려서 뻗을 수도 있으니
조심해서 쓰세요ㄷㄷ
-
빗방울
2026.10.30 13:31
이거 진짜 JS 기본 설계가 좀 킹받게 되어있는 부분임ㅋㅋ
정 헷갈리면 그냥 구글에 forEach async 라고 검색해서 블로그 몇 개만 읽어보세요 바로 이해됨
-
빗방울
2026.10.30 14:05
진짜 JS 비동기 쪽이 처음 접하면 뇌정지 오는 구간이죠ㅋㅋ 그냥 map으로 Promise 배열 만들어서 처리하는 습관 들이는 게 나중에 편하더라고요.
-
빗방울
2026.10.30 14:17
근데 이거 나중에 대량 데이터 처리할 때
동기식으로 돌리면 너무 느려질 수도 있음ㅋㅋ
그럴 땐 p-limit 같은 라이브러리 써서 동시 실행 개수 제한하는 게 국룰인듯ㄷㄷ
모든 이야기1455
가벼운 안부부터 깊은 생각까지, 함께 나눠요.
forEach는 콜백 함수가Promise를 반환하는지 신경 쓰지 않고 단순히 루프를 돌리기 때문에 발생하는 현상입니다.forEach내부에서async함수를 사용하면, 각 반복마다 새로운 Promise가 생성되지만forEach자체는 이 Promise들이 해결될 때까지 기다려주지 않고 즉시 다음 단계로 넘어가 버립니다.이 문제를 해결하려면
for...of루프를 사용하시거나Promise.all()과map의 조합을 추천드립니다. 순차적으로 실행해야 한다면for (const item of items) { await updateData(item); }방식으로 수정해 보세요. 만약 순서와 상관없이 병렬로 빠르게 처리하고 싶다면await Promise.all(items.map(item => updateData(item)));를 사용하는 것이 효율적입니다.