Files
2nd/10_Wiki/Topics/Frontend/Error_Handling_and_Stability.md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

5.6 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-error-handling-and-stability Error Handling and Stability 10_Wiki/Topics verified self
Frontend Error Boundaries
Error Recovery
none A 0.9 applied
errors
stability
observability
sentry
2026-05-10 pending
language framework
TypeScript React/Vue

Error Handling and Stability

매 한 줄

"매 frontend stability = error 의 isolation + telemetry + graceful degradation.". 매 single uncaught error가 매 SPA 의 전체 white-screen 의 유발 — 매 ErrorBoundary, global handlers (window.onerror, unhandledrejection), 매 Sentry-class telemetry 가 필수. 매 2026의 트렌드는 React 19 ErrorBoundary + Sentry + Replay + AI-driven root-cause clustering.

매 핵심

매 layers

  • Component: React ErrorBoundary, Vue errorCaptured, Svelte <svelte:boundary>.
  • Async: try/catch, Promise .catch, unhandledrejection listener.
  • Global: window.onerror, window.onunhandledrejection.
  • Network: fetch retry, circuit breaker, AbortController.

매 telemetry 기둥

  • Capture (stack, breadcrumb, source map).
  • Group (fingerprint, dedup).
  • Alert (threshold, regression).
  • Replay (Sentry / LogRocket — DOM reconstruction).

매 응용

  1. SPA route-level boundary — 매 chunk load fail 의 reload prompt.
  2. Form submission retry with exponential backoff.
  3. Feature flag fallback when remote config unavailable.
  4. Service Worker offline shell.

💻 패턴

1. React ErrorBoundary (class)

import { Component, type ReactNode } from 'react';

interface State { error?: Error }

export class ErrorBoundary extends Component<{ fallback: ReactNode; children: ReactNode }, State> {
  state: State = {};
  static getDerivedStateFromError(error: Error): State { return { error }; }
  componentDidCatch(error: Error, info: React.ErrorInfo) {
    Sentry.captureException(error, { extra: { componentStack: info.componentStack } });
  }
  render() {
    return this.state.error ? this.props.fallback : this.props.children;
  }
}

2. react-error-boundary (functional)

import { ErrorBoundary } from 'react-error-boundary';

<ErrorBoundary
  fallbackRender={({ error, resetErrorBoundary }) => (
    <div role="alert">
      <p>Failed: {error.message}</p>
      <button onClick={resetErrorBoundary}>Retry</button>
    </div>
  )}
  onReset={() => location.reload()}
>
  <App />
</ErrorBoundary>

3. Global handlers

window.addEventListener('error', (e) => {
  Sentry.captureException(e.error ?? new Error(e.message));
});
window.addEventListener('unhandledrejection', (e) => {
  Sentry.captureException(e.reason);
});

4. Chunk load failure recovery

const lazyWithRetry = <T,>(load: () => Promise<{ default: T }>) =>
  React.lazy(async () => {
    try {
      return await load();
    } catch (err) {
      if (!sessionStorage.getItem('chunk-retried')) {
        sessionStorage.setItem('chunk-retried', '1');
        location.reload();
      }
      throw err;
    }
  });

5. Fetch retry with backoff

async function fetchRetry(url: string, retries = 3, delay = 500): Promise<Response> {
  try {
    const res = await fetch(url);
    if (!res.ok && res.status >= 500) throw new Error(`HTTP ${res.status}`);
    return res;
  } catch (err) {
    if (retries === 0) throw err;
    await new Promise((r) => setTimeout(r, delay));
    return fetchRetry(url, retries - 1, delay * 2);
  }
}

6. AbortController on unmount

useEffect(() => {
  const ac = new AbortController();
  fetch('/api/x', { signal: ac.signal }).catch((e) => {
    if (e.name !== 'AbortError') report(e);
  });
  return () => ac.abort();
}, []);

7. Sentry init (2026)

import * as Sentry from '@sentry/react';

Sentry.init({
  dsn: import.meta.env.VITE_SENTRY_DSN,
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.replayIntegration({ maskAllText: false }),
  ],
  tracesSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  release: import.meta.env.VITE_RELEASE,
});

8. Vue 3 errorHandler

import { createApp } from 'vue';
const app = createApp(App);
app.config.errorHandler = (err, instance, info) => {
  Sentry.captureException(err, { extra: { info } });
};

매 결정 기준

상황 Approach
Component-local fail ErrorBoundary at route level.
Async fail try/catch + telemetry.
Chunk 404 (deploy mid-session) lazyWithRetry + reload.
Transient 5xx Exponential backoff retry.
Auth expired Refresh token interceptor.

기본값: Sentry + Replay + per-route ErrorBoundary + global handlers.

🔗 Graph

🤖 LLM 활용

언제: ErrorBoundary scaffolding, retry helper 작성, Sentry config. 언제 X: 매 root-cause analysis from minified stack — 매 source map upload 필수.

안티패턴

  • Swallow errors: 매 catch {} 빈 — 매 silent fail.
  • No source map: 매 prod stack 의 a.b.c — 매 debug X.
  • Boundary at root only: 매 한 component fail이 매 entire app crash.
  • Console.error as monitoring: 매 user 의 console 의 도달 X — telemetry 필수.

🧪 검증 / 중복

  • Verified (Sentry docs, react.dev error boundary).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — Error boundary + Sentry 2026 patterns