-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FE] react-query에 맞는 error handling 적용 #415
Conversation
TODO: 테스트 코드 역할 위임
주석처리한다고 테스트가 넘어가지는게 아니었군요... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR 내용만 읽어도 복잡하다는게 느껴지네요..
어떻게 이걸 해낸거지 ㄷㄷ
고생 너무 많았어요 토다리!
터지는 test로 인해 merge가 불가능하니, 해당 PR은 후에 merge해도 괜찮을 것 같네요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
정말 어려운 작업이었을텐데 너무 고생했어요 웨디 토다리~
</UnhandledErrorBoundary> | ||
</QueryClientProvider> | ||
</QueryClientBoundary> | ||
</ErrorCatcher> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
컴포넌트 명 너무 좋다! 에러를 캐치해주는 녀석
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
캣쮜
queryCache: new QueryCache({ | ||
onError: (error: Error) => { | ||
updateAppError(error); | ||
}, | ||
}), | ||
mutationCache: new MutationCache({ | ||
onError: (error: Error) => { | ||
updateAppError(error); | ||
}, | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
너무 좋아요! 기존의 에러 처리방식보다 확실히 더 좋아진 것 같아요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
useFetch가 useQuery, useMutation으로 대체되며 더 신경쓸 필요가 적어진 것 같아요 ㅎ.ㅎㅎㅎ
@@ -2,7 +2,7 @@ import {useState} from 'react'; | |||
|
|||
import validateEventName from '@utils/validate/validateEventName'; | |||
|
|||
const useSetEventName = () => { | |||
const useSetEventNamePage = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요거는 페이지에서 사용하는 훅이라서 Page를 붙인걸까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
어... 이건 뭔지 모르겠습니다........... 토다리에게 패스...
// 토스트 메시지가 나타나는지 확인 | ||
expect(screen.getByText(TOAST_CONFIG.message)).toBeInTheDocument(); | ||
|
||
// 1초 후에 토스트 메시지가 사라지는지 확인 | ||
await waitFor( | ||
() => { | ||
expect(screen.queryByText(TOAST_CONFIG.message)).not.toBeInTheDocument(); | ||
}, | ||
{timeout: 3100}, | ||
); // 타임아웃을 3100ms로 설정하여 정확히 3초 후 확인 | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
주석을 잘 적어줘서 테스트 이해하기 너무 좋은 것 같아요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GPT는 신인가,..
<Title title="알 수 없는 오류입니다." description="오류가 난 상황에 대해 {메일}로 연락주시면 소정의 상품을..." /> | ||
<Title | ||
title="알 수 없는 오류입니다." | ||
description="오류가 난 상황에 대해 [email protected] 로 연락주시면 소정의 상품을 드립니다." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아 우리 메일로 바꿔놨군요! 디테일 대박
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵넵 내일이 데모라..!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
웨디 PR 내용으로 후대댁 이해를 박았습니댜!
코드..뭐.. 잘 해줬겠죠! 화이팅!
issue
(여기부턴 웨디가 씀)
구현 목적
구현 내용
✅ 테스트 커버리지
시간이 많이 없으므로 테스트 커버리지는 많이 신경쓰지 못했습니다.
✅ 핸들링 불가능한 에러가 발생한 경우 에러 바운더리를 뜨도록 하기
기존의 상태는 핸들링 불가능한 에러가 발생해도 에러 바운더리가 뜨지 않고 있었습니다.
리액트 쿼리를 도입하기 전에 이 에러 핸들링 방식을 개선하려고 생각했었는데요. 그 방식은 useError역할을 하는 전역 상태가 중간에 없어도 정상적으로 에러 바운더리가 뜨도록 하는 방식입니다.
다만 다시 생각해보니 컴포넌트의 렌더링 과정이거나 상태를 업데이트해 강제로 리렌더링을 발생시키지 않는다면 에러 바운더리를 트리거할 수 없었습니다.
따라서 useError역할을 하는 에러 스토어를 그대로 유지하는 결정을 내리게 되었습니다. 그리고 강제로 리렌더링을 유발하는 것은
ErrorCatcher
라는 Router를 감싸는 컴포넌트가 담당하게 됐습니다. 이ErrorCatcher
에서 에러 스토어의 에러를 useEffect로 구독한 채로 리렌더링을 유발해 에러 바운더리와 토스트를 뜨도록 했습니다. (사실 정확하게는 리렌더링이 아니지만 최대한 빨리 이해할 수 있도록 설명하려고 했습니다. 양해바랍니다.)다만 기존의 방식처럼 useToast에서 error 상태를 구독하고 있는 결합도 높은 코드가 아닌, 에러를 잡은 쪽에서 토스트를 부르는 방식입니다. 따라서useToast에는 이제 에러에 관련된 코드는 없고, 토스트 기능 자체 로직만 남게 되었습니다.
그리고 던져진 에러를 잡기 위해
UnhandledErrorBoundary
를 다시 사용하게 되었습니다.시간 상 설계에 많은 공을 들이지 못해 일단 최소한의 에러 핸들링 정도만 구현해놓은 상태입니다.
(여기까지 웨디 끝)
구현 목적
고려 사항
as-is
ErrorProvider
에서errorInfo
가 변경되면 예상했던 에러인지 판별하여 예상하지 못한 에러라면UnhandledErrorBoundary
가 이를 잡도록 error를 throw합니다.ErrorProvider
를 구독하던ToastProvider
가 toast를 띄웁니다.to-be
QueryClientBoundary
에서 queryFunction의 error를 일괄적으로 처리합니다(상태관리, throw 등).AppErrorBoundary
에서 예상했던 오류라면,showToast
를 이용해 toast를 띄웁니다.FallbackComponent
를 출력합니다.TroubleShooting
QueryClientBoundary
에서 error를 throw하는 방식QueryClientBoundary
에서 error를 throw 하면AppErrorBoundary
에서<ErrorPage>
를 출력하는 방향을 고려했습니다.ErrorBoundary
는 렌더링 중 발생한 에러, 생명주기 메서드에서 발생한 에러, 자식 컴포넌트의 생성자에서 발생한 에러를 잡는데, 비동기 코드나 이벤트 핸들러의 에러를 잡을 수 없습니다.QueryClientBoundary
는QueryClient
를 생성하고,QueryClientProvider
를 통해 React 컴포넌트 트리 내에서 사용할 수 있도록 합니다.QueryClient
내부의queryCache
나mutationCache
에서 발생하는 에러가 React의 렌더링 트리에서 직접 발생하지 않기 때문에ErrorBoundary
가 이를 감지할 수 없습니다.구현 내용
onError
시appErrorStore
에 error 상태를 업데이트합니다.ErrorBoundary
는 error가 변경될 경우,showToast
를 이용하여 toast를 띄워줍니다.onError
에서 발생한 error가 아닐 땐,fallbackComponent
에서 이를 처리합니다.fallbackComponent
는�예상한 error일 때, toast를 띄워주고, 아닌 경우 fallbackComponent를 보여줍니다.참고사항
사용되지 않는 test코드들에 대해서 test를 옮기려고 했는데 생각보다 쉽지 않았습니다...
해당 케이스들이 대부분 queryFunction들에 대한 함수가 될 것 같아서, 런칭데이를 앞두고
바쁜 일들 먼저 마무리하고 queryFunction들에 대한 테스트를 작성해보도록 하겠습니다...
시켜주는 일들 위주로 하면서, landingPage, 낙관적업데이트 부분들을 해볼까 생각중이에요