Designing Error Boundaries with Claude Code: From Frontend to API
Designing Error Boundaries: Claude Code 활용. From Frontend to API. 실용적인 코드 예시를 포함합니다.
에러バウンダリとは
에러バウンダリは、애플리케이션の一部で에러が発生しても全体がクラッシュしないようにする防御的な설계パターンです。Claude Code를 활용하면 프론트엔드と백엔드の両方で一貫した에러処理を설계할 수 있습니다。
React Error Boundary
import { Component, ErrorInfo, ReactNode } from "react";
interface ErrorBoundaryProps {
children: ReactNode;
fallback?: ReactNode;
onError?: (error: Error, errorInfo: ErrorInfo) => void;
}
interface ErrorBoundaryState {
hasError: boolean;
error: Error | null;
}
class ErrorBoundary extends Component<
ErrorBoundaryProps,
ErrorBoundaryState
> {
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error("Error caught by boundary:", error, errorInfo);
this.props.onError?.(error, errorInfo);
// Send to error monitoring service
reportError(error, {
componentStack: errorInfo.componentStack,
});
}
render() {
if (this.state.hasError) {
return (
this.props.fallback || (
<div className="error-fallback">
<h2>エラーが発生しました</h2>
<p>{this.state.error?.message}</p>
<button onClick={() => this.setState({ hasError: false, error: null })}>
再試行
</button>
</div>
)
);
}
return this.props.children;
}
}
함수컴포넌트向けフック
import { useCallback, useState } from "react";
function useErrorHandler() {
const [error, setError] = useState<Error | null>(null);
if (error) {
throw error; // 親のError Boundaryでキャッチ
}
const handleError = useCallback((err: unknown) => {
if (err instanceof Error) {
setError(err);
} else {
setError(new Error(String(err)));
}
}, []);
const withErrorHandling = useCallback(
<T,>(fn: () => Promise<T>) => {
return async () => {
try {
return await fn();
} catch (err) {
handleError(err);
return undefined;
}
};
},
[handleError]
);
return { handleError, withErrorHandling };
}
API 에러응답の標準化
// 에러コード定義
enum ErrorCode {
VALIDATION_ERROR = "VALIDATION_ERROR",
NOT_FOUND = "NOT_FOUND",
UNAUTHORIZED = "UNAUTHORIZED",
FORBIDDEN = "FORBIDDEN",
CONFLICT = "CONFLICT",
INTERNAL_ERROR = "INTERNAL_ERROR",
RATE_LIMITED = "RATE_LIMITED",
}
interface ApiError {
code: ErrorCode;
message: string;
details?: Record<string, unknown>;
requestId: string;
timestamp: string;
}
class AppError extends Error {
constructor(
public code: ErrorCode,
message: string,
public statusCode: number,
public details?: Record<string, unknown>
) {
super(message);
this.name = "AppError";
}
static notFound(resource: string) {
return new AppError(
ErrorCode.NOT_FOUND,
`${resource} not found`,
404
);
}
static validation(details: Record<string, string>) {
return new AppError(
ErrorCode.VALIDATION_ERROR,
"Validation failed",
400,
details
);
}
static unauthorized(message = "Authentication required") {
return new AppError(ErrorCode.UNAUTHORIZED, message, 401);
}
}
グローバル에러핸들러ー
import { v4 as uuidv4 } from "uuid";
function globalErrorHandler(
err: Error,
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
const requestId = uuidv4();
if (err instanceof AppError) {
// 業務에러
return res.status(err.statusCode).json({
code: err.code,
message: err.message,
details: err.details,
requestId,
timestamp: new Date().toISOString(),
});
}
// 予期しない에러
console.error(`[${requestId}] Unexpected error:`, err);
res.status(500).json({
code: ErrorCode.INTERNAL_ERROR,
message: "An unexpected error occurred",
requestId,
timestamp: new Date().toISOString(),
});
}
// 등록順序が重要:ルーターの後に配置
app.use(globalErrorHandler);
비동기에러のキャッチ
// asyncHandler ラッパー
function asyncHandler(
fn: (
req: express.Request,
res: express.Response,
next: express.NextFunction
) => Promise<void>
) {
return (
req: express.Request,
res: express.Response,
next: express.NextFunction
) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
}
// Usage example
router.get(
"/users/:id",
asyncHandler(async (req, res) => {
const user = await prisma.user.findUnique({
where: { id: req.params.id },
});
if (!user) {
throw AppError.notFound("User");
}
res.json({ data: user });
})
);
階層的에러バウンダリ
React側では複数のError Boundaryを階層的に配置します。에러処理の설계をClaude Code에依頼する際の参考にして주세요。プロンプトの書き方は효과적인プロンプト5つのTips、コード品質の改善には리팩터링자동화も役立ちます。
function App() {
return (
<ErrorBoundary fallback={<FullPageError />}>
<Header />
<ErrorBoundary fallback={<SidebarFallback />}>
<Sidebar />
</ErrorBoundary>
<ErrorBoundary fallback={<ContentFallback />}>
<MainContent />
</ErrorBoundary>
</ErrorBoundary>
);
}
에러 핸들링の설계原則에 대해서는MDN Web Docs: Error handlingが参考になります。Claude Code의 상세 정보는공식 문서를 확인하세요.
정리
에러バウンダリは사용자体験を損なわないための重要な설계パターンです。Claude Code를 활용하면 프론트엔드からAPIまで一貫した에러処理を효율적으로구현할 수 있습니다。
#Claude Code
#error handling
#React
#API design
#TypeScript
Related Posts
Advanced
Advanced
Claude Code MCP Server 설정 및 실전 활용 가이드
Claude Code의 MCP Server 기능을 종합적으로 소개합니다. 외부 도구 연결, 서버 설정, 실전 통합 사례까지 한 번에 알아보세요.
Advanced
Advanced
Claude Code Hooks 완전 정복: 자동 포맷팅, 자동 테스트 설정법
Claude Code Hooks로 자동 포맷팅과 자동 테스트를 설정하는 방법을 알아봅니다. 실용적인 설정 예제와 실전 활용 사례를 포함합니다.
Advanced
Advanced
CLAUDE.md 작성 완벽 가이드: 프로젝트 설정 베스트 프랙티스
효과적인 CLAUDE.md 파일 작성법을 상세히 소개합니다. 기술 스택, 컨벤션, 프로젝트 구조를 Claude Code에 전달하여 출력 품질을 극대화하세요.