Files
2nd/10_Wiki/Topics/Coding/Observability_Error_Reporting.md
T
2026-05-09 21:08:02 +09:00

4.0 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
observability-error-reporting Error Reporting — Sentry / 분류 / 우선순위 Coding draft B conceptual 2026-05-09 2026-05-09
observability
error-reporting
sentry
vibe-coding
language applicable_to
TypeScript / Sentry / Bugsnag
Web
Backend
Mobile
Sentry
exception capture
source maps
fingerprinting

Error Reporting

로그만으로는 에러 우선순위 판단 어려움. Sentry / Bugsnag 같은 도구가 fingerprint / count / 영향 사용자 수 / breadcrumb / source map / 알림을 묶어줌. 단 모든 throw 가 capture 대상은 아님.

📖 핵심 개념

  • Fingerprint: 같은 종류 에러 묶기. 1만번 발생해도 하나의 issue.
  • Breadcrumb: 에러 직전의 사용자/시스템 액션 시퀀스.
  • Source map: minified 코드 stack 을 원본 매핑.
  • Release: 어떤 빌드에서 발생했는지. SHA / version 으로.
  • Sample rate: 트래픽 큰 곳은 sampling.

💻 코드 패턴

Sentry Node

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

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV,
  release: process.env.GIT_SHA,
  tracesSampleRate: 0.1,
  profilesSampleRate: 0.1,
  beforeSend(event, hint) {
    // PII redact
    if (event.user?.email) event.user.email = '[REDACTED]';
    // 무시할 에러
    if (hint.originalException instanceof KnownClientError) return null;
    return event;
  },
});

// Express integration
app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.tracingHandler());
// ... routes ...
app.use(Sentry.Handlers.errorHandler());

Sentry Browser (Vite/Next)

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

Sentry.init({
  dsn,
  release,
  integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()],
  tracesSampleRate: 0.1,
  replaysSessionSampleRate: 0.01,
  replaysOnErrorSampleRate: 1.0,
});

// React error boundary
<Sentry.ErrorBoundary fallback={<ErrorPage />}>{children}</Sentry.ErrorBoundary>

사용자 컨텍스트

Sentry.setUser({ id: user.id, email: user.email });
// 로그아웃
Sentry.setUser(null);

Custom fingerprint — 잘못 묶이는 경우

Sentry.captureException(err, {
  fingerprint: ['stripe-decline', err.code],
  tags: { provider: 'stripe', errorCode: err.code },
  extra: { orderId, userId },
});

의도적 무시

// 사용자가 cancel 한 fetch — 에러 X
fetch(...).catch(e => {
  if (e.name === 'AbortError') return; // Sentry 안 보냄
  Sentry.captureException(e);
});

🤔 의사결정 기준

에러 종류 capture
예측된 도메인 실패 (잔액 부족) — 정상 흐름
4xx (클라이언트 잘못) 보통
5xx (서버 버그)
외부 API 실패 (재시도 후 final fail) + provider tag
Browser unhandled rejection (자동)
React render error (ErrorBoundary onError)
AbortError
Network offline 또는 별도 이벤트

안티패턴

  • 모든 에러 capture: 노이즈 → 진짜 버그 파묻힘.
  • PII 그대로: 이메일 / 카드 / 토큰. beforeSend 에서 redact.
  • source map 안 업로드: stack 이 minified — 디버깅 불가. CI 가 release 와 함께 업로드.
  • release 태그 없음: 어떤 버전 사고인지 모름. git SHA 자동.
  • fingerprint 잘못: 같은 에러가 1000개 issue 로 분리. 또는 다른 에러가 한 issue 로.
  • 알림 없음 / 알림 폭주: critical 레벨만 PagerDuty. 나머지는 Slack/이메일.
  • breadcrumb 에 민감정보: form 입력 자동 캡처가 비밀번호 leak. denyUrls / mask.
  • dev 에서도 Sentry on: 노이즈. environment 분리.

🤖 LLM 활용 힌트

  • 새 catch 블록: "예측 가능 vs 시스템 에러 분류 후 system 만 capture" 강제.
  • ErrorBoundary onError + captureException + extra context.

🔗 관련 문서