Skip to content

[FEAT] Sentry 알림이 대응 판단으로 이어지도록 이벤트 맥락 개선#469

Merged
useon merged 8 commits into
developfrom
feat/#468
Jul 23, 2026
Merged

[FEAT] Sentry 알림이 대응 판단으로 이어지도록 이벤트 맥락 개선#469
useon merged 8 commits into
developfrom
feat/#468

Conversation

@useon

@useon useon commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

🚩 연관 이슈

closed #468

📝 작업 내용

기존에는 이렇게 알림이 와서 알림만 보고 어떤 에러가 어떻게 발생한다는 것을 빠르게 파악하기 힘들었습니다.
image

이번 작업은 Sentry 알림을 단순히 “에러가 발생했다”는 신호로 두지 않고, 알림을 받았을 때 어떤 사용자 흐름에서 문제가 생겼고 지금 확인해야 하는지 판단할 수 있도록 이벤트 맥락을 정리한 작업입니다.

기존 Sentry 설정은 에러 수집, Replay, Source Map을 통해 디버깅 가능한 상태를 만드는 데에는 효과적이었습니다. 다만 실제로 알림을 받아보면, 알림만 보고 어떤 기능에서 발생한 문제인지, 사용자 핵심 흐름에 영향을 주는지, 바로 대응해야 하는지 판단하기 어려웠습니다.

그래서 이번 PR에서는 알림 수신자의 다음 행동을 돕는 방향으로 Sentry 이벤트의 제목, 태그, level, grouping 기준을 개선했습니다.

1. Sentry 알림 판단 기준 유틸 분리

  • Sentry 이벤트에 필요한 판단 기준을 src/util/sentry.ts로 분리했습니다.
  • endpoint 정규화, pathname 기반 feature 분류, API error level 결정, 수집 제외 기준을 순수 함수로 정리했습니다.
  • 알림 정책이 axiosInstance 내부에 섞이지 않도록 분리해서, 이후 라우트나 핵심 기능 기준이 바뀌어도 수정 범위를 좁힐 수 있게 했습니다.

이번 작업은 “어떤 에러를 어떤 맥락의 알림으로 볼 것인가”를 테스트 가능한 기준으로 만들기 위한 목적입니다.

2. 알림에서 사용자 영향 흐름이 보이도록 feature tag 추가

  • pathname을 기준으로 timer, vote, live-share, debate-end 등 사용자 흐름 단위의 feature를 분류했습니다.
  • API 에러와 렌더링 에러에 feature tag를 붙여, Sentry 알림만 봐도 어떤 화면/기능에서 문제가 발생했는지 파악할 수 있도록 했습니다.

기존에는 endpoint나 status는 확인할 수 있었지만, 이 에러가 실제로 어떤 사용자 행동에 영향을 주는지 알림만 보고 판단하기 어려웠습니다. 이번 작업에서는 알림을 여는 순간 “타이머 진행 중 문제인지”, “투표 흐름 문제인지”, “실시간 공유 문제인지”를 먼저 볼 수 있게 만드는 데 집중했습니다.

3. API 에러 이슈 제목과 grouping 기준 개선

  • API 에러를 Sentry에 보낼 때 이슈 제목에 status, method, endpoint가 드러나도록 정리했습니다.
    • 예: [network-error] POST /api/live/:id
  • endpoint의 숫자 id, uuid, query string은 정규화해서 같은 API 장애가 하나의 이슈로 묶이도록 했습니다.
  • fingerprint도 api-error + status + method + endpoint 기준으로 정리했습니다.

사용자별 id 값 때문에 같은 장애가 여러 이슈로 흩어지면 알림 피로도가 커지고 원인 파악도 늦어진다고 봤습니다. 그래서 “같은 문제는 같은 알림 이슈로 묶이게 하는 것”을 기준으로 정리했습니다.

4. 대응 가치 기준으로 error level과 필터링 정리

  • 핵심 흐름의 서버성 에러는 더 높은 우선순위로 볼 수 있도록 level 기준을 정리했습니다.
  • 사용자 입력이나 상태 충돌처럼 예상 가능한 에러는 warning으로 낮췄습니다.
  • 토큰 재발급으로 복구 가능한 401, 사용자 오프라인 상태의 네트워크 에러처럼 바로 대응하기 어려운 이벤트는 수집에서 제외했습니다.

여기서 중요한 기준은 에러를 덜 보는 것이 아니라, 실제로 확인해야 할 알림의 신뢰도를 높이는 것이었습니다.

5. 렌더링 에러에도 feature 맥락 추가

  • ErrorBoundary에서 잡힌 렌더링 에러는 화면이 깨진 상태로 보고 fatal로 분류했습니다.
  • 렌더링 에러에도 pathname 기반 feature tag를 추가했습니다.
  • render-error + feature 기준 fingerprint를 설정해 같은 기능의 렌더링 장애가 묶이도록 했습니다.
  • API 인터셉터에서 이미 캡처한 에러는 중복 전송되지 않도록 기준을 통일했습니다.

6. 알림 제목 개선 전/후

API 에러와 렌더링 에러 모두 알림 제목에서 level → errorType → feature → 세부 원인 순서로 읽히도록 정리했습니다.

구분 개선 전 개선 후
API 에러 AxiosError: Request failed with status code 500 fatal · api-error · live-share · [500] GET /api/live/:id
렌더링 에러 TypeError: Cannot read properties of undefined fatal · render-error · timer · TypeError: Cannot read properties of undefined

개선 전에는 제목만 보고 어떤 사용자 흐름에서 문제가 발생했는지, 어떤 요청이 실패했는지, 지금 바로 대응해야 하는지 판단하기 어려웠습니다.

개선 후에는 제목만 보고도 아래 순서로 문제를 읽을 수 있습니다.

  • fatal: 대응 우선순위
  • api-error / render-error: 에러 종류
  • live-share / timer: 영향받은 사용자 흐름
  • [500] GET /api/live/:id / TypeError: ...: 실패 요청 또는 원본 에러

✅ 검증

  • src/util/sentry.test.ts
    • 8개 테스트 통과
  • tsc --build --noEmit
    • 통과
  • 수정 파일 대상 ESLint
    • 통과

🗣️ 리뷰 요구사항 (선택)

이번 PR에서는 “Sentry에 더 많이 남기기”보다 “알림을 받았을 때 바로 판단할 수 있게 만들기”에 초점을 뒀습니다.

feature 분류 기준이나 error level 기준이 실제 운영 관점에서 어색한 부분이 있다면 편하게 의견 주세요 ~ !!

Summary by CodeRabbit

개선 사항

  • API/렌더링 오류를 표준화해 기능·요청 정보·심각도 중심의 일관된 메타데이터로 Sentry에 기록합니다.
  • 중복 캡처는 안정적으로 차단하고, 복구 가능한 인증 오류 및 오프라인 네트워크 오류는 전송을 건너뛰도록 동작을 조정했습니다.
  • 렌더링 오류는 기능 식별 태그와 상세 렌더링 컨텍스트를 포함해 withScope 방식으로 캡처되도록 변경했습니다.

테스트

  • 오류 스킵 조건, 에러 레벨 매핑, 마스킹/메타데이터 생성, 캡처 여부 처리에 대한 테스트를 추가했습니다.

@useon
useon requested a review from i-meant-to-be July 22, 2026 13:49
@useon useon self-assigned this Jul 22, 2026
@useon useon added the feat 기능 개발 label Jul 22, 2026
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Sentry 오류 처리를 공통 유틸리티로 통합하고, API 경로·기능·상태·네트워크 상태를 기반으로 이벤트 메타데이터와 심각도를 산출하도록 변경했습니다. Axios, APIError, ErrorBoundary의 중복 캡처 방지 흐름도 공통 플래그 헬퍼를 사용하도록 조정했습니다.

Changes

Sentry 오류 맥락 처리

Layer / File(s) Summary
Sentry 오류 유틸리티와 검증
src/util/sentry.ts, src/util/sentry.test.ts
엔드포인트 정규화, 기능 분류, 심각도 계산, API 오류 제외 조건, 민감정보 마스킹, 메타데이터·Sentry 오류 생성, 캡처 플래그 처리를 추가하고 테스트했습니다.
Axios API 오류 캡처 흐름
src/apis/axiosInstance.ts
Axios 오류 캡처가 공통 유틸리티로 스킵 여부와 메타데이터를 결정하고, Sentry scope에 태그·컨텍스트·fingerprint를 설정하도록 변경했습니다.
APIError 및 ErrorBoundary 연동
src/apis/primitives.ts, src/components/ErrorBoundary/ErrorBoundary.tsx
APIError와 ErrorBoundary가 공통 캡처 플래그를 사용하며, 렌더링 오류에 기능 태그와 정제된 렌더링 컨텍스트를 설정하도록 변경했습니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AxiosRequest
  participant SentryUtilities
  participant Sentry
  participant ErrorBoundary
  AxiosRequest->>SentryUtilities: AxiosError 분석
  SentryUtilities-->>AxiosRequest: 스킵 여부·메타데이터·Sentry Error
  AxiosRequest->>Sentry: API 오류 캡처 및 플래그 표시
  AxiosRequest->>ErrorBoundary: APIError 전달
  ErrorBoundary->>Sentry: 미캡처 렌더링 오류 전송
Loading

Possibly related PRs

Suggested reviewers: i-meant-to-be, jaeml06

Poem

토끼가 오류 길을 정리해요,
기능과 상태를 살펴봐요.
민감한 값은 살짝 가리고,
중복 신호는 넘겨보내며,
Sentry 숲에 맥락을 심어요.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed 연결 이슈의 목표인 Sentry 알림에 판단용 맥락을 추가해 우선순위 판단을 쉽게 하는 개선이 반영되었습니다.
Out of Scope Changes check ✅ Passed 추가된 테스트와 유틸 리팩터링은 모두 Sentry 맥락 개선 범위에 속하며 명백한 무관 변경은 보이지 않습니다.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Sentry 알림의 맥락, 분류, 그룹핑을 개선해 대응 판단을 돕는다는 변경 내용을 잘 요약합니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#468

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

🚀 Preview 배포 완료!

환경 URL
Preview 열기
API Dev 환경

PR이 닫히면 자동으로 정리됩니다.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/util/sentry.ts (2)

17-17: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

상수 네이밍 컨벤션 위반.

criticalFeatures는 새로 추가된 모듈 레벨 상수 배열인데 camelCase로 작성되어 있습니다. As per coding guidelines, **/*.{ts,tsx} 파일은 "UPPER_SNAKE_CASE for constants"를 요구합니다.

♻️ 제안
-const criticalFeatures: DebateFeature[] = ['timer', 'vote', 'live-share'];
+const CRITICAL_FEATURES: DebateFeature[] = ['timer', 'vote', 'live-share'];

(사용처인 resolveApiErrorLevel의 참조도 함께 변경 필요)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/util/sentry.ts` at line 17, Rename the module-level constant
criticalFeatures to the required UPPER_SNAKE_CASE convention, and update its
reference in resolveApiErrorLevel accordingly while preserving the existing
array contents and behavior.

Source: Coding guidelines


147-157: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

sentryError에 설정한 __sentry_captured__ 플래그는 사용되지 않는 죽은 코드입니다.

154번 줄에서 새로 생성한 sentryError에 플래그를 설정하지만, 이 객체는 Sentry.captureException에만 전달되고 버려집니다. 실제 중복 캡처 방지는 axiosInstance.ts에서 원본 error에 대해 별도로 호출하는 markSentryCaptured(error)가 담당합니다. 이 줄은 오해를 유발할 수 있으니 제거를 고려해 주세요.

♻️ 제안
   const sentryError = new Error(error.message);
   sentryError.name = `[${metadata.statusLabel}] ${metadata.method} ${metadata.endpoint}`;
   sentryError.stack = error.stack;
-  (sentryError as SentryCapturedError).__sentry_captured__ = true;
 
   return sentryError;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/util/sentry.ts` around lines 147 - 157, Remove the __sentry_captured__
assignment from createSentryApiError; duplicate-capture prevention is handled by
markSentryCaptured(error) on the original AxiosError, so leave the constructed
sentryError without this unused flag.
src/util/sentry.test.ts (1)

2-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

markSentryCaptured/isSentryCaptured에 대한 직접 테스트 추가를 권장합니다.

이 두 함수는 axiosInstance, primitives, ErrorBoundary 세 곳이 공유하는 중복 캡처 방지 계약의 핵심입니다. 계약이 깨지면 조용히 중복 알림 또는 알림 누락이 발생할 수 있으므로, import 목록에 추가해 간단한 단위 테스트를 붙이면 좋겠습니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/util/sentry.test.ts` around lines 2 - 9, sent​​ry 유틸리티의
markSentryCaptured와 isSentryCaptured를 직접 import하고, 동일한 오류 객체에 캡처 표시를 설정한 뒤
isSentryCaptured가 표시 전후에 올바른 값을 반환하는 단위 테스트를 추가하세요. 서로 다른 오류 객체는 독립적으로 처리되는지와 기존
중복 캡처 방지 계약을 검증하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/apis/axiosInstance.ts`:
- Around line 71-83: Prevent raw user-controlled data from reaching Sentry by
introducing a shared masking or allowlist utility. In
src/apis/axiosInstance.ts#L71-L83, apply it to request params and response data
before setContext; in src/components/ErrorBoundary/ErrorBoundary.tsx#L49-L53,
sanitize window.location.search by masking or removing sensitive parameters such
as token, code, and state before setting the render context.

In `@src/util/sentry.ts`:
- Around line 48-96: Update resolveFeatureFromPathname so every startsWith route
check enforces a path-segment boundary, matching removeLanguagePrefix behavior:
accept the route only when the pathname ends at that prefix or the next
character is /. Apply this to /composition, /overview, /vote, /table/customize,
/oauth, /share, and /live while preserving the existing route order and feature
mappings.

---

Nitpick comments:
In `@src/util/sentry.test.ts`:
- Around line 2-9: sent​​ry 유틸리티의 markSentryCaptured와 isSentryCaptured를 직접
import하고, 동일한 오류 객체에 캡처 표시를 설정한 뒤 isSentryCaptured가 표시 전후에 올바른 값을 반환하는 단위 테스트를
추가하세요. 서로 다른 오류 객체는 독립적으로 처리되는지와 기존 중복 캡처 방지 계약을 검증하세요.

In `@src/util/sentry.ts`:
- Line 17: Rename the module-level constant criticalFeatures to the required
UPPER_SNAKE_CASE convention, and update its reference in resolveApiErrorLevel
accordingly while preserving the existing array contents and behavior.
- Around line 147-157: Remove the __sentry_captured__ assignment from
createSentryApiError; duplicate-capture prevention is handled by
markSentryCaptured(error) on the original AxiosError, so leave the constructed
sentryError without this unused flag.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 90ced027-62ba-45c6-b28c-234f5bfa68e1

📥 Commits

Reviewing files that changed from the base of the PR and between 2bb54aa and 7d9d167.

📒 Files selected for processing (5)
  • src/apis/axiosInstance.ts
  • src/apis/primitives.ts
  • src/components/ErrorBoundary/ErrorBoundary.tsx
  • src/util/sentry.test.ts
  • src/util/sentry.ts

Comment thread src/apis/axiosInstance.ts
Comment thread src/util/sentry.ts

@i-meant-to-be i-meant-to-be left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 매번 센트리 오류 오는 거 잘 안 봤는데 이렇게 개선되면 확실히 보기 편하겠네요... 조은 PR 감사합니다!

딱히 문제 될 내용은 없어 보여 승인 남깁니다 깔끔한 작업 최고 👍👍👍

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/util/sentry.ts (1)

18-33: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

모듈 상수 명명 규칙을 맞춰 주세요.

filteredValue, sensitiveKeys는 불변 모듈 상수이므로 FILTERED_VALUE, SENSITIVE_KEYS로 변경하고 사용처도 함께 갱신하세요.

As per coding guidelines, **/*.{ts,tsx}: “UPPER_SNAKE_CASE for constants”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/util/sentry.ts` around lines 18 - 33, Rename the module constants
filteredValue and sensitiveKeys to FILTERED_VALUE and SENSITIVE_KEYS,
respectively, and update every reference to those symbols throughout the sentry
utility.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/util/sentry.ts`:
- Around line 201-215: API 요청 URL이 원문으로 Sentry에 기록되지 않도록 `sanitizeSentrySearch`와
별도로 URL 전용 sanitizer를 추가하고, `src/apis/axiosInstance.ts`의 `error.config?.url`을
`request.url`에 저장하는 경로에서 이를 적용하세요. URL의 쿼리 파라미터 중 `code`, `access_token`,
`email` 등 `isSensitiveKey` 대상만 마스킹하고 경로와 비민감 파라미터는 유지해야 합니다.

---

Nitpick comments:
In `@src/util/sentry.ts`:
- Around line 18-33: Rename the module constants filteredValue and sensitiveKeys
to FILTERED_VALUE and SENSITIVE_KEYS, respectively, and update every reference
to those symbols throughout the sentry utility.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4522d930-23cc-4446-9789-e08a22d57552

📥 Commits

Reviewing files that changed from the base of the PR and between 3f76c30 and a1d3219.

📒 Files selected for processing (4)
  • src/apis/axiosInstance.ts
  • src/components/ErrorBoundary/ErrorBoundary.tsx
  • src/util/sentry.test.ts
  • src/util/sentry.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/components/ErrorBoundary/ErrorBoundary.tsx
  • src/apis/axiosInstance.ts

Comment thread src/util/sentry.ts
@useon
useon merged commit cbd7c32 into develop Jul 23, 2026
3 checks passed
@useon
useon deployed to DEPLOY_DEV July 23, 2026 13:01 — with GitHub Actions Active
@useon
useon deployed to PREVIEW_ENV July 23, 2026 13:01 — with GitHub Actions Active
@github-actions

Copy link
Copy Markdown

🧹 Preview 배포가 정리되었습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] Sentry 알림이 대응 판단으로 이어지도록 이벤트 맥락 개선

2 participants