JavaScript에서 forEach, map 함수 내에서 throw Error가 되지 않을 때 해결 방법

javascript
javascript

많은 JavaScript 개발자들이 배열을 처리할 때 map 함수를 즐겨 사용합니다. 그러나 때때로 예상치 못한 문제에 부딪힐 수 있습니다. 이 글에서는 map 함수 내에서 throw Error가 작동하지 않는 상황을 해결하는 방법에 대해 알아보겠습니다.


1. 문제 상황 파악

자바스크립트의 map/forEach 함수는 배열의 각 요소에 대해 주어진 함수를 호출하고, 그 결과를 모아 새로운 배열을 반환합니다. 때로는 배열 내의 특정 요소에 대한 조건을 검사하고 해당 조건이 충족되지 않을 경우 에러를 발생시키고 싶을 때가 있습니다.

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => {
  if (num > 3) {
    throw new Error('Number is too big');
  }
  return num * 2;
});

이 코드에서 숫자 4와 5는 3보다 크기 때문에 오류를 발생시키려고 했지만, 실제로는 그렇게 동작하지 않습니다. 이러한 상황이 발생하는 주된 원인map/forEach 함수가 동기적으로 동작하기 때문입니다.


2. Promise와 함께 사용하는 경우

비동기 작업을 수행할 때 Promise와 함께 map/forEach 함수를 사용하면 예외 처리가 더 복잡해질 수 있습니다. Promise에서 발생한 오류는 .catch 메소드를 통해 캐치할 수 있습니다.

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(async num => {
  if (num > 3) {
    throw new Error('Number is too big');
  }
  return num * 2;
});

Promise.all(doubled).catch(error => console.error(error.message));

위 코드에서 Promise.all은 모든 프로미스가 성공적으로 완료되거나 첫 번째 프로미스가 거부될 때까지 기다립니다. 이렇게 하면 map 내에서 발생하는 오류를 캐치할 수 있습니다.


3. 해결 방법

map 함수 내에서 명시적으로 예외처리

가장 간단한 해결책map/forEach 함수 내에서 발생하는 예외를 명시적으로 캐치하는 것입니다.

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => {
  try {
    if (num > 3) {
      throw new Error('Number is too big');
    }
    return num * 2;
  } catch (error) {
    console.error(error.message);
    return null;
  }
});

위 코드에서는 각 숫자를 처리하는 동안 오류가 발생하면 콘솔에 오류 메시지가 출력되고 해당 숫자의 결과 값은 null이 됩니다.

for ... of 를 사용하는 방법

for...of를 사용하면 반복문 내에서 개별 요소에 접근하면서 에러를 직접 처리할 수 있습니다. 이 방식은 코드의 명확성을 높여줍니다.

const numbers = [1, 2, 3, 4, 5];
const doubled = [];

for (const num of numbers) {
  if (num > 3) {
    console.error('Number is too big');
  } else {
    doubled.push(num * 2);
  }
}
3.3 Promise.all을 사용하는 방법

비동기 작업을 수행할 때 Promise와 함께 map 함수를 사용하면, Promise에서 발생한 오류는 .catch 메소드를 통해 캐치할 수 있습니다.

const numbers = [1, 2, 3, 4, 5];
const doubledPromises = numbers.map(num => {
  return new Promise((resolve, reject) => {
    if (num > 3) {
      reject(new Error('Number is too big'));
    } else {
      resolve(num * 2);
    }
  });
});

Promise.all(doubledPromises)
  .then(results => console.log(results))
  .catch(error => console.error(error.message));

이렇게 Promise.all을 사용하면, 모든 프로미스가 성공적으로 완료되거나 첫 번째 프로미스가 거부될 때까지 기다리게 됩니다.


마치며

이 세 가지 방법을 적절하게 활용하면, map/forEach 함수 내에서의 오류 처리 문제를 효과적으로 해결할 수 있습니다. 필요에 따라 적합한 방법을 선택하면, 예상치 못한 문제를 효과적으로 대응하고 코드의 안정성을 높일 수 있습니다.

함께 읽으면 좋은 글

MVC, MVP, MVVM 패턴 차이: 개발자를 위한 아키텍처 패턴 이해하기
개발자라면 아키텍처 패턴에 대한 이해는 필수입니다. 특히, MVC, MVP, MVVM은 가장 널리 사용되는 디자인 패턴 중 하나로, 앱의 로직과 UI를 분리하며 유지보수를 쉽게 해줍니다. 이 글에서는 이 세 가지 아키텍처 패턴의 차이와 각각의 구조를 깊이 있게 살펴보겠습니다. 목차 1. MVC 패턴의 구조 flowchart TD User --> Controller Controller --> Model
옵셔널 체이닝(Optional Chaining) 연산자: 예시와 특징
개발자들 사이에서 자주 나오는 옵셔널 체이닝(optinal chaining) 연산자에 대해서 자세히 알아보겠습니다. 이 연산자는 자바스크립트에서 객체의 키에 안전하게 접근할 수 있게 도와줍니다. 1. 옵셔널 체이닝 연산자란? 옵셔널 체이닝 연산자는 ‘?.’로 표시되며, 객체의 키에 접근할 때 해당 키가 존재하는지 여부를 체크하지 않고도 접근이 가능하게 해줍니다. const value = obj?.key; 이
자바스크립트 물음표 두개 ‘??’는 뭘까?: JS Nullish Coalescing Operator
안녕하세요. 독자 여러분! 최근 자바스크립트에서 흔히 볼 수 있는 물음표 두 개 (??) 가 뭔지 궁금해하시는 분들이 많았습니다. 오늘은 바로 이 Nullish Coalescing Operator에 대해 알아보도록 하겠습니다. 1. ?? 연산자의 정의 1.1. 무엇을 위한 연산자인가? Nullish Coalescing Operator (??) 는 자바스크립트에서 relatively 최신 문법입니다. 이 연산자는 왼쪽 피연산자가 null 또는 undefined일 경우