Skip to content

Comments

[Feature] 전역 에러 처리 및 Sentry 연동#1196

Merged
seongwon030 merged 11 commits intodevelop-fefrom
feature/#1193-error-Boundary-sentry-integration-MOA-646
Feb 14, 2026
Merged

[Feature] 전역 에러 처리 및 Sentry 연동#1196
seongwon030 merged 11 commits intodevelop-fefrom
feature/#1193-error-Boundary-sentry-integration-MOA-646

Conversation

@seongwon030
Copy link
Member

@seongwon030 seongwon030 commented Feb 13, 2026

#️⃣연관된 이슈

ex) #1193

📝작업 내용

Sentry를 도입했지만 컴포넌트 내부에서 에러를 처리하고 있었기에 상위에서 에러를 잡지 못 하고 있었습니다.
그래서 전역 에러 바운더리를 도입하여 공통된 에러폴백을 보여주도록 했고, Sentry에 에러가 전파되도록 개선했습니다.

프로덕션 환경에서는 에러메세지 안 뜸

스크린샷 2026-02-13 오후 9 48 13

1. 전역 에러 바운더리 구현

  • GlobalBoundary 컴포넌트 생성 (Sentry ErrorBoundary + React Suspense 통합)
  • GlobalErrorFallback 폴백 UI 제공
  • "다시 시도" 및 "홈으로 이동" 버튼 제공
  • 개발 환경에서만 에러 상세 정보 노출

/error-test경로에서 동기 에러, 비동기 에러, tanstack에러, 이벤트 핸들러 에러, 타입 에러를 각각 테스트할 수 있습니다.
개발 환경에서만 테스트할 수 있도록 했습니다.

2. Tanstack Query 에러 전파 설정

  • throwOnError: true 설정으로 Query 에러를 ErrorBoundary로 전파
  • Mutation은 throwOnError: false로 설정

Mutation은 수정/삭제 요청이 대부분이며 이것을 에러바운더리로 넘긴다면, 사용자는 요청이 실패하면 에러페이지를 보게됩니다.
이것보다는 토스트로 간단하게 띄워주는 것이 더 낫다고 판단했습니다.

3. Sentry 성능 모니터링 연동

browserTracingIntegration 추가로 페이지 로드, 라우팅, API 성능 추적 가능. 이걸로 LCP측정도 가능합니다.

4. Suspense 제거

Suspense는 전역적으로 관리되는 Suspense UI가 있어야 하지만 현재는 각 컴포넌트 내에서 로딩, 에러 상태를 관리합니다.
그리고 새로 추가된 전역 에러 바운더리에서 Suspense로 스피너를 띄웁니다. 기존 App.tsx에 있던 Suspense는 이 두 가지 이유로 필요가 없어서 제거했습니다. (사실 원래도 필요가 없었습니다..)

5. 메인페이지 내부 에러처리

메인페이지에서 에러가 뜨면 전역에러 폴백을 보여주는데, 이 부분이 부자연스러웠습니다. api는 카드 부분인데 헤더, 배너, 푸터,
카테고리 버튼 등이 모두 안 보이면 사용자 경험이 더 안 좋다고 판단했습니다.

그래서 error 발생 시 전역으로 던지지 않고 페이지 내부에서 refetch할 수 있도록 디자인을 변경했습니다.

그리고 throwOnError옵션도 일단 제거했습니다. 추후 전역으로 처리할 에러를 정한 뒤 다시 고려해보겠습니다.

스크린샷 2026-02-14 오후 4 44 52

추후 할 작업

  • APIError 바운더리 추가
  • ContentError 바운더리 추가

논의하고 싶은 부분(선택)

논의하고 싶은 부분이 있다면 작성해주세요.

🫡 참고사항

- 페이지 로드 및 라우팅 성능 모니터링을 위해 browserTracingIntegration 설정 추가
- 동기 런타임, 비동기에러, API에러, 이벤트 핸들러 에러, 타입 에러 테스트
- Sentry.ErrorBoundary로 최상위 컴포넌트 래핑하여 런타임 에러 포착
- GlobalErrorFallback 컴포넌트 연결
- 개발 환경 전용 에러 테스트 라우트(/error-test) 추가
- Sentry.ErrorBoundary와 Suspense를 결합한 GlobalBoundary 컴포넌트 생성
- App 최상위에 적용하여 전역 에러 핸들링 및 코드 스플리팅/Suspense 로딩 처리 일원화
- App.tsx 내의 불필요한 개별 Suspense 래퍼 제거 (GlobalBoundary로 위임)
- App.tsx: 각 페이지 라우트의 Suspense(fallback=null) 래퍼 제거
@seongwon030 seongwon030 self-assigned this Feb 13, 2026
@seongwon030 seongwon030 added ✨ Feature 기능 개발 💻 FE Frontend labels Feb 13, 2026
@vercel
Copy link

vercel bot commented Feb 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
moadong Ready Ready Preview, Comment Feb 14, 2026 7:43am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 13, 2026

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Invalid regex pattern for base branch. Received: "**" at "reviews.auto_review.base_branches[0]"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

Sentry와 통합된 전역 에러 바운더리를 구현하여 애플리케이션 전체에서 발생하는 런타임 에러를 캡처하고 처리합니다. 개발 환경에서 에러를 테스트할 수 있는 페이지를 추가하며, TanStack Query 에러 처리 설정을 업데이트합니다.

Changes

Cohort / File(s) Summary
Global Error Handling
frontend/src/components/common/ErrorBoundary/GlobalBoundary.tsx, frontend/src/components/common/ErrorBoundary/GlobalErrorFallback.tsx, frontend/src/components/common/ErrorBoundary/GlobalErrorFallback.styles.ts, frontend/src/components/common/ErrorBoundary/index.ts
Sentry ErrorBoundary를 래핑하는 GlobalBoundary 컴포넌트 추가 및 사용자 친화적 에러 폴백 UI 구현. 개발 모드에서는 에러 상세 정보 표시, 프로덕션에서는 숨김 처리.
Error Testing Page
frontend/src/pages/ErrorTestPage/ErrorTestPage.tsx, frontend/src/pages/ErrorTestPage/ErrorTestPage.styles.ts
동기/비동기 에러, 이벤트 핸들러 에러, React Query 에러 등 다양한 에러 시나리오를 테스트할 수 있는 개발 전용 페이지 추가.
App Configuration
frontend/src/App.tsx, frontend/src/utils/initSDK.ts
Suspense 래퍼 제거 및 GlobalBoundary로 전체 앱 감싸기. DEV 플래그로 보호된 /error-test 라우트 추가. React Query 설정에서 queries의 throwOnError를 true로 설정.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App as App Component
    participant GlobalBoundary
    participant SentryErrorBoundary as Sentry ErrorBoundary
    participant Fallback as GlobalErrorFallback
    participant Sentry

    User->>App: 애플리케이션 사용
    App->>GlobalBoundary: 앱 렌더링
    GlobalBoundary->>SentryErrorBoundary: children 감싸기
    
    User->>App: 에러 발생 액션
    App-->>SentryErrorBoundary: throw Error
    SentryErrorBoundary->>Sentry: 에러 캡처/전송
    SentryErrorBoundary->>Fallback: error & resetError 전달
    Fallback-->>User: 에러 폴백 UI 표시
    
    User->>Fallback: 다시 시도 / 홈으로 이동 선택
    Fallback->>SentryErrorBoundary: resetError() 호출
    SentryErrorBoundary->>App: 앱 상태 복구
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • oesnuj
  • lepitaaar
  • suhyun113
🚥 Pre-merge checks | ✅ 4 | ❌ 2
❌ Failed checks (2 warnings)
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.
Merge Conflict Detection ⚠️ Warning ⚠️ Unable to check for merge conflicts: Invalid branch name format
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목 '[Feature] 전역 에러 처리 및 Sentry 연동'은 변경 사항의 주요 내용(전역 에러 처리와 Sentry 통합)을 명확하고 간결하게 요약합니다.
Linked Issues check ✅ Passed PR은 MOA-646의 모든 주요 요구사항을 충족합니다: GlobalBoundary(Sentry ErrorBoundary 포함) 설정, App.tsx 최상위 적용, TanStack Query throwOnError 설정, 에러 폴백 UI 구현.
Out of Scope Changes check ✅ Passed 모든 변경 사항이 전역 에러 처리 및 Sentry 통합 범위 내에 있으며, ErrorBoundary 컴포넌트, 에러 UI, 테스트 페이지, Sentry 설정은 모두 정의된 목표와 직접 관련됩니다.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/#1193-error-Boundary-sentry-integration-MOA-646
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch feature/#1193-error-Boundary-sentry-integration-MOA-646
  • Create stacked PR with resolved conflicts
  • Post resolved changes as copyable diffs in a comment

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 and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/utils/initSDK.ts (1)

44-47: ⚠️ Potential issue | 🔴 Critical

import.meta.env.NODE_ENV는 Vite에서 기본적으로 제공되지 않습니다.

현재 프로젝트의 Vite 설정(./frontend/config/vite.config.ts)에는 NODE_ENV 정의가 없으며, Vite는 표준으로 MODE, DEV, PROD, SSR만 제공합니다. import.meta.env.NODE_ENVundefined가 되어 조건이 항상 거짓이 되므로, 개발 환경에서도 Sentry가 초기화됩니다. 프로젝트의 다른 파일들(index.tsx:9, ErrorBoundary.tsx:25)에서는 이미 import.meta.env.DEV를 올바르게 사용하고 있습니다.

제안된 수정
 export function initializeSentry() {
-  if (import.meta.env.NODE_ENV === 'development') {
+  if (import.meta.env.DEV) {
     return;
   }
🤖 Fix all issues with AI agents
In `@frontend/src/pages/ErrorTestPage/ErrorTestPage.tsx`:
- Around line 111-121: The current throwTypeError handler triggers an error in
an event handler (outside React render), so ErrorBoundary won't catch it;
replace that pattern by adding a shouldThrow boolean state (e.g.,
useState(false)) and a toggle function invoked by Styled.TestButton that sets
shouldThrow=true, then in the component render if (shouldThrow) throw new
TypeError(...) so the error occurs during rendering and is catchable by
ErrorBoundary; update the section title text (Styled.SectionTitle) to accurately
state "ErrorBoundary 캐치" remains correct and keep or set the button $variant
appropriately (e.g., keep 'danger' since it will now throw during render) and
remove or repurpose the existing throwTypeError function.
🧹 Nitpick comments (3)
frontend/src/components/common/ErrorBoundary/GlobalBoundary.tsx (1)

12-18: errorData.error as Error 타입 단언이 안전하지 않을 수 있습니다.

throw "string"Error 인스턴스가 아닌 값이 던져지면 error.messageundefined로 표시될 수 있습니다. 방어적으로 처리하는 것을 권장합니다.

제안된 수정
     <Sentry.ErrorBoundary
       fallback={(errorData) => {
+        const error =
+          errorData.error instanceof Error
+            ? errorData.error
+            : new Error(String(errorData.error));
         return (
           <GlobalErrorFallback
-            error={errorData.error as Error}
+            error={error}
             resetError={errorData.resetError}
           />
         );
       }}
     >
frontend/src/App.tsx (2)

20-20: ErrorTestPage가 정적 import로 프로덕션 번들에 포함됩니다.

개발 환경 전용 페이지이지만 lazy가 아닌 정적 import이므로, 프로덕션 빌드에도 해당 코드가 포함됩니다. lazy를 사용하거나 조건부 동적 import로 변경하면 프로덕션 번들 크기를 줄일 수 있습니다.

제안된 수정
-import ErrorTestPage from './pages/ErrorTestPage/ErrorTestPage';
+const ErrorTestPage = lazy(
+  () => import('./pages/ErrorTestPage/ErrorTestPage'),
+);

22-34: 전역 throwOnError: true 설정이 에러 처리에 미치는 영향 검토 필요

현재 일부 쿼리 훅(useApplication, usePromotion, useClub 등)과 뮤테이션에서 onError 콜백으로 인라인 에러 처리를 하고 있습니다. 다만 이 패턴이 모든 쿼리에 일관되게 적용되지 않으면, 에러 처리가 없는 쿼리의 실패는 ErrorBoundary로 전파됩니다. 다음 중 하나를 고려해 주세요:

  • 모든 쿼리가 onError 콜백을 통해 인라인 에러 처리를 하도록 통일
  • 토스트, 재시도 UI 등이 필요한 쿼리는 개별적으로 throwOnError: false 설정
  • 또는 throwOnError: (error) => error.status >= 500 같이 특정 에러만 throw하도록 조건부 처리

Copy link
Contributor

@lepitaaar lepitaaar left a comment

Choose a reason for hiding this comment

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

오 개굳;;;;;;;;;; 미쳤는데요? 센트리까지 전파 너무좋습니다. 프론트도 에러 로깅되겠군요

- 에러 발생 시 GlobalErrorFallback 대신 콘텐츠 영역에 에러 메시지와 재시도 버튼 표시
- 헤더/네비게이션을 유지하여 사용자가 쉽게 복구 가능
- 각 페이지에서 에러를 직접 처리하여 레이아웃 유지 및 복구 가능성 향상
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@frontend/src/App.tsx`:
- Line 20: The file currently uses a static import of ErrorTestPage which forces
its code into production bundles; replace the static import with a dynamic/lazy
load: remove the top-level "import ErrorTestPage ..." and instead create a
lazy-loaded component (e.g. React.lazy(() =>
import('./pages/ErrorTestPage/ErrorTestPage'))) and render it only inside the
import.meta.env.DEV guard, wrapping the route in Suspense with a fallback so the
lazy component loads correctly; update any references to ErrorTestPage in the
router/route rendering to use the new lazy component name.
🧹 Nitpick comments (1)
frontend/src/pages/MainPage/MainPage.styles.ts (1)

122-148: box-shadow에 하드코딩된 색상값 사용

Line 137의 rgba(255, 84, 20, 0.3)는 하드코딩되어 있지만, 배경색은 테마(theme.colors.primary)를 참조하고 있습니다. 테마의 primary 색상이 변경되면 box-shadow 색상이 불일치하게 됩니다. 가능하다면 테마 색상 기반으로 통일하는 것을 고려해 주세요.

Copy link
Member

@oesnuj oesnuj left a comment

Choose a reason for hiding this comment

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

에러 바운더리 추가 고생하셨습니다
바운더리 하위 컴포넌트 단에서도 세세하게 처리해서 더 안정적으로 만들어봅시다
Sentry도 잘 활용해보기

Comment on lines +20 to +21
<Suspense fallback={<Spinner />}>{children}</Suspense>
</Sentry.ErrorBoundary>
Copy link
Member

Choose a reason for hiding this comment

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

Suspense가 GlobalBoundary로 이동하면서 로딩과 에러 처리가 한 곳에서 관리되도록 정리된 것 같네요
App.tsx에서 덕지덕지 관리하던 것보다 책임이 분리되어 좋아 보입니다 ㅎㅎ
(물론 Suspense 트리거가 없긴하지만... 안전빵으로 있는 것도 좋은 듯해요)

Copy link
Member Author

Choose a reason for hiding this comment

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

useQuery를 쓰고 있는 페이지에선 내부에서 로딩,에러 상태를 관리하니 suspense 대상이 아니지만
UX를 고려해서 useSuspenseQuery가 필요한 곳이라면 Suspense를 쓸 수는 있을 것 같아요.

안전빵이라도 Suspense보단 에러 추적 목적으로 상위 에러바운더리로 전파하는 방식이 좋을 것 같아요.

Comment on lines +62 to +64
<Styled.PrimaryButton onClick={handleReset}>
다시 시도
</Styled.PrimaryButton>
Copy link
Member

Choose a reason for hiding this comment

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

handleReset이 Sentry에서 전달해주는 resetError이라는 함수군요
ErrorBoundary 아래 subtree만 다시 렌더링해야 해서 다시 시도 버튼이 필요한 구조군요.
별도 새로고침이 아니라 이렇게 처리할수 있네요
배워갑니다

Copy link
Member Author

Choose a reason for hiding this comment

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

네 Sentry 에러바운더리 내에서 에러 상태를 초기화하는 방식입니다 !

@seongwon030 seongwon030 merged commit 0f05285 into develop-fe Feb 14, 2026
4 checks passed
@seongwon030 seongwon030 deleted the feature/#1193-error-Boundary-sentry-integration-MOA-646 branch February 14, 2026 15:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FE Frontend ✨ Feature 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] MOA-646 Sentry 통합 에러바운더리 및 전역 에러 핸들링 설정

3 participants