프론트엔드 첫걸음

throw와 Promise.reject의 차이와 선택 기준 본문

개발 공부/Javascript

throw와 Promise.reject의 차이와 선택 기준

차정 2024. 12. 24. 00:28

에러를 처리할 때 throw와 Promise.reject 중 어떤 것을 사용해야 할지 모를 수 있습니다.

저만 모른것일수 있습니다.


throw와 Promise.reject란?

  1. throw:
    • 동기적인 에러를 발생시킬 때 사용합니다.
    • 예외가 발생하면 현재 실행 중인 함수가 종료되고, 상위 호출 스택으로 에러가 전달됩니다.
    • try-catch 블록으로 처리할 수 있습니다.
  2. Promise.reject:
    • 비동기 함수에서 명시적으로 에러를 반환할 때 사용합니다.
    • Promise 체인에서 .catch로 처리할 수 있습니다.
    • throw와 달리 비동기 작업에서 의도적으로 에러를 처리하기 위해 사용됩니다.

언제 throw를 사용해야 할까?

throw는 동기 코드에서 예외를 처리할 때 적합합니다. 아래는 간단한 예시입니다.

예제: 입력값 검증

const validateInput = (input) => {
  if (!input) {
    throw new Error("Input is required");
  }
  return input;
};

try {
  validateInput(null);
} catch (error) {
  console.error("Caught:", error.message);
}​

출력:

Caught: Input is required
 

언제 Promise.reject를 사용해야 할까?

Promise.reject는 비동기 코드에서 에러를 명시적으로 반환할 때 적합합니다. 이는 네트워크 요청 실패나 비동기 작업 중 에러가 발생했을 때 유용합니다.

예제: 네트워크 요청 실패

const fetchData = () => {
  return Promise.reject("Network error");
};

fetchData()
  .catch((error) => console.error("Caught:", error));

출력:

Caught: Network error

throw와 Promise.reject 비교: A > B > C 흐름 예제

A -> B -> C 단계로 이어지는 함수 호출 흐름에서, 각각의 에러 처리 방식과 결과를 비교해 봅니다.

1. throw를 사용한 예제

 
const C = () => {
  console.log("C is called");
  throw new Error("C failed with throw");
};

const B = () => {
  console.log("B is called");
  try {
    C();
  } catch (error) {
    console.error("Error caught in B:", error);
    throw error; // 에러를 다시 전달
  }
};

const A = () => {
  console.log("A is called");
  try {
    B();
  } catch (error) {
    console.error("Error caught in A:", error);
  }
};

A();

 

출력:

A is called
B is called
C is called
Error caught in B: Error: C failed with throw
Error caught in A: Error: C failed with throw
 

2. Promise.reject를 사용한 예제

const C = () => {
  console.log("C is called");
  return Promise.reject("C failed with Promise.reject");
};

const B = () => {
  console.log("B is called");
  return C()
    .catch((error) => {
      console.error("Error caught in B:", error);
      return Promise.reject(error); // 에러를 다시 전달
    });
};

const A = async () => {
  console.log("A is called");
  try {
    await B();
  } catch (error) {
    console.error("Error caught in A:", error);
  }
};

A();

출력:

A is called
B is called
C is called
Error caught in B: C failed with Promise.reject
Error caught in A: C failed with Promise.reject

throw와 Promise.reject의 선택 기준

  1. 동기 코드에서는 throw를 사용합니다.
    • 입력값 검증, 계산 오류 등 즉시 에러가 발생하는 경우 적합합니다.
  2. 비동기 코드에서는 Promise.reject를 사용합니다.
    • 네트워크 요청 실패, 비동기 작업 중 에러 발생 등을 처리하기 위해 적합합니다.

결론

throw와 Promise.reject는 각각 동기적/비동기적 에러 처리에 사용되며, 상황에 맞게 선택하면 코드의 가독성과 유지보수성을 높일 수 있습니다. 다음과 같은 기준으로 선택하세요:

  • 동기적 에러 처리: throw
  • 비동기적 에러 처리: Promise.reject

정확한 사용법을 익히고 프로젝트에 적절히 적용하면 더 나은 에러 핸들링을 구현할 수 있습니다.