Skip to content

[Feature/#274] 에러 처리 안전망 구축 (에러 페이지 + Error Boundary) - #280

Merged
Seojegyeong merged 9 commits into
developfrom
feature/#274
Jul 4, 2026
Merged

[Feature/#274] 에러 처리 안전망 구축 (에러 페이지 + Error Boundary)#280
Seojegyeong merged 9 commits into
developfrom
feature/#274

Conversation

@Seojegyeong

@Seojegyeong Seojegyeong commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

🚨 관련 이슈

#274

✨ 변경사항

  • 🐞 BugFix Something isn't working
  • 💻 CrossBrowsing Browser compatibility
  • 🌏 Deploy Deploy
  • 🎨 Design Markup & styling
  • 📃 Docs Documentation writing and editing (README.md, etc.)
  • ✨ Feature Feature
  • 🔨 Refactor Code refactoring
  • ⚙️ Setting Development environment setup
  • ✅ Test Test related (storybook, jest, etc.)

✏️ 작업 내용

1. 전역 에러 페이지

  • Error.tsx 재작성: useRouteError() 기반으로 404 / 일반 에러 분기, 재시도 · 홈 이동 액션 추가
  • NotFound.tsx 신규 생성: 404 전용 페이지, 이전 페이지 · 홈 이동 액션
  • Router.tsx: path: "*" 라우트 추가, errorElement 업데이트

2. 컴포넌트 레벨 Error Boundary

  • react-error-boundary 설치 및 ErrorBoundary.tsx re-export 래퍼 생성
  • MetricErrorFallback: KPI 카드 그리드 자리 대체 fallback UI
  • ChartErrorFallback: Card 내부 차트 콘텐츠 자리 대체 fallback UI
  • OverviewKpiSection: KPI 그리드 · 트래픽 차트 각각 내부에서 ErrorBoundary 래핑
  • OverviewBudgetSection: "예산 소진 현황" 카드 헤더는 유지, 차트 콘텐츠 영역에만 ErrorBoundary 적용
  • OverviewDashboard: 플랫폼 비교 · AI 요약 섹션 ErrorBoundary 래핑

3. 기타

  • MetricErrorFallback · ChartErrorFallback 스토리북 스토리 추가
  • ComingSoonPlaceholder: 임의값 클래스 → Tailwind 토큰으로 통일

스크린샷 참고

스크린샷 2026-07-03 오후 1 10 38 스크린샷 2026-07-03 오후 1 16 52

😅 미완성 작업

N/A

📢 논의 사항 및 참고 사항

  1. ErrorBoundary 배치 구조
OverviewDashboard
├── OverviewKpiSection
│   ├── ErrorBoundary → MetricErrorFallback  (KPI 카드 4개 영역)
│   └── Card "실시간 트래픽 변화"
│       └── ErrorBoundary → ChartErrorFallback  (차트 영역)
├── OverviewBudgetSection
│   └── Card "예산 소진 현황"  ← 에러 시에도 카드 헤더 유지
│       └── ErrorBoundary → ChartErrorFallback  (차트 영역)
├── ErrorBoundary → ChartErrorFallback  (플랫폼별 비교 섹션)
└── ErrorBoundary → ChartErrorFallback  (AI 요약 섹션)
  1. API 에러 vs 렌더 에러 구분
  • API 에러(isError) → 기존 인라인 에러 UI 유지 (변경 없음)
  • 렌더 타임 에러 (차트 라이브러리 crash 등) → ErrorBoundary가 캐치 → fallback UI + "다시 시도" 버튼으로 resetErrorBoundary 호출
  1. 각 페이지 ErrorBoundary 적용 필요
    이번 PR은 제 담당인 통합 대시보드(OverviewDashboard)에만 적용했습니다.
    src/components/common/error/ 하위에 공용 컴포넌트로 준비되어 있으니, 플랫폼 대시보드 · 광고 관리 등 각 페이지 담당자가 동일한 패턴으로 적용해 주세요.

💬 리뷰어 가이드 (P-Rules)
P1: 필수 반영 (Critical) - 버그 가능성, 컨벤션 위반. 해결 전 머지 불가.
P2: 적극 권장 (Recommended) - 더 나은 대안 제시. 가급적 반영 권장.
P3: 제안 (Suggestion) - 아이디어 공유. 반영 여부는 드라이버 자율.
P4: 단순 확인/칭찬 (Nit) - 사소한 오타, 칭찬 등 피드백.

Summary by CodeRabbit

  • New Features

    • 차트/지표 로딩 실패 시 재시도 가능한 전용 에러 안내 화면이 추가되었습니다.
    • 대시보드의 주요 섹션에 오류 경계를 적용해, 발생 시 해당 영역만 안내 UI로 전환됩니다.
    • 404 및 미매칭 주소에 상황별 Error/Not Found 페이지가 표시되도록 라우팅이 정비되었습니다.
  • Bug Fixes

    • 오류/로딩 상태 노출이 더 일관되게 동작하도록 개선했습니다.
  • Chores

    • 에러 화면 스토리북 문서화 및 애니메이션 유틸 추가가 반영되었습니다.
    • 일부 “Coming Soon” 영역 폭 설정이 조정되었습니다.

- Error.tsx: useRouteError 기반으로 개선, 404/일반 에러 분기 및 재시도·홈 이동 액션 추가
- NotFound.tsx: 404 전용 페이지 신규 생성 (이전 페이지·홈 이동 액션)
- Router: path "*" 라우트 추가, errorElement 업데이트
- react-error-boundary 설치 및 ErrorBoundary 컴포넌트 추가
- MetricErrorFallback / ChartErrorFallback fallback UI 제작
- OverviewDashboard 각 섹션을 ErrorBoundary로 래핑하여 위젯 에러 격리
- Error, NotFound: h-full min-h-[70vh] → min-h-screen으로 교체하여 완전 중앙 정렬
- ComingSoonPlaceholder: 임의값 클래스를 Tailwind 토큰으로 통일
- KPI 섹션: ErrorBoundary를 카드 그리드·트래픽 차트 내부로 이동
- Budget 섹션: 예산 카드 헤더 유지, 차트 콘텐츠 영역에만 ErrorBoundary 적용
- OverviewDashboard에서 KPI·Budget 바깥 ErrorBoundary 제거
- ChartErrorFallback: flex-1 추가 및 배경 투명도 조정
- MetricErrorFallback: min-h-28 추가
@Seojegyeong Seojegyeong linked an issue Jul 3, 2026 that may be closed by this pull request
10 tasks
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Seojegyeong, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fc5a2064-934d-4d8e-b89b-f0ca90c64f37

📥 Commits

Reviewing files that changed from the base of the PR and between b1b3328 and b96ad33.

📒 Files selected for processing (1)
  • src/pages/dashboard/overview/OverviewDashboard.tsx
📝 Walkthrough

Walkthrough

에러 레이아웃, 차트/지표 폴백, 라우팅 오류 페이지를 추가하고, Overview 대시보드의 여러 섹션을 ErrorBoundary로 감싸도록 바뀌었습니다. 라우터는 새 ErrorPage와 NotFound를 연결합니다.

Changes

에러 처리 및 폴백 UI

Layer / File(s) Summary
공용 에러 레이아웃과 애니메이션
src/components/common/error/ErrorLayout.tsx, src/lib/animation.ts
에러 상태를 보여주는 공용 레이아웃과 motion variants가 추가되었습니다.
차트·지표 폴백 컴포넌트
src/components/common/error/ErrorBoundary.tsx, src/components/common/error/ChartErrorFallback.tsx, src/components/common/error/ChartErrorFallback.stories.tsx, src/components/common/error/MetricErrorFallback.tsx, src/components/common/error/MetricErrorFallback.stories.tsx
react-error-boundary 재-export와 차트/지표 오류용 fallback UI, Storybook 스토리가 추가되었습니다.
라우팅 오류와 404 페이지
src/pages/common/Error.tsx, src/pages/common/NotFound.tsx, src/routes/Router.tsx
라우팅 오류용 ErrorPage와 404용 NotFound 페이지를 추가하고 라우터에 연결했습니다.
대시보드 에러 경계 적용
src/pages/dashboard/overview/OverviewDashboard.tsx, src/pages/dashboard/overview/sections/OverviewBudgetSection.tsx, src/pages/dashboard/overview/sections/OverviewKpiSection.tsx
Overview 대시보드의 KPI, 차트, 예산, 플랫폼, AI 요약 렌더링을 ErrorBoundary로 감싸 fallback을 연결했습니다.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Router
  participant ErrorPage
  participant NotFound
  participant ErrorLayout
  Router->>ErrorPage: errorElement 렌더
  ErrorPage->>ErrorLayout: 제목/설명/액션 전달
  Router->>NotFound: path="*" 매칭
  NotFound->>ErrorLayout: 404 문구와 이동 버튼 전달
Loading
sequenceDiagram
  participant OverviewDashboard
  participant ErrorBoundary
  participant ChartErrorFallback
  participant MetricErrorFallback
  OverviewDashboard->>ErrorBoundary: 섹션 렌더링 래핑
  ErrorBoundary->>ChartErrorFallback: 차트 오류 fallback 표시
  ErrorBoundary->>MetricErrorFallback: KPI 오류 fallback 표시
Loading

Possibly related issues

Possibly related PRs

Suggested labels: 🔨 Refactor

Suggested reviewers: jjjsun, YermIm

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 에러 페이지와 Error Boundary 구축이라는 핵심 변경을 간결하게 잘 요약하고 있습니다.
Description check ✅ Passed 필수 섹션인 관련 이슈, 변경사항, 작업 내용, 미완성 작업, 논의 사항이 모두 포함되어 있어 템플릿을 충분히 따릅니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#274

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.

@Seojegyeong Seojegyeong changed the title [Feature/#274] 에러 처리 안전망 구축 [Feature/#274] 에러 처리 안전망 구축 (에러 페이지 + Error Boundary) Jul 3, 2026
@Seojegyeong Seojegyeong self-assigned this Jul 3, 2026
@Seojegyeong Seojegyeong added the ✨ Feature 기능 개발 label Jul 3, 2026
@Seojegyeong
Seojegyeong requested review from YermIm and jjjsun July 3, 2026 04:23
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

📚 Storybook 배포 완료

항목 링크
📖 Storybook https://69a147b60a56365d9e2185ef-wclkxwvzbc.chromatic.com/
🔍 Chromatic https://www.chromatic.com/build?appId=69a147b60a56365d9e2185ef&number=386

@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: 3

🧹 Nitpick comments (7)
src/components/common/error/ChartErrorFallback.tsx (1)

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

ChartErrorFallback / MetricErrorFallback 구조 중복

두 컴포넌트가 아이콘 + 제목/설명 + 재시도 버튼이라는 동일한 레이아웃을 거의 그대로 복사해서 쓰고 있습니다(컨테이너 클래스, 아이콘 크기, 텍스트만 다름). 앞으로 폴백 UI 종류가 늘어날 걸 감안하면 공통 BaseErrorFallback 같은 컴포넌트로 추출해서 title/description/icon size 같은 props만 바꿔 쓰는 게 중복 관리 부담을 줄일 수 있습니다.

♻️ 예시 리팩터 방향
// src/components/common/error/BaseErrorFallback.tsx
type Props = FallbackProps & {
  title: string;
  description: string;
  containerClassName: string;
  iconClassName: string;
};

export const BaseErrorFallback = memo(function BaseErrorFallback({
  resetErrorBoundary,
  title,
  description,
  containerClassName,
  iconClassName,
}: Props) {
  return (
    <div role="alert" className={containerClassName}>
      <WarnCircleIcon className={iconClassName} aria-hidden="true" />
      <div className="flex flex-col gap-1">
        <p className="font-body1 text-text-title">{title}</p>
        <p className="font-body2 text-text-muted">{description}</p>
      </div>
      <Button variant="outline" size="small" onClick={resetErrorBoundary}>
        다시 시도
      </Button>
    </div>
  );
});
🤖 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/components/common/error/ChartErrorFallback.tsx` around lines 9 - 32,
ChartErrorFallback and MetricErrorFallback duplicate the same error-fallback
layout, so extract the shared UI into a reusable BaseErrorFallback component and
pass only the varying pieces as props. Move the common container,
WarnCircleIcon, title/description block, and resetErrorBoundary button logic
into BaseErrorFallback, then update ChartErrorFallback to render it with its
chart-specific text and classes. Keep the existing memo/FallbackProps pattern in
the new shared component so both fallbacks can reuse it cleanly.
src/pages/dashboard/overview/OverviewDashboard.tsx (1)

69-84: 🧹 Nitpick | 🔵 Trivial

참고: 캐치된 에러 로깅(onError)도 고려해보세요.

지금은 FallbackComponent만 지정되어 있어 렌더 에러가 콘솔 외에는 어디에도 기록되지 않습니다. 대시보드 전반에 걸쳐 ErrorBoundary를 도입하는 김에, onError로 모니터링 서비스에 로깅하는 방안을 함께 검토하면 운영 시 장애 파악에 도움이 될 것 같습니다.

🤖 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/pages/dashboard/overview/OverviewDashboard.tsx` around lines 69 - 84, The
OverviewDashboard ErrorBoundary setup only provides ChartErrorFallback, so
caught render errors are not being recorded anywhere beyond the default console
output. Update the ErrorBoundary usages around OverviewPlatformSection and
DashboardAiSummarySection to include an onError handler, and route the caught
error plus context into your monitoring/logging path. Use the existing
ErrorBoundary, ChartErrorFallback, OverviewPlatformSection, and
DashboardAiSummarySection symbols to place the logging alongside the fallback
configuration.
src/pages/dashboard/overview/sections/OverviewKpiSection.tsx (1)

38-58: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

KPI ErrorBoundary에 resetKeys를 추가해 자동 복구를 열어두면 좋겠습니다.
kpis가 새로 들어오면 경계가 함께 리셋되도록 resetKeys={[kpis]}를 붙여두면, 데이터 갱신 뒤에도 렌더 에러 상태가 덜 오래 남습니다. 지금도 수동 재시도는 가능하지만, 자동 복구까지 기대한다면 이쪽이 더 안전합니다.

🤖 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/pages/dashboard/overview/sections/OverviewKpiSection.tsx` around lines 38
- 58, The KPI ErrorBoundary currently has no automatic reset when the underlying
data changes, so a previous render error can linger after new KPI data arrives.
Update the ErrorBoundary in OverviewKpiSection to include resetKeys tied to the
kpis value so it reinitializes when fresh data is loaded. Keep the change local
to the ErrorBoundary usage around MetricErrorFallback and the KPI rendering
block.

Source: Path instructions

src/pages/common/Error.tsx (3)

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

role="alert"가 전체 페이지 콘텐츠(버튼 포함)에 적용됨.

role="alert"는 일반적으로 짧은 알림용 live region에 쓰이며, 스크린리더가 즉시 전체 내용을 읽어버립니다. 헤딩·설명·버튼을 포함한 풀페이지 콘텐츠 전체에 적용하면 오히려 탐색성이 떨어질 수 있습니다. role="status" 또는 role 제거를 고려해보세요.

🤖 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/pages/common/Error.tsx` around lines 47 - 48, The Error page wrapper in
Error should not use role="alert" for the full content block because it forces
assistive tech to announce the entire page contents at once. Update the
container in Error to either remove the role entirely or change it to a less
intrusive live region like status, keeping the heading, description, and action
buttons accessible without an assertive alert.

Source: Path instructions


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

props 없는 컴포넌트에 memo 적용은 실효 없음.

ErrorPage는 라우터가 직접 렌더링하는 페이지 컴포넌트로 props를 받지 않으므로 memo의 리렌더 방지 효과가 없습니다. 사소한 부분이라 급하진 않지만 제거해도 무방합니다.

Also applies to: 105-105

🤖 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/pages/common/Error.tsx` at line 33, `ErrorPage`는 props를 받지 않는 라우터 페이지
컴포넌트라 `memo`의 최적화 효과가 없으므로, `ErrorPage` 선언에서 `memo` 래퍼를 제거하고 일반 함수 컴포넌트로 유지하세요.
함께 적용된 다른 `memo` 사용처도 같은 기준으로 확인해 불필요한 래핑을 정리하면 됩니다.

34-34: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

useRouteError 타입 캐스팅을 없애고 isRouteErrorResponse로 분기해 주세요.
src/pages/common/Error.tsxerrorElement에서 쓰이므로, 실제 형태를 숨기는 캐스팅보다 isRouteErrorResponse(error) && error.status === 404로 404를 판별하는 편이 더 명확합니다.

🤖 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/pages/common/Error.tsx` at line 34, Replace the `useRouteError` type cast
in `Error` with explicit route-error handling: use `isRouteErrorResponse(error)`
to detect route errors and branch on `error.status === 404` for the not-found
case. Update the `Error` component in `src/pages/common/Error.tsx` so it checks
the result of `useRouteError()` directly instead of hiding the shape behind a
cast.

Source: Path instructions

src/pages/common/NotFound.tsx (1)

76-83: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

navigate(-1)은 히스토리가 없는 경우 예측 불가능한 동작을 할 수 있어요.

사용자가 404 페이지에 딥링크로 직접 진입한 경우(북마크, 외부 링크 등) 앱 내 히스토리가 없어서 navigate(-1)이 앱 밖으로 이동하거나 아무 동작을 하지 않을 수 있습니다. 히스토리가 없을 때는 홈으로 폴백하는 게 안전합니다.

💡 제안 수정
+import { useNavigate } from "react-router-dom";
+import { useCallback } from "react";
...
+  const handleBack = useCallback(() => {
+    if (window.history.state?.idx > 0) {
+      navigate(-1);
+    } else {
+      navigate("/", { replace: true });
+    }
+  }, [navigate]);
...
-            onClick={() => navigate(-1)}
+            onClick={handleBack}
🤖 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/pages/common/NotFound.tsx` around lines 76 - 83, The NotFound page’s back
button currently uses navigate(-1), which can behave unpredictably when there is
no in-app history. Update the onClick handler in NotFound.tsx to check for a
usable history entry and fall back to the home route when the user arrived
directly via deep link or external link. Keep the change localized to the Button
handler that calls navigate so the “이전 페이지로” action is safe in all cases.
🤖 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/pages/common/Error.tsx`:
- Around line 1-31: `Error.tsx` is duplicating the same animation presets and
outer layout structure used in `NotFound.tsx`, so refactor the shared pieces
into a reusable abstraction. Extract `easeOut`, `containerVariants`, and
`itemVariants` into a common module (for example a shared error animation
preset) or move the repeated `motion.div` wrapper, icon, and text layout into an
`ErrorLayout` component. Then update `Error.tsx` to consume that shared code
instead of defining the same motion configuration inline.

In `@src/pages/dashboard/overview/OverviewDashboard.tsx`:
- Around line 69-77: The OverviewPlatformSection error boundary currently stays
stuck in ChartErrorFallback even after new rankings data arrives. Update the
ErrorBoundary around OverviewPlatformSection to include resetKeys tied to
roasRankingsData so it automatically resets when the data changes, allowing the
normal overview view to recover without relying only on the fallback’s retry
action.

In `@src/pages/dashboard/overview/sections/OverviewBudgetSection.tsx`:
- Around line 63-79: The OverviewBudgetSection ErrorBoundary is missing
resetKeys, so it may stay in the fallback state even after new budget data
arrives. Update the ErrorBoundary wrapper around ChartErrorFallback in
OverviewBudgetSection to pass resetKeys={[budget]} so the boundary automatically
resets when the budget prop changes and the chart can recover without manual
retry.

---

Nitpick comments:
In `@src/components/common/error/ChartErrorFallback.tsx`:
- Around line 9-32: ChartErrorFallback and MetricErrorFallback duplicate the
same error-fallback layout, so extract the shared UI into a reusable
BaseErrorFallback component and pass only the varying pieces as props. Move the
common container, WarnCircleIcon, title/description block, and
resetErrorBoundary button logic into BaseErrorFallback, then update
ChartErrorFallback to render it with its chart-specific text and classes. Keep
the existing memo/FallbackProps pattern in the new shared component so both
fallbacks can reuse it cleanly.

In `@src/pages/common/Error.tsx`:
- Around line 47-48: The Error page wrapper in Error should not use role="alert"
for the full content block because it forces assistive tech to announce the
entire page contents at once. Update the container in Error to either remove the
role entirely or change it to a less intrusive live region like status, keeping
the heading, description, and action buttons accessible without an assertive
alert.
- Line 33: `ErrorPage`는 props를 받지 않는 라우터 페이지 컴포넌트라 `memo`의 최적화 효과가 없으므로,
`ErrorPage` 선언에서 `memo` 래퍼를 제거하고 일반 함수 컴포넌트로 유지하세요. 함께 적용된 다른 `memo` 사용처도 같은
기준으로 확인해 불필요한 래핑을 정리하면 됩니다.
- Line 34: Replace the `useRouteError` type cast in `Error` with explicit
route-error handling: use `isRouteErrorResponse(error)` to detect route errors
and branch on `error.status === 404` for the not-found case. Update the `Error`
component in `src/pages/common/Error.tsx` so it checks the result of
`useRouteError()` directly instead of hiding the shape behind a cast.

In `@src/pages/common/NotFound.tsx`:
- Around line 76-83: The NotFound page’s back button currently uses
navigate(-1), which can behave unpredictably when there is no in-app history.
Update the onClick handler in NotFound.tsx to check for a usable history entry
and fall back to the home route when the user arrived directly via deep link or
external link. Keep the change localized to the Button handler that calls
navigate so the “이전 페이지로” action is safe in all cases.

In `@src/pages/dashboard/overview/OverviewDashboard.tsx`:
- Around line 69-84: The OverviewDashboard ErrorBoundary setup only provides
ChartErrorFallback, so caught render errors are not being recorded anywhere
beyond the default console output. Update the ErrorBoundary usages around
OverviewPlatformSection and DashboardAiSummarySection to include an onError
handler, and route the caught error plus context into your monitoring/logging
path. Use the existing ErrorBoundary, ChartErrorFallback,
OverviewPlatformSection, and DashboardAiSummarySection symbols to place the
logging alongside the fallback configuration.

In `@src/pages/dashboard/overview/sections/OverviewKpiSection.tsx`:
- Around line 38-58: The KPI ErrorBoundary currently has no automatic reset when
the underlying data changes, so a previous render error can linger after new KPI
data arrives. Update the ErrorBoundary in OverviewKpiSection to include
resetKeys tied to the kpis value so it reinitializes when fresh data is loaded.
Keep the change local to the ErrorBoundary usage around MetricErrorFallback and
the KPI rendering block.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d2e8ccbe-86f3-4bc0-bc51-63301e68ecb0

📥 Commits

Reviewing files that changed from the base of the PR and between 78b8cff and a1ec648.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json and included by none
  • package.json is excluded by none and included by none
📒 Files selected for processing (12)
  • src/components/common/ComingSoonPlaceholder.tsx
  • src/components/common/error/ChartErrorFallback.stories.tsx
  • src/components/common/error/ChartErrorFallback.tsx
  • src/components/common/error/ErrorBoundary.tsx
  • src/components/common/error/MetricErrorFallback.stories.tsx
  • src/components/common/error/MetricErrorFallback.tsx
  • src/pages/common/Error.tsx
  • src/pages/common/NotFound.tsx
  • src/pages/dashboard/overview/OverviewDashboard.tsx
  • src/pages/dashboard/overview/sections/OverviewBudgetSection.tsx
  • src/pages/dashboard/overview/sections/OverviewKpiSection.tsx
  • src/routes/Router.tsx

Comment thread src/pages/common/Error.tsx Outdated
Comment thread src/pages/dashboard/overview/OverviewDashboard.tsx Outdated
Comment thread src/pages/dashboard/overview/sections/OverviewBudgetSection.tsx Outdated

@jjjsun jjjsun left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P4: 확인했습니다!

- src/lib/animation.ts: easeOut, containerVariants, itemVariants 공용 프리셋 분리
- ErrorLayout 컴포넌트 신규 생성: NotFound·Error 페이지의 공통 motion wrapper 통합
- OverviewPlatformSection ErrorBoundary에 resetKeys={[roasRankingsData]} 추가
- OverviewBudgetSection ErrorBoundary에 resetKeys={[budget]} 추가
- ErrorLayout: role="alert" → "status"로 교체, memo 제거
- Error.tsx: memo 제거, useRouteError 타입 캐스트 → isRouteErrorResponse 분기
- NotFound.tsx: memo 제거, navigate(-1) → history 길이 확인 후 안전한 fallback 추가
- OverviewDashboard: 두 ErrorBoundary에 onError 핸들러 추가해 렌더 에러 로깅

@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.

🧹 Nitpick comments (3)
src/components/common/error/ErrorLayout.tsx (1)

17-25: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

에러 페이지 알림에 role="status"보다 role="alert"가 더 적합해 보여요.

role="status"는 polite 라이브 리전이라 스크린리더가 다른 작업을 마친 뒤 조용히 알려주는데, 에러 페이지는 사용자에게 즉시 인지시켜야 하는 상황이라 role="alert" (assertive)가 더 적절합니다. 접근성 관점에서 재검토 부탁드려요.

As per path instructions, src/** 리뷰 시 "접근성: 시맨틱 HTML, ARIA 속성 사용 확인" 항목을 확인하도록 되어 있습니다.

♻️ 제안
       <motion.div
         className="flex w-full max-w-105 flex-col items-center rounded-4xl bg-surface-100 px-8 py-12 text-center shadow-Soft transition-ui-smooth tablet:px-6"
-        role="status"
+        role="alert"
🤖 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/components/common/error/ErrorLayout.tsx` around lines 17 - 25, The error
page container in ErrorLayout currently uses role="status", but this should be
changed to an assertive alert role so the message is announced immediately.
Update the motion.div in ErrorLayout to use role="alert" and keep the rest of
the accessible structure intact.

Source: Path instructions

src/pages/common/NotFound.tsx (1)

21-26: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

window.history.length 체크만으론 "이전 페이지"가 실제로 우리 앱 내부인지 보장 못해요.

외부 사이트에서 링크 타고 들어와 브라우저 히스토리가 이미 쌓여있는 경우, navigate(-1)이 앱 밖으로 이동시킬 수 있습니다. 라우터 진입 시 location.state에 플래그를 심어 "앱 내부에서 왔는지"를 판단하는 방식이 더 안전할 수 있어요. 다만 엣지 케이스라 지금 당장 블로커는 아닙니다.

🤖 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/pages/common/NotFound.tsx` around lines 21 - 26, The back-navigation
logic in NotFound uses window.history.length, which can send users outside the
app; update the NotFound component’s onClick handler to rely on an app-internal
marker from location.state instead. Have the route entry set a flag indicating
the user came from inside the app, and in the navigate handler only call
navigate(-1) when that flag is present; otherwise fall back to navigate("/", {
replace: true }).
src/pages/common/Error.tsx (1)

11-14: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

라우트 에러가 어디에도 로깅되지 않아요.

useRouteError()로 받은 error 값을 콘솔이나 모니터링 툴로 전송하는 코드가 없습니다. 운영 환경에서 실제 어떤 에러가 발생해 이 페이지가 떴는지 추적하기 어려울 수 있어요. 최소한 console.error(error) 정도는 남겨두는 게 좋을 것 같습니다.

♻️ 제안
 export default function ErrorPage() {
   const error = useRouteError();
   const navigate = useNavigate();
 
   const is404 = isRouteErrorResponse(error) && error.status === 404;
+
+  if (!is404) {
+    console.error(error);
+  }
🤖 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/pages/common/Error.tsx` around lines 11 - 14, The Error page currently
reads the route error via useRouteError() but never logs it, so add error
reporting in the Error component by capturing the value returned from
useRouteError() and sending it to console.error or your monitoring hook before
the 404 handling logic. Keep the existing is404 and navigate flow intact, and
place the logging near the current error/navigate initialization so the actual
failure is visible when this page renders.
🤖 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.

Nitpick comments:
In `@src/components/common/error/ErrorLayout.tsx`:
- Around line 17-25: The error page container in ErrorLayout currently uses
role="status", but this should be changed to an assertive alert role so the
message is announced immediately. Update the motion.div in ErrorLayout to use
role="alert" and keep the rest of the accessible structure intact.

In `@src/pages/common/Error.tsx`:
- Around line 11-14: The Error page currently reads the route error via
useRouteError() but never logs it, so add error reporting in the Error component
by capturing the value returned from useRouteError() and sending it to
console.error or your monitoring hook before the 404 handling logic. Keep the
existing is404 and navigate flow intact, and place the logging near the current
error/navigate initialization so the actual failure is visible when this page
renders.

In `@src/pages/common/NotFound.tsx`:
- Around line 21-26: The back-navigation logic in NotFound uses
window.history.length, which can send users outside the app; update the NotFound
component’s onClick handler to rely on an app-internal marker from
location.state instead. Have the route entry set a flag indicating the user came
from inside the app, and in the navigate handler only call navigate(-1) when
that flag is present; otherwise fall back to navigate("/", { replace: true }).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 130ccb05-40fa-4c6c-9709-8e26769a4816

📥 Commits

Reviewing files that changed from the base of the PR and between a1ec648 and b1b3328.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml and included by none
📒 Files selected for processing (6)
  • src/components/common/error/ErrorLayout.tsx
  • src/lib/animation.ts
  • src/pages/common/Error.tsx
  • src/pages/common/NotFound.tsx
  • src/pages/dashboard/overview/OverviewDashboard.tsx
  • src/pages/dashboard/overview/sections/OverviewBudgetSection.tsx
✅ Files skipped from review due to trivial changes (1)
  • src/lib/animation.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/pages/dashboard/overview/sections/OverviewBudgetSection.tsx
  • src/pages/dashboard/overview/OverviewDashboard.tsx

@YermIm YermIm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P4: 확인했습니다!

@Seojegyeong
Seojegyeong merged commit 3ec0887 into develop Jul 4, 2026
3 checks passed
@Seojegyeong
Seojegyeong deleted the feature/#274 branch July 4, 2026 10:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ [Feature] 에러 처리 안전망 구축 (에러 페이지 + Error Boundary)

3 participants