서론
배열을 순회할 때 자주 사용하는 forEach 메서드에서는 break 키워드를 통한 반복문 탈출이 불가능하다. 이런 제약사항을 이해하고 대안을 찾아보기 전에, 먼저 forEach가 무엇인지 알아보겠다.
forEach란?
forEach는 Array 객체의 메서드로, 인자로 받은 콜백함수를 배열의 각 요소에 대해 순회하며 호출한다.
map 메서드와 달리 새로운 배열을 반환하지 않으며, 변수에 할당하여 호출하면 undefined가 반환된다.
const arr = [1, 2, 3, 4];
const arr2 = arr.forEach((num) => num + 1);
// 기댓값
// [2,3,4,5]
// 실제 호출
// undefined
break 사용 시 발생하는 에러
아래와 같은 코드를 실행하면 다음과 같은 에러가 발생한다:
const arr = [1,2,3,4,5]
arr.forEach(num => {
if(num > 3) {
break;
}
console.log(num)
})
Uncaught SyntaxError: Illegal break statement
이 에러는 break 문이 반복문 밖에서 실행되었다고 판단되어 발생한 것이다.
break 문은 for, while, switch 등의 제어문 내부에서만 사용할 수 있는데, 이 콜백 함수는 그저 일반 함수일 뿐 실제 반복문 내부가 아니다.
그래서 JavaScript 엔진은 "여기서 break를 사용할 수 없다"는 SyntaxError를 발생시키는 것이다.
return으로 대체할 수 없을까?
break 대신 return을 사용하면 어떻게 될까?
const arr = [1, 2, 3, 4, 5];
arr.forEach((num) => {
if (num > 3) {
return;
}
console.log(num);
});
// 1
// 2
// 3
return을 사용하면 해당 콜백함수의 실행은 중단되지만, 배열의 순회 자체는 계속된다. 즉, 원하는 시점에서 순회를 완전히 중단할 수는 없다.
강제로 순회 중단하기
forEach 메서드에서 순회를 중단하는 한 가지 방법은 에러를 발생시키는 것이다:
const arr = [1, 2, 3, 4, 5];
arr.forEach((num) => {
if (num > 3) {
throw Error("break forEach!");
}
console.log(num);
});
// 1
// 2
// 3
// 🚫 Uncaught Error: break forEach!
하지만 이는 정상적인 중단이라기보다는 강제로 에러를 발생시키는 것이므로 권장되지 않는 방법이다.
대안: for...of 사용하기
원하는 시점에 순회를 중단하고 싶다면 for...of 구문을 사용하면 된다:
const arr = [1, 2, 3, 4, 5];
for (let num of arr) {
if (num > 3) {
break;
}
console.log(num);
}
// 1
// 2
// 3
for...of는 배열의 각 요소를 직접 순회하며, 일반적인 반복문처럼 break와 continue 키워드를 사용할 수 있다.
some과 every 메서드 활용하기
배열 메서드 중 some과 every를 사용해서도 순회를 중단할 수 있다:
// some: 조건에 맞는 요소를 찾으면 순회 중단
arr.some((num) => {
if (num > 3) return true;
console.log(num);
return false;
});
// 1
// 2
// 3
// every: 조건에 맞지 않는 요소를 찾으면 순회 중단
arr.every((num) => {
if (num > 3) return false;
console.log(num);
return true;
});
// 1
// 2
// 3
forEach의 적절한 사용
forEach는 순수 함수형 프로그래밍의 관점에서 '부수 효과(side effect)'를 일으키는 용도로 주로 사용된다. 예를 들어 DOM 조작이나 로깅과 같은 작업에 적합하다 반면 배열을 변환하거나 새로운 값을 생성하는 경우에는 map, filter, reduce 등의 메서드가 더 적절하다.
따라서 배열 순회 중 특정 조건에서 순회를 중단해야 하는 경우, forEach 대신 for...of나 some, every 등의 대안을 고려하는 것이 좋다.
참고
- Array.prototype.forEach() - MDN Web Docs
- JavaScript Loops and Iteration - MDN Web Docs
- Array.prototype.some() - MDN Web Docs
- Array.prototype.every() - MDN Web Docs
피드백은 언제나 환영입니다.