kind: capsule status: active visibility: private license: CC-BY-SA-4.0 summary: async/await 와 forEach 함께 쓰면 안 되는 이유 — forEach 는 반환 promise 를 버림. 순차는 for…of, 병렬은 Promise.all(map). tags: - javascript - async - promise - iteration - capsule
JavaScript async forEach Capsule
Summary#
forEach(async fn) 는 promise 를 무시한다. printFiles() 이 즉시 반환 + 내부 async 가 백그라운드로 떠있음. 순차 실행이 필요하면 for…of, 병렬은 Promise.all(arr.map(async …)).
Claim#
❌ 의도대로 동작하지 않음#
async function printFiles () {
const files = await getFilePaths();
files.forEach(async (file) => {
const contents = await fs.readFile(file, 'utf8');
console.log(contents);
});
// ↑ 여기서 함수가 이미 반환됨
// forEach 는 async 콜백이 반환한 promise 들을 전부 버림
}
✅ 순차 — for…of#
async function printFiles () {
const files = await getFilePaths();
for (const file of files) {
const contents = await fs.readFile(file, 'utf8');
console.log(contents);
}
}
- 각 반복에서
await이 정확히 작동 - 파일을 순서대로 읽음 → 읽기 간 의존성 있을 때 필수
✅ 병렬 — Promise.all + map#
async function printFiles () {
const files = await getFilePaths();
await Promise.all(files.map(async (file) => {
const contents = await fs.readFile(file, 'utf8');
console.log(contents);
}));
}
.map(async …)은 promise 배열 생성Promise.all이 전부 await- 각 파일 I/O 가 동시에 진행 → 대량 작업에서 극적 속도 향상
제어된 병렬성 (N개씩)#
import pLimit from 'p-limit';
const limit = pLimit(5); // 최대 5개 동시
const results = await Promise.all(
files.map(file => limit(() => fs.readFile(file, 'utf8')))
);
수백~수천 파일 동시 open 시 파일 핸들 고갈 방지.
왜 forEach 가 문제인가#
Array.prototype.forEach시그니처는(callback) => void- 콜백이 반환하는 값(promise 포함)을 버린다
- → async/await 의 semantics 와 근본적으로 안 맞음
Scope#
- ES2017+ async/await 표준.
- 동일 원리는
map반환값 무시 (.then안 붙이고 버림) 등 모든 고차 함수에 적용.
Caveats#
Promise.all은 하나가 reject 되면 즉시 rejected → 부분 실패 허용 필요하면Promise.allSettled.for…of안에서도await없이 동기식 처리 원하면 그냥 for 루프.- hot promise vs cold:
.map(async …)은 즉시 promise 시작. 직렬화 원하면for…of외에 선택지 없음. - Node.js 의
fs/promises사용. CommonJSfs의readFile은 callback 기반.
Source#
- Stack Overflow Q: Using async/await with a forEach loop
- Accepted Answer: https://stackoverflow.com/a/37576787 — by Bergi
- License: CC BY-SA 4.0 (Stack Exchange user contributions)
- 조회일: 2026-04-19
Sagwan Revalidation 2026-04-18T22:57:32Z#
- verdict:
ok - note: forEach/for…of/Promise.all 패턴 및 p-limit 권장안 모두 2026년 현재도 유효한 JavaScript 표준 실천법임.