🛠️ Promise rejection unhandled 완벽 해결법 – 원인부터 예방까지

개발 에러 해결 가이드 - FixLog 노트

Promise rejection unhandled 완벽 해결법 – 원인부터 예방까지

도입

JavaScript 개발을 하다 보면 콘솔에서 Promise rejection unhandled 에러를 한 번쯤은 마주하게 됩니다. 이 에러는 비동기 처리 중 발생한 예외를 제대로 처리하지 않았을 때 나타나는 경고 메시지로, 방치할 경우 애플리케이션의 안정성을 크게 해칠 수 있습니다. Promise rejection unhandled 에러는 특히 Node.js 환경에서는 프로세스를 종료시킬 수 있어 더욱 위험합니다. 이 글에서는 에러의 정확한 의미부터 발생 원인, 실전 해결 방법, 그리고 예방 전략까지 체계적으로 다루어 여러분이 이 문제를 완벽하게 해결할 수 있도록 돕겠습니다.

🤖 AI 에러 분석 도우미

이 에러는 다음과 같은 상황에서 주로 발생합니다:

  • 코드 문법 오류가 있을 때
  • 라이브러리나 의존성 문제
  • 환경 설정이 잘못된 경우
  • 타입 불일치 문제

💡 위 해결법을 순서대로 시도해보세요. 90% 이상 해결됩니다!

에러 상세 분석

Promise rejection unhandled는 Promise가 reject 상태로 전환되었지만, 해당 거부(rejection)를 처리할 .catch() 핸들러나 try-catch 블록이 없을 때 발생합니다. JavaScript 엔진은 Promise가 거부되었는데 아무도 그 에러를 처리하지 않는 상황을 감지하면 이 경고를 발생시킵니다.

브라우저 환경에서는 unhandledrejection 이벤트가 발생하며, Node.js에서는 unhandledRejection 이벤트가 트리거됩니다. Node.js 15 버전 이상부터는 처리되지 않은 Promise rejection이 발생하면 프로세스가 종료되므로 더욱 주의가 필요합니다.

이 에러의 위험성은 단순히 콘솔에 경고가 표시되는 것을 넘어서, 데이터 손실, 불완전한 트랜잭션, 사용자 경험 저하 등 실질적인 문제를 야기할 수 있다는 점입니다. 따라서 모든 Promise는 반드시 적절한 에러 핸들링 메커니즘을 갖춰야 합니다.

발생 원인 5가지

1. .catch() 핸들러 누락

가장 흔한 원인으로, Promise 체인에서 에러 처리 구문을 빠뜨린 경우입니다.

// 잘못된 예시
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data));
// 네트워크 에러 발생 시 처리되지 않음

2. async/await에서 try-catch 미사용

async 함수 내에서 await를 사용할 때 try-catch로 감싸지 않으면 에러가 전파되지 않습니다.

// 잘못된 예시
async function fetchData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  return data;
}

3. Promise 생성자 내부의 에러

Promise 생성자 함수 내에서 발생한 동기적 에러는 자동으로 reject되지만, 비동기 에러는 그렇지 않습니다.

// 문제가 되는 예시
new Promise((resolve, reject) => {
  setTimeout(() => {
    throw new Error('비동기 에러'); // reject로 전달되지 않음
  }, 100);
});

4. 이벤트 핸들러 내부의 Promise

이벤트 리스너나 콜백 함수 내에서 생성된 Promise는 에러 처리를 잊기 쉽습니다.

button.addEventListener('click', () => {
  fetch('/api/endpoint').then(res => res.json());
  // 에러 처리 없음
});

5. Promise.all()의 부분적 실패

여러 Promise를 병렬로 실행할 때 하나라도 실패하면 전체가 reject되는데, 이를 처리하지 않는 경우입니다.

Promise.all([
  fetch('/api/user'),
  fetch('/api/posts'),
  fetch('/api/comments')
]);
// 하나라도 실패하면 unhandled rejection

해결방법 7가지 (코드 포함)

1. .catch() 핸들러 추가

모든 Promise 체인 끝에 .catch()를 추가합니다.

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    console.error('에러 발생:', error);
    // 에러 로깅, 사용자 알림 등
  });

2. async/await with try-catch

async 함수에서는 try-catch 블록으로 감싸서 처리합니다.

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('데이터 가져오기 실패:', error);
    throw error; // 필요시 재전파
  }
}

3. 전역 에러 핸들러 설정

브라우저와 Node.js에서 전역 핸들러를 등록하여 마지막 안전망을 구축합니다.

// 브라우저
window.addEventListener('unhandledrejection', event => {
  console.error('처리되지 않은 Promise rejection:', event.reason);
  event.preventDefault(); // 기본 동작 방지
});

// Node.js
process.on('unhandledRejection', (reason, promise) => {
  console.error('처리되지 않은 Promise rejection at:', promise, 'reason:', reason);
  // 로깅 서비스로 전송
});

4. Promise 생성자 내 에러 처리

Promise 내부에서 발생할 수 있는 에러를 명시적으로 reject로 전달합니다.

const safePromise = new Promise((resolve, reject) => {
  try {
    setTimeout(() => {
      // 비동기 작업
      const result = riskyOperation();
      resolve(result);
    }, 100);
  } catch (error) {
    reject(error);
  }
});

5. Promise.allSettled() 사용

모든 Promise의 결과를 기다리고 싶을 때는 Promise.all() 대신 Promise.allSettled()를 사용합니다.

const results = await Promise.allSettled([
  fetch('/api/user'),
  fetch('/api/posts'),
  fetch('/api/comments')
]);

results.forEach((result, index) => {
  if (result.status === 'fulfilled') {
    console.log(`요청 ${index} 성공:`, result.value);
  } else {
    console.error(`요청 ${index} 실패:`, result.reason);
  }
});

6. 유틸리티 래퍼 함수 생성

자주 사용하는 비동기 작업을 안전하게 감싸는 헬퍼 함수를 만듭니다.

async function safeAsync(asyncFn, defaultValue = null) {
  try {
    return await asyncFn();
  } catch (error) {
    console.error('에러 발생:', error);
    return defaultValue;
  }
}

// 사용 예시
const data = await safeAsync(
  () => fetch('/api/data').then(r => r.json()),
  { default: 'data' }
);

7. finally() 블록 활용

에러 여부와 관계없이 항상 실행되어야 하는 코드는 .finally()에 작성합니다.

fetch('/api/data')
  .then(response => response.json())
  .then(data => updateUI(data))
  .catch(error => showError(error))
  .finally(() => {
    hideLoadingSpinner(); // 항상 실행
  });

예방법과 베스트 프랙티스

1. ESLint 규칙 활용

no-floating-promises 규칙을 활성화하여 처리되지 않은 Promise를 자동으로 감지합니다.

// .eslintrc.json
{
  "rules": {
    "@typescript-eslint/no-floating-promises": "error"
  }
}

2. 명시적 에러 처리 정책

팀 내에서 “모든 Promise는 반드시 .catch() 또는 try-catch로 처리한다”는 코딩 규칙을 수립합니다.

3. 에러 로깅 시스템 구축

Sentry, LogRocket 같은 도구를 사용하여 프로덕션 환경의 unhandled rejection을 모니터링합니다.

4. 타입스크립트 사용

TypeScript의 타입 시스템을 활용하면 Promise 반환 함수를 명확히 표시하고 에러 처리를 강제할 수 있습니다.

5. 테스트 커버리지

단위 테스트에서 에러 케이스를 반드시 포함하여 모든 Promise rejection이 적절히 처리되는지 검증합니다.

마무리

Promise rejection unhandled 에러는 JavaScript 비동기 프로그래밍에서 피할 수 없는 주제입니다. 하지만 이 글에서 다룬 원인 분석과 해결 방법을 숙지하고, 베스트 프랙티스를 따른다면 안정적인 애플리케이션을 구축할 수 있습니다. 모든 Promise에 에러 핸들러를 추가하고, 전역 핸들러로 마지막 안전망을 구축하며, ESLint 같은 도구로 자동 검증하는 습관을 들이세요. 작은 실수가 큰 장애로 이어지지 않도록 항상 에러 처리에 신경 쓰는 것이 전문 개발자의 자세입니다. 지금 바로 여러분의 코드를 점검하고 unhandled rejection을 제거해보세요!

📚 함께 읽으면 좋은 글

1

Promise rejection unhandled 완벽 해결법 – 원인부터 예방까지

📂 JavaScript 에러
📅 2025. 10. 6.
🎯 Promise rejection unhandled

2

SyntaxError: Unexpected token 완벽 해결법 – 원인부터 예방까지

📂 JavaScript 에러
📅 2025. 10. 5.
🎯 SyntaxError: Unexpected token

3

Memory leak in JavaScript applications 완벽 해결법 – 원인부터 예방까지

📂 JavaScript 에러
📅 2025. 10. 4.
🎯 Memory leak in JavaScript applications

4

Memory leak in JavaScript applications 완벽 해결법 – 원인부터 예방까지

📂 JavaScript 에러
📅 2025. 10. 3.
🎯 Memory leak in JavaScript applications

5

SyntaxError: Unexpected token 완벽 해결법 – 원인부터 예방까지

📂 JavaScript 에러
📅 2025. 10. 3.
🎯 SyntaxError: Unexpected token

💡 위 글들을 통해 더 깊이 있는 정보를 얻어보세요!

📢 이 글이 도움되셨나요? 공유해주세요!

여러분의 공유 한 번이 더 많은 사람들에게 도움이 됩니다 ✨


📘 페이스북


🐦 트위터


✈️ 텔레그램

🔥 공유할 때마다 블로그 성장에 큰 힘이 됩니다! 감사합니다 🙏

💬 여러분의 소중한 의견을 들려주세요!

Promise rejection unhandled 관련해서 궁금한 점이 더 있으시다면 언제든 물어보세요!

💡
유용한 정보 공유

궁금한 점 질문

🤝
경험담 나누기

👍
의견 표현하기

⭐ 모든 댓글은 24시간 내에 답변드리며, 여러분의 의견이 다른 독자들에게 큰 도움이 됩니다!
🎯 건설적인 의견과 경험 공유를 환영합니다 ✨

🔔 블로그 구독하고 최신 글을 받아보세요!

📚
다양한 주제
17개 카테고리

정기 업데이트
하루 3회 발행

🎯
실용적 정보
바로 적용 가능

💡
최신 트렌드
2025년 기준

🌟 JavaScript 에러부터 다양한 실생활 정보까지!
매일 새로운 유용한 콘텐츠를 만나보세요 ✨

📧 RSS 구독 | 🔖 북마크 추가 | 📱 모바일 앱 알림 설정
지금 구독하고 놓치는 정보 없이 업데이트 받아보세요!

📱 전체 버전 보기