에러처리에 관해서 모든 api call에 에러 처리 로직을 넣고, 클라이언트 컴포넌트에서도 별도로 404 페이지로 이동시키면서 비효율적이라는 생각이 들었다. 그래서 사수분과 이야기를 하다 React ErrorBoundary 라는 기술을 알게되었다.
에러 경계는 하위 컴포넌트 트리의 어디에서든 자바스크립트 에러를 기록하며 깨진 컴포넌트 트리 대신 폴백 UI를 보여주는 React 컴포넌트입니다. 에러 경계는 렌더링 도중 생명주기 메서드 및 그 아래에 있는 전체 트리에서 에러를 잡아냅니다.
다음과 같은 에러는 처리하지 않는다.
- 이벤트 핸들러
- 비동기적 코드 (예: setTimeout 혹은 requestAnimationFrame 콜백)
- 서버 사이드 렌더링
- 자식에서가 아닌 ErrorBoundary 자체에서 발생하는 에러
공식 문서 예제 코드 중 일부
- export 만 추가.
- import React from "react" 추가
- fallbackImage 와 text 추가.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// 다음 렌더링에서 폴백 UI가 보이도록 Error상태 업데이트.
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// 특정 서비스에 에러를 기록할 수도 있다.
logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
// 폴백 UI를 커스텀하여 렌더링할 수 있다.
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
그런 다음엔 아래와 같이 일반 컴포넌트로 사용할 수 있다.
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
위 내용은 클라이언트 에러에서만 해결이 가능하기때문에 서버 fetch 중 에러 대응이 필요했는데 이 부분은 error.tsx 를 만들어서 대응하였다.
// app/members/error.tsx
"use client";
export default function Error({ error }: { error: Error }) {
return (
<div>
<h2>앗! 에러가 발생했어요 😵</h2>
<p>{error.message}</p>
</div>
);
}
export default async function Page() {
const data = await fetchSomeDangerousThing();
if (!data) {
throw new Error("데이터 없음!"); // ✅ 자동으로 error.tsx로 감
}
return <SomeComponent data={data} />;

비동기에서는 error.tsx 로 가지않기때문에 catch에서 UI 처리를 해주어야한다.