본문 바로가기
일상이 개발

React 앱에서 에러 처리 제대로 하기 – UX를 해치지 않는 예외 설계 전략

by 디어노미 2025. 4. 15.
반응형

React 앱에서 사용자 경험을 해치지 않고 에러를 다루는 법 – 오류 처리 전략 및 예외 상황 UX 설계

프론트엔드 개발을 하다 보면 생각보다 자주 마주하게 되는 상황이 있습니다. 바로 에러 처리입니다. API 통신 실패, 컴포넌트 오류, 예기치 못한 예외 등…

이 포스팅에서는 React 기반 앱에서 에러를 감지하고 처리하며, 사용자 경험(UX)을 유지하는 방법을 총정리합니다. 실전에서 바로 쓸 수 있는 예제와 전략을 담았으니 끝까지 읽어주세요!


1. 에러 처리, 왜 중요한가?

React 앱은 예외가 발생하면 특정 컴포넌트의 UI가 깨지거나 전체 앱이 마비될 수 있습니다. try/catch만으로는 커버가 어려운 상황도 많습니다.

문제 발생 시 나쁜 예:

  • 페이지가 하얗게 됨
  • 콘솔에 에러만 출력되고 사용자에겐 무반응
  • 서버에서 내려온 오류 메시지를 그대로 노출

이제 우리는 사용자에게 더 나은 UX를 제공하는 쪽으로 나아가야 합니다.


2. React에서 에러를 감지하는 방법

📌 2-1. Error Boundary (에러 바운더리)

React에서는 렌더링 중 발생한 에러를 잡기 위해 Error Boundary를 사용합니다.

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    logErrorToService(error, info);
  }

  render() {
    if (this.state.hasError) {
      return <h2>문제가 발생했어요. 다시 시도해 주세요.</h2>;
    }
    return this.props.children;
  }
}

주의: Error Boundary는 render 중, constructor, lifecycle 에러만 처리하며 event handler 내부 에러는 잡지 못합니다.

📌 2-2. API 요청 오류 처리

서버에서 내려오는 에러는 대부분 axios 또는 fetch 사용 시 발생합니다.

try {
  const res = await axios.get("/api/data");
} catch (error) {
  setError("데이터를 불러오지 못했어요.");
}

Tip: 에러 유형에 따라 401/403/500 등의 상태 코드별 대응 메시지를 설계하세요.


3. 사용자 중심의 에러 UI 설계

🎨 3-1. 친절한 문구

  • ❌ “Error: Something went wrong”
  • ✅ “데이터를 불러오는 중 문제가 발생했어요. 잠시 후 다시 시도해 주세요.”

🎨 3-2. 복구 수단 제공

  • 🔁 새로고침 버튼
  • 📩 고객센터 링크
  • 🏠 홈으로 돌아가기

🎨 3-3. UX를 해치지 않는 디자인

전체 페이지 에러인지, 일부분 에러인지에 따라 UI 위치를 전략적으로 설계해야 합니다.

예:

  • 목록 영역만 오류 → 스켈레톤 대신 오류 메시지
  • 페이지 전체 오류 → 풀 페이지 에러 페이지

4. 실전 패턴: 에러 처리 시스템화하기

🧩 4-1. 공통 ErrorBoundary 컴포넌트 만들기

프로젝트 전역에서 재사용 가능한 에러 바운더리 컴포넌트를 만들어 각 페이지 또는 섹션에 감싸줍니다.

<ErrorBoundary>
  <Dashboard />
</ErrorBoundary>

🧩 4-2. API 에러 처리를 위한 hook 만들기

function useApiError() {
  const [error, setError] = useState(null);

  const handleError = (err) => {
    if (axios.isAxiosError(err)) {
      if (err.response?.status === 401) {
        setError("로그인이 필요합니다.");
      } else {
        setError("오류가 발생했습니다.");
      }
    }
  };

  return { error, handleError };
}

🧩 4-3. 예외 로깅 시스템 연동

Sentry, LogRocket, Firebase Crashlytics 등을 통해 실제 에러가 발생한 상황을 기록해두면, 사용자로부터 “오류가 났어요”라는 말 없이도 사후 대응이 가능해집니다.


5. Next.js 환경에서의 추가 전략

Next.js에서는 _error.js 또는 error.js 파일을 통해 서버 사이드 에러도 대응할 수 있습니다.

// app/error.js (Next.js 13 이후 App Router)
export default function GlobalError({ error, reset }) {
  return (
    <div>
      문제가 발생했어요. <button onClick={() => reset()}>다시 시도하기</button>
    </div>
  );
}

서버 → 클라이언트 → 사용자 UX까지 끊김없이 대응하는 것이 중요합니다.


6. 마무리 – '에러가 곧 신뢰다'

완벽한 앱은 없습니다. 결국 중요한 건 “문제가 생겼을 때 어떻게 대처하는가”입니다.

이 글에서 소개한 전략을 정리하면 다음과 같습니다:

  • 렌더링 에러는 ErrorBoundary로 감싸기
  • API 에러는 try/catch + 상태코드별 UX
  • 사용자에게는 친절한 안내와 복구 수단
  • 로그는 기록하고, 반복되지 않도록 개선

에러 UX는 기술적인 디테일뿐 아니라 브랜드 이미지까지 좌우할 수 있는 요소입니다.
오늘부터 실무에 바로 적용해보세요 😊


 

반응형