用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/puk0806/gugbab-claude --skill error-handling命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
DDD(Domain-Driven Design) 아키텍처 핵심 패턴 - 유비쿼터스 언어, 서브도메인, 바운디드 컨텍스트, Aggregate, Entity/VO, 도메인 서비스/이벤트, 레이어드 아키텍처
대규모 React/Next.js 프로젝트를 layer-first(types/·utils/·hooks/·api/·components/ 밑에 도메인이 반복되는 구조)에서 domain-first(feature/도메인 우선) 구조로 전환하는 설계 기준과 절차. Feature-Sliced Design 2.1 정본(layers 6종·slices·segments·import 규칙·@x 크로스임포트·public API), FSD를 쓰지 않는 경량 대안(features + shared 2~3계층 + ESLint import/no-restricted-paths), Next.js App Router 공존 전략(route group `()`·private folder `_`·colocation), Turborepo/Nx 모노레포에서 폴더↔패키지 승격 기준, colocation과 배럴 파일 성능 트레이드오프, 도메인 경계 역추출(import 그래프·change coupling·용어 클러스터), 전환 실패 패턴(shared 비대화·entities 남용·순환 의존·도메인=라우트 착각·조기 추상화). 도메인 개념 자체(바운디드 컨텍스트·유비쿼터스 언어)는 `architecture/ddd` 스킬을 참조한다.
소스 파일 수천 개 규모 프론트엔드 코드베이스를 멈추지 않고 점진 재구조화하는 실행 전략 - Strangler Fig / Branch by Abstraction / Parallel Change, ts-morph·jscodeshift codemod, PR 분할·검증 게이트·되돌리기, 테스트 없는 코드의 안전망, 작업 순서 설계와 위반 수 기반 진행 추적
基于 SOC 职业分类
正在显示 SKILL.md
| name | error-handling |
| description | React 19 Error Boundary, Suspense 조합, TanStack Query 에러 처리, 에러 유형별 전략 |
소스: https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary | https://react.dev/reference/react-dom/client/createRoot | https://github.com/bvaughn/react-error-boundary 검증일: 2026-04-01
| 에러 유형 | 발생 위치 | 처리 방법 | Error Boundary |
|---|---|---|---|
| 렌더 에러 | 컴포넌트 렌더링 중 | Error Boundary | 필수 |
| API 에러 | 데이터 페칭 | TanStack Query error 상태 or throwOnError | 선택 |
| 폼 에러 | 이벤트 핸들러, 제출 | useState, useActionState | 불필요 |
Error Boundary는 이벤트 핸들러, 비동기 코드, SSR 에러를 잡지 못한다.
React 19에서도 Error Boundary는 클래스 컴포넌트로만 직접 작성 가능. 실제로는 react-error-boundary 라이브러리를 사용한다 (React 19 공식 지원: peerDependencies: "^18.0.0 || ^19.0.0").
import { ErrorBoundary } from 'react-error-boundary'
function App() {
return (
<ErrorBoundary
fallbackRender={({ error, resetErrorBoundary }) => (
<div>
<p>오류: {error.message}</p>
<button onClick={resetErrorBoundary}>다시 시도</button>
</div>
)}
onError={(error, info) => {
console.error(error, info.componentStack)
}}
>
<Page />
</ErrorBoundary>
)
}
<ErrorBoundary fallback={<p>에러가 발생했습니다</p>}>
<Suspense fallback={<p>로딩 중...</p>}>
<AsyncComponent />
</Suspense>
</ErrorBoundary>
중첩 구조 (Progressive Loading):
<ErrorBoundary fallback={<PageError />}>
<Suspense fallback={<PageSkeleton />}>
<ErrorBoundary fallback={<SectionError />}>
<Suspense fallback={<SectionSkeleton />}>
<Section />
</Suspense>
</ErrorBoundary>
</Suspense>
</ErrorBoundary>
React 19에서 createRoot에 에러 콜백이 추가됐다. 컴포넌트 레벨이 아닌 전역 에러 모니터링용이다.
import { createRoot } from 'react-dom/client'
const root = createRoot(container, {
onCaughtError: (error, errorInfo) => {
// Error Boundary가 잡은 에러
reportToSentry(error, errorInfo.componentStack)
},
onUncaughtError: (error, errorInfo) => {
// Error Boundary 없이 throw된 에러
reportToSentry(error, errorInfo.componentStack)
},
onRecoverableError: (error, errorInfo) => {
// React가 자동 복구 가능한 에러 (hydration 불일치 등)
console.warn(error, errorInfo.componentStack)
},
})
const { data, error, isError } = useQuery({
queryKey: ['user', id],
queryFn: fetchUser,
})
// 인라인 처리
if (isError) return <p>에러: {error.message}</p>
import { QueryErrorResetBoundary } from '@tanstack/react-query'
import { ErrorBoundary } from 'react-error-boundary'
function App() {
return (
<QueryErrorResetBoundary>
{({ reset }) => (
<ErrorBoundary
onReset={reset}
fallbackRender={({ resetErrorBoundary }) => (
<div>
<p>데이터 로드 실패</p>
<button onClick={resetErrorBoundary}>재시도</button>
</div>
)}
>
<DataComponent />
</ErrorBoundary>
)}
</QueryErrorResetBoundary>
)
}
useQuery({
queryKey: ['critical'],
queryFn: fetchCriticalData,
// 치명적 에러만 Error Boundary로 위임
throwOnError: (error) => error.status >= 500,
})
onError콜백은 TanStack Query v5에서 제거됐다. 에러 로깅은QueryCache의onError를 사용한다.
const queryClient = new QueryClient({
queryCache: new QueryCache({
onError: (error) => reportToSentry(error),
}),
})
import { useActionState } from 'react'
async function submitAction(prevState: any, formData: FormData) {
const result = await submitForm(formData)
if (!result.ok) {
return { error: result.message }
}
return { error: null }
}
function Form() {
const [state, action, isPending] = useActionState(submitAction, { error: null })
return (
<form action={action}>
{state.error && <p>{state.error}</p>}
<button disabled={isPending}>제출</button>
</form>
)
}