Error Boundary
에러바운더리가 무엇이고 어떻게 사용했나요?
Error Boundary는 자바스크립트 에러가 전체 앱을 중단시키는 것을 방지하는 React 컴포넌트입니다. 자식 컴포넌트 트리의 어디서든 에러를 잡아내고, 에러를 기록하며, 대신 fallback UI를 보여줍니다.
Error Boundary의 필요성
React 16 이전에는 컴포넌트 내부의 JavaScript 에러가 React의 내부 상태를 손상시키고 다음 렌더링에서 암호화된 에러를 발생시켰습니다. Error Boundary는 이러한 문제를 해결합니다.
클래스 컴포넌트로 만드는 Error Boundary
Error Boundary는 현재 클래스 컴포넌트에서만 만들 수 있습니다:
import React, { Component, ErrorInfo, ReactNode } from "react";
interface Props {
children: ReactNode;
fallback?: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
}
class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
// 에러가 발생했을 때 상태를 업데이트
static getDerivedStateFromError(error: Error): State {
return {
hasError: true,
error,
};
}
// 에러 정보를 로깅
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error("Error Boundary가 에러를 잡았습니다:", error, errorInfo);
// 에러 리포팅 서비스로 전송
// logErrorToService(error, errorInfo);
}
render() {
if (this.state.hasError) {
// 커스텀 fallback UI 또는 기본 UI
return (
this.props.fallback || (
<div className="error-boundary">
<h2>문제가 발생했습니다</h2>
<details style={{ whiteSpace: "pre-wrap" }}>
<summary>에러 세부사항</summary>
{this.state.error && this.state.error.toString()}
</details>
<button onClick={() => this.setState({ hasError: false })}>
다시 시도
</button>
</div>
)
);
}
return this.props.children;
}
}
export default ErrorBoundary;함수 컴포넌트에서 사용하기
함수 컴포넌트에서는 react-error-boundary 라이브러리를 사용할 수 있습니다:
npm install react-error-boundaryimport { ErrorBoundary } from "react-error-boundary";
function ErrorFallback({ error, resetErrorBoundary }: any) {
return (
<div role="alert" className="error-fallback">
<h2>문제가 발생했습니다:</h2>
<pre style={{ color: "red" }}>{error.message}</pre>
<button onClick={resetErrorBoundary}>다시 시도</button>
</div>
);
}
function MyApp() {
return (
<ErrorBoundary
FallbackComponent={ErrorFallback}
onError={(error, errorInfo) => {
// 에러 로깅
console.error("Error caught by boundary:", error, errorInfo);
}}
onReset={() => {
// 에러 상태 리셋 시 추가 로직
window.location.reload();
}}
>
<App />
</ErrorBoundary>
);
}Error Boundary가 잡지 못하는 에러들
- 이벤트 핸들러 내부의 에러
- 비동기 코드의 에러 (setTimeout, Promise 등)
- 서버 사이드 렌더링 중의 에러
- Error Boundary 자체에서 발생하는 에러
실제 사용 예시들
컴포넌트 레벨 Error Boundary
function ComponentErrorFallback({ error, resetErrorBoundary }: any) {
return (
<div className="rounded border border-red-300 bg-red-50 p-4">
<h3 className="font-semibold text-red-800">컴포넌트 오류</h3>
<p className="mt-1 text-sm text-red-600">이 부분을 불러올 수 없습니다.</p>
<button
onClick={resetErrorBoundary}
className="mt-2 text-sm text-red-600 underline"
>
다시 시도
</button>
</div>
);
}
export function ComponentErrorBoundary({
children,
}: {
children: React.ReactNode;
}) {
return (
<ErrorBoundary FallbackComponent={ComponentErrorFallback}>
{children}
</ErrorBoundary>
);
}
// 실제 앱에서의 사용
function App() {
return (
<div className="app">
<header>
<ComponentErrorBoundary>
<Navigation />
</ComponentErrorBoundary>
</header>
<main>
<ComponentErrorBoundary>
<UserProfile />
</ComponentErrorBoundary>
<ComponentErrorBoundary>
<PostsList />
</ComponentErrorBoundary>
</main>
</div>
);
}Best Practices
- 적절한 레벨에 배치: 페이지 레벨과 컴포넌트 레벨에 각각 적절한 Error Boundary 설치
- 사용자 친화적 메시지: 기술적 에러 메시지 대신 사용자가 이해할 수 있는 설명 제공
- 에러 로깅: 프로덕션에서는 에러를 추적할 수 있도록 로깅 시스템과 연동
- 복구 메커니즘: 사용자가 쉽게 복구할 수 있는 방법 제공
Edit on GitHub
Last updated on