
WhereYouAd 프로젝트가 드디어...!!! 끝이 보인다...!!ㅠㅠㅠㅠ
발표준비하고, 최종 마무리랑 행정 정리하면서 바쁜 하루를 보내다보니... 이 내용정리 velog를 올려야지!! 하다가 못올렸는데요ㅠㅠ 드디어!! 함 해봅니다!!
일단 오늘 정리 내용은 ErrorBoundary입니다!
에러바운더리 처음에 이해 어려워서 정리해봅니다!
도입은 다른 팀원이 담당해주었고, 저는 도입된걸 담당 페이지들에 적용하는 방향으로 진행했는데, 이건 다른 프로젝트 진행하게 될떄도 유용하게 활용될 것같아서!
개념과 API에러와의 차이점, 그리고 도입 방법 까지 한번 정리해보겠다!
React에서 자식 컴포넌트가 랜더링 중에 JS에러가 나오면, 원래 페이지 전체가 깨질 수 있습니다.
사실 알고보면 전체보단 일부분만 에러가 난 거지만, 사용자가 보기에는 페이지 전체 오류로 보여집니다.
그래서, 페이지 전체 오류가 아니라, 이부분만 오류입니다! 라고 표현하기 위해서 Errorboundary가 사용됩니다.
그래서 사용자가 보기에는 화이트스크린이 뜨는 것이 아니고, 다시 시도해서 그 영역만 복구될 수 있도록.
즉, 일부분 UI 깨짐이 화이트스크린으로 번지지 않도록 막고, 오류 난 해당 영역만 복구하는 울타리 장치다!
그리고, 이벤트 핸들러, async, API 실패 는 안잡습니다.
isError)| 구분 | 처리 방식 | 예시 |
|---|---|---|
| 렌더 타임 JS crash | ErrorBoundary + Fallback | undefined.map(), 차트 내부 throw |
| API 실패 | 기존 isError 인라인 UI | 목록 불러오기 실패, 알림 설정 불러오기 실패 |
pnpm add react-error-boundary 로 라이브러리 설치후,
프로젝트에서는 라이브러리를 페이지마다 직접 import하는 것이 아니라,
공용 경로로 한번 감싸서 사용
src/components/common/error/ErrorBoundary.tsx 파일을 만들어서 공용 경로로 쓴다.
export type { FallbackProps} from "react-error-boundary";
export {
ErrorBoundary,
useErrorBoundary,
withErrorBoundary,
} from "react-error-boundary"
react-error-boundary 라이브러리를 re-export하는 파일이기 때문에 이 파일은 간단하게 작성된다!
자세한 사용법은 React ErrorBoundary 공식문서 에서 확인해볼수있다!
영역만 에러처리했다면! 그 부분에만 에러라고 나타낼 UI가 필요하겠죠?
Fallback UI는 에러났을때 그 자리를 대체할 화면입니다.
그래서, 우리 프로젝트에서보면 각각의 영역 성격에 따라 다르게 공용 Fallback으로 나눴습니다.
| 컴포넌트 | 용도 | 문구 느낌 |
|---|---|---|
AreaErrorFallback | 목록, 폼, 표, 설정 같은 일반 영역 | 이 영역을 불러오지 못했어요 |
ChartErrorFallback | 차트 | 차트를 불러오지 못했어요 |
MetricErrorFallback | KPI/지표 카드 | 지표를 불러오지 못했어요 |
포인트는 비슷합니다. resetErrorBoundary로 다시 연결시도합니다.
/src/components/common/error/AreaErrorFallback.tsx
import { memo } from "react";
import Button from "@/components/common/button/Button";
import type { FallbackProps } from "./ErrorBoundary";
import WarnCircleIcon from "@/assets/icon/common/warn-circle.svg?react";
const AreaErrorFallback = memo(function AreaErrorFallback({
resetErrorBoundary,
}: FallbackProps) {
return (
<div
role="alert"
className="flex min-h-40 w-full flex-1 flex-col items-center justify-center gap-4 rounded-2xl bg-surface-200/40 px-6 py-8 text-center"
>
<WarnCircleIcon
className="h-7 w-7 shrink-0 text-info-red"
aria-hidden="true"
/>
<div className="flex flex-col gap-1">
<p className="font-body1 text-text-title">
이 영역을 불러오지 못했어요
</p>
<p className="font-body2 text-text-muted">
일시적인 오류입니다. 잠시 후 다시 시도해 주세요.
</p>
</div>
<Button variant="outline" size="small" onClick={resetErrorBoundary}>
다시 시도
</Button>
</div>
);
});
export default AreaErrorFallback;
페이지마다 Fallback을 만드는것보다는 공용 Fallback을 재사용하는게 팀 패턴이었습니다. 코드 효율성을 높인거죠!
구성으로 보면 대략 이렇습니다.
react-error-boundary (라이브러리)
└─ components/common/error/
├─ ErrorBoundary.tsx ← re-export
├─ AreaErrorFallback.tsx
├─ ChartErrorFallback.tsx
└─ MetricErrorFallback.tsx
└─ pages / components 에서 감싸기
도입은 다른 팀원이 했고, 저는 제 담당페이지에서 충돌 날 수 있는 영역에 ErrorBoundary 감싸는 작업을 했습니다.
기본 형태는
import { ErrorBoundary } from "@/components/common/error/ErrorBoundary";
import AreaErrorFallback from "@/components/common/error/AreaErrorFallback";
<ErrorBoundary
FallbackComponents={AreaErrorFallback}
resetKeys={[workspaces]}
>
{renderWorkspaceContent()}
</ErrorBoundary>
여기서 이제 props 2개가 중요하다.
FallbackComponent: 에러가 났을때보여줄 UIresetKeys: 이 값이 바뀌면 fallback 상태를 자동으로 리셋해서, 자식 UI를 다시 그려봄. (이거는 없어도 동작함. 없으면 사용자가 다시시도 버튼으로 복구)목록, 폼 본문, 차트, 테이블 처럼 깨졌을때 페이지 전체 에러가 아닌 일부분 에러로 처리하고 싶을 때
isLoading UI : 로딩상태는 에러상태가 아닙니다!isError 인라인 UI : 이미 API 실패를 보여주는 정상흐름예를 들어 보여주면, 워크스페이스 목록은
{/* 검색 / 생성 버튼은 밖 */}
<div>...</div>
{/* 목록만 안 */}
<ErrorBoundary
FallbackComponent={AreaErrorFallback}
resetKeys={[workspaces]}
>
{renderWorkspaceContent()}
</ErrorBoundary>
{/* 생성 모달도 밖 */}
<Modal>...</Modal>
이렇게 구현해두었다.
Setting의 알림도 보면,
{isLoading || isNotificationSectionLoading ? (
<Skeleton />
) : isNotificationError ? (
<InlineApiError onRetry={refetch} /> // API isError → 기존 유지
) : (
<ErrorBoundary
FallbackComponent={AreaErrorFallback}
resetKeys={[draftOrgNotif, draftChannel, draftWorkspaceNotif]}
>
<NotificationSection ... />
</ErrorBoundary>
)}
이렇게 격리범위를 정해놓았다.
그래서
즉, API 실패 UI를 ErrorBoundary로 대체하는 것이 아니라, 성공했을 때 그리는 UI가 렌더 중 깨지는 경우를 막는 것!
우리 프로젝트에서 각각의 Fallback을 어떤식으로 고르는지 보면
AreaErrorFallbackChartErrorFallbackMetricErrorFallback내 담당 파트 워크스페이스/멤버/알림/타임라인/설정에 적용해두었고, API isError와 loadingUI는 따로 건드리지 않았습니다!
그러면 이제 다음 다른 프로젝트에서 도입할 수 있지?
정리해보면,
1.
pnpm add react-error-boundary라이브러리 설치
2. 공용ErrorBoundaryre-export 파일 만들기 (공용 경로)
3. Fallback UI 만들기 (에러난 영역 대체할 UI)
4. 충돌 가능한 영역만<ErrorBoundary>로 감싸기
5. APIisErrorUI와 역할 분리 유지하기
도입은 이렇게 한번만 해두고, 그뒤로는 페이지마다 감싸는 과정만 반복하면 된다!
ErrorBoundary는 랜더링 중에 JS 에러가 페이지 전체를 죽이지 않게 막는 영역 단위의 안정망이다.
API 실패인 isError를 대체하는 도구가 아니라, 이미 그려진 UI가 예상치 못하게 깨질때를 대비해놓는 장치다.
그래서 나중에, 개인프로젝트나 다른 프로젝트에서도 바로 적용해서 사용할 수 있도록 정리했다! 이제 완전 정복!