댓글 (0)
댓글 (0)
TanStack Query의 Devtools에는 Trigger Error 버튼으로 쿼리의 에러 상태를 테스트할 수 있다. 그런데 이미 데이터가 캐시에 존재하는 상태에서 Trigger Error를 눌러도 에러가 발생하지 않아, Error Boundary가 작동되지 않는 현상을 확인했다.
이 글에서는 왜 이런 현상이 발생하는지 원인을 분석하고, 현재는 어떻게 해결됐는지에 대해서 정리한다.
useSuspenseQuery는 useQuery와는 다르게 데이터가 보장된 상태에서 컴포넌트를 렌더링한다. 그리고 로딩 상태와 에러 상태를 각각 <Suspense>와 <ErrorBoundary>가 처리하는 구조이다.
<ErrorBoundary fallback={<ErrorFallback />}>
<Suspense fallback={<Loading />}>
<MyComponent />
</Suspense>
</ErrorBoundary>
function MyComponent() {
const { data } = useSuspenseQuery({
queryKey: ["category"],
queryFn: fetchCategory,
});
return <div>{data.name}</div>;
}
이 구조에서 에러 처리를 테스트하려고 Devtools의 Trigger Error 버튼을 클릭하였지만, <ErrorBoundary>의 fallback UI가 전혀 나타나지 않았다.
useSuspenseQuery는 에러가 발생했을 때 throw를 통해 가장 가까운 Error Boundary로 에러를 전파한다. 그런데 여기에 핵심적인 조건이 있다.
공식 문서에 따르면, useSuspenseQuery의 throwOnError는 기본값이 (error, query) => typeof query.state.data === 'undefined'로 고정되어 있다.
throwOnError: (error, query) => typeof query.state.data === 'undefined'
캐시에 데이터가 있으면 에러를 throw하지 않고, 컴포넌트를 그대로 렌더링하는 것이 의도된 동작이다.
기존 Devtools Trigger Error 버튼의 동작 코드는 다음과 같았다.
activeQueryVal.setState({
status: 'error',
error,
fetchMeta: {
...activeQueryVal.state.fetchMeta,
__previousQueryOptions,
} as any,
})
쿼리가 한 번이라도 성공적으로 데이터를 받아온 상태라면, data에는 이전에 fetch한 값이 남아 있다.
버튼을 눌러도 data는 지워지지 않았기 때문에, useSuspenseQuery는 에러를 throw하지 않고, Error Boundary가 동작하지 않는 것이다.
이 문제는 Discussion #10044에서 제기되었고, PR #10072를 통해 수정되어 @tanstack/[email protected]에 반영되었다.
수정된 코드는 간단하다:
activeQueryVal.setState({
data: undefined, // 추가된 부분
status: 'error',
error,
fetchMeta: {
...activeQueryVal.state.fetchMeta,
__previousQueryOptions,
} as any,
})
이제 "Trigger Error"를 누르면 data가 undefined로 설정되기 때문에, useSuspenseQuery가 에러를 정상적으로 throw하고 Error Boundary가 동작한다.
| 구분 | 수정 전 | 수정 후 |
|---|---|---|
| Trigger Error 시 data 상태 | 기존 데이터 유지 | undefined로 초기화 |
| Error Boundary 동작 | ❌ 동작 안 함 | ✅ 정상 동작 |
| 적용 버전 | ~5.92.x | 5.93.0~ |
라이브러리 내부 동작을 이해하지 못하면 이런 함정에 빠지기 쉽다. useSuspenseQuery가 에러를 throw하려면 단순히 status: 'error'가 아니라 data: undefined도 함께 충족되어야 한다는 점을 기억하자.
현재는 @tanstack/[email protected] 이상으로 업그레이드하면 Trigger Error 버튼 하나로 Error Boundary 테스트가 가능하다.